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
851 map : function(fun /*, thisp*/)
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);
872 if (!Array.prototype.map)
877 * Ext JS Library 1.1.1
878 * Copyright(c) 2006-2007, Ext JS, LLC.
880 * Originally Released Under LGPL - original licence link has changed is not relivant.
883 * <script type="text/javascript">
889 * The date parsing and format syntax is a subset of
890 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
891 * supported will provide results equivalent to their PHP versions.
893 * Following is the list of all currently supported formats:
896 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
898 Format Output Description
899 ------ ---------- --------------------------------------------------------------
900 d 10 Day of the month, 2 digits with leading zeros
901 D Wed A textual representation of a day, three letters
902 j 10 Day of the month without leading zeros
903 l Wednesday A full textual representation of the day of the week
904 S th English ordinal day of month suffix, 2 chars (use with j)
905 w 3 Numeric representation of the day of the week
906 z 9 The julian date, or day of the year (0-365)
907 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
908 F January A full textual representation of the month
909 m 01 Numeric representation of a month, with leading zeros
910 M Jan Month name abbreviation, three letters
911 n 1 Numeric representation of a month, without leading zeros
912 t 31 Number of days in the given month
913 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
914 Y 2007 A full numeric representation of a year, 4 digits
915 y 07 A two digit representation of a year
916 a pm Lowercase Ante meridiem and Post meridiem
917 A PM Uppercase Ante meridiem and Post meridiem
918 g 3 12-hour format of an hour without leading zeros
919 G 15 24-hour format of an hour without leading zeros
920 h 03 12-hour format of an hour with leading zeros
921 H 15 24-hour format of an hour with leading zeros
922 i 05 Minutes with leading zeros
923 s 01 Seconds, with leading zeros
924 O -0600 Difference to Greenwich time (GMT) in hours
925 T CST Timezone setting of the machine running the code
926 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
929 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
931 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
932 document.write(dt.format('Y-m-d')); //2007-01-10
933 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
934 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
937 * Here are some standard date/time patterns that you might find helpful. They
938 * are not part of the source of Date.js, but to use them you can simply copy this
939 * block of code into any script that is included after Date.js and they will also become
940 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
943 ISO8601Long:"Y-m-d H:i:s",
944 ISO8601Short:"Y-m-d",
946 LongDate: "l, F d, Y",
947 FullDateTime: "l, F d, Y g:i:s A",
951 SortableDateTime: "Y-m-d\\TH:i:s",
952 UniversalSortableDateTime: "Y-m-d H:i:sO",
960 document.write(dt.format(Date.patterns.ShortDate));
965 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
966 * They generate precompiled functions from date formats instead of parsing and
967 * processing the pattern every time you format a date. These functions are available
968 * on every Date object (any javascript function).
970 * The original article and download are here:
971 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
978 Returns the number of milliseconds between this date and date
979 @param {Date} date (optional) Defaults to now
980 @return {Number} The diff in milliseconds
981 @member Date getElapsed
983 Date.prototype.getElapsed = function(date) {
984 return Math.abs((date || new Date()).getTime()-this.getTime());
986 // was in date file..
990 Date.parseFunctions = {count:0};
992 Date.parseRegexes = [];
994 Date.formatFunctions = {count:0};
997 Date.prototype.dateFormat = function(format) {
998 if (Date.formatFunctions[format] == null) {
999 Date.createNewFormat(format);
1001 var func = Date.formatFunctions[format];
1002 return this[func]();
1007 * Formats a date given the supplied format string
1008 * @param {String} format The format string
1009 * @return {String} The formatted date
1012 Date.prototype.format = Date.prototype.dateFormat;
1015 Date.createNewFormat = function(format) {
1016 var funcName = "format" + Date.formatFunctions.count++;
1017 Date.formatFunctions[format] = funcName;
1018 var code = "Date.prototype." + funcName + " = function(){return ";
1019 var special = false;
1021 for (var i = 0; i < format.length; ++i) {
1022 ch = format.charAt(i);
1023 if (!special && ch == "\\") {
1028 code += "'" + String.escape(ch) + "' + ";
1031 code += Date.getFormatCode(ch);
1034 /** eval:var:zzzzzzzzzzzzz */
1035 eval(code.substring(0, code.length - 3) + ";}");
1039 Date.getFormatCode = function(character) {
1040 switch (character) {
1042 return "String.leftPad(this.getDate(), 2, '0') + ";
1044 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1046 return "this.getDate() + ";
1048 return "Date.dayNames[this.getDay()] + ";
1050 return "this.getSuffix() + ";
1052 return "this.getDay() + ";
1054 return "this.getDayOfYear() + ";
1056 return "this.getWeekOfYear() + ";
1058 return "Date.monthNames[this.getMonth()] + ";
1060 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1062 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1064 return "(this.getMonth() + 1) + ";
1066 return "this.getDaysInMonth() + ";
1068 return "(this.isLeapYear() ? 1 : 0) + ";
1070 return "this.getFullYear() + ";
1072 return "('' + this.getFullYear()).substring(2, 4) + ";
1074 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1076 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1078 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1080 return "this.getHours() + ";
1082 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1084 return "String.leftPad(this.getHours(), 2, '0') + ";
1086 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1088 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1090 return "this.getGMTOffset() + ";
1092 return "this.getTimezone() + ";
1094 return "(this.getTimezoneOffset() * -60) + ";
1096 return "'" + String.escape(character) + "' + ";
1101 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1102 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1103 * the date format that is not specified will default to the current date value for that part. Time parts can also
1104 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1105 * string or the parse operation will fail.
1108 //dt = Fri May 25 2007 (current date)
1109 var dt = new Date();
1111 //dt = Thu May 25 2006 (today's month/day in 2006)
1112 dt = Date.parseDate("2006", "Y");
1114 //dt = Sun Jan 15 2006 (all date parts specified)
1115 dt = Date.parseDate("2006-1-15", "Y-m-d");
1117 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1118 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1120 * @param {String} input The unparsed date as a string
1121 * @param {String} format The format the date is in
1122 * @return {Date} The parsed date
1125 Date.parseDate = function(input, format) {
1126 if (Date.parseFunctions[format] == null) {
1127 Date.createParser(format);
1129 var func = Date.parseFunctions[format];
1130 return Date[func](input);
1135 Date.createParser = function(format) {
1136 var funcName = "parse" + Date.parseFunctions.count++;
1137 var regexNum = Date.parseRegexes.length;
1138 var currentGroup = 1;
1139 Date.parseFunctions[format] = funcName;
1141 var code = "Date." + funcName + " = function(input){\n"
1142 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1143 + "var d = new Date();\n"
1144 + "y = d.getFullYear();\n"
1145 + "m = d.getMonth();\n"
1146 + "d = d.getDate();\n"
1147 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1148 + "if (results && results.length > 0) {";
1151 var special = false;
1153 for (var i = 0; i < format.length; ++i) {
1154 ch = format.charAt(i);
1155 if (!special && ch == "\\") {
1160 regex += String.escape(ch);
1163 var obj = Date.formatCodeToRegex(ch, currentGroup);
1164 currentGroup += obj.g;
1166 if (obj.g && obj.c) {
1172 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1173 + "{v = new Date(y, m, d, h, i, s);}\n"
1174 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1175 + "{v = new Date(y, m, d, h, i);}\n"
1176 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1177 + "{v = new Date(y, m, d, h);}\n"
1178 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1179 + "{v = new Date(y, m, d);}\n"
1180 + "else if (y >= 0 && m >= 0)\n"
1181 + "{v = new Date(y, m);}\n"
1182 + "else if (y >= 0)\n"
1183 + "{v = new Date(y);}\n"
1184 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1185 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1186 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1189 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1190 /** eval:var:zzzzzzzzzzzzz */
1195 Date.formatCodeToRegex = function(character, currentGroup) {
1196 switch (character) {
1200 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1203 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1204 s:"(\\d{1,2})"}; // day of month without leading zeroes
1207 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1208 s:"(\\d{2})"}; // day of month with leading zeroes
1212 s:"(?:" + Date.dayNames.join("|") + ")"};
1216 s:"(?:st|nd|rd|th)"};
1231 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1232 s:"(" + Date.monthNames.join("|") + ")"};
1235 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1236 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1239 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1240 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1243 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1244 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1255 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1259 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1260 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1264 c:"if (results[" + currentGroup + "] == 'am') {\n"
1265 + "if (h == 12) { h = 0; }\n"
1266 + "} else { if (h < 12) { h += 12; }}",
1270 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1271 + "if (h == 12) { h = 0; }\n"
1272 + "} else { if (h < 12) { h += 12; }}",
1277 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1278 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1282 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1283 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1286 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1290 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1295 "o = results[", currentGroup, "];\n",
1296 "var sn = o.substring(0,1);\n", // get + / - sign
1297 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1298 "var mn = o.substring(3,5) % 60;\n", // get minutes
1299 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1300 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1306 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1309 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1310 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1311 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1315 s:String.escape(character)};
1320 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1321 * @return {String} The abbreviated timezone name (e.g. 'CST')
1323 Date.prototype.getTimezone = function() {
1324 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1328 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1329 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1331 Date.prototype.getGMTOffset = function() {
1332 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1333 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1334 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1338 * Get the numeric day number of the year, adjusted for leap year.
1339 * @return {Number} 0 through 364 (365 in leap years)
1341 Date.prototype.getDayOfYear = function() {
1343 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1344 for (var i = 0; i < this.getMonth(); ++i) {
1345 num += Date.daysInMonth[i];
1347 return num + this.getDate() - 1;
1351 * Get the string representation of the numeric week number of the year
1352 * (equivalent to the format specifier 'W').
1353 * @return {String} '00' through '52'
1355 Date.prototype.getWeekOfYear = function() {
1356 // Skip to Thursday of this week
1357 var now = this.getDayOfYear() + (4 - this.getDay());
1358 // Find the first Thursday of the year
1359 var jan1 = new Date(this.getFullYear(), 0, 1);
1360 var then = (7 - jan1.getDay() + 4);
1361 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1365 * Whether or not the current date is in a leap year.
1366 * @return {Boolean} True if the current date is in a leap year, else false
1368 Date.prototype.isLeapYear = function() {
1369 var year = this.getFullYear();
1370 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1374 * Get the first day of the current month, adjusted for leap year. The returned value
1375 * is the numeric day index within the week (0-6) which can be used in conjunction with
1376 * the {@link #monthNames} array to retrieve the textual day name.
1379 var dt = new Date('1/10/2007');
1380 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1382 * @return {Number} The day number (0-6)
1384 Date.prototype.getFirstDayOfMonth = function() {
1385 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1386 return (day < 0) ? (day + 7) : day;
1390 * Get the last day of the current month, adjusted for leap year. The returned value
1391 * is the numeric day index within the week (0-6) which can be used in conjunction with
1392 * the {@link #monthNames} array to retrieve the textual day name.
1395 var dt = new Date('1/10/2007');
1396 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1398 * @return {Number} The day number (0-6)
1400 Date.prototype.getLastDayOfMonth = function() {
1401 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1402 return (day < 0) ? (day + 7) : day;
1407 * Get the first date of this date's month
1410 Date.prototype.getFirstDateOfMonth = function() {
1411 return new Date(this.getFullYear(), this.getMonth(), 1);
1415 * Get the last date of this date's month
1418 Date.prototype.getLastDateOfMonth = function() {
1419 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1422 * Get the number of days in the current month, adjusted for leap year.
1423 * @return {Number} The number of days in the month
1425 Date.prototype.getDaysInMonth = function() {
1426 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1427 return Date.daysInMonth[this.getMonth()];
1431 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1432 * @return {String} 'st, 'nd', 'rd' or 'th'
1434 Date.prototype.getSuffix = function() {
1435 switch (this.getDate()) {
1452 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1455 * An array of textual month names.
1456 * Override these values for international dates, for example...
1457 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1476 * An array of textual day names.
1477 * Override these values for international dates, for example...
1478 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1494 Date.monthNumbers = {
1509 * Creates and returns a new Date instance with the exact same date value as the called instance.
1510 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1511 * variable will also be changed. When the intention is to create a new variable that will not
1512 * modify the original instance, you should create a clone.
1514 * Example of correctly cloning a date:
1517 var orig = new Date('10/1/2006');
1520 document.write(orig); //returns 'Thu Oct 05 2006'!
1523 var orig = new Date('10/1/2006');
1524 var copy = orig.clone();
1526 document.write(orig); //returns 'Thu Oct 01 2006'
1528 * @return {Date} The new Date instance
1530 Date.prototype.clone = function() {
1531 return new Date(this.getTime());
1535 * Clears any time information from this date
1536 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1537 @return {Date} this or the clone
1539 Date.prototype.clearTime = function(clone){
1541 return this.clone().clearTime();
1546 this.setMilliseconds(0);
1551 // safari setMonth is broken
1553 Date.brokenSetMonth = Date.prototype.setMonth;
1554 Date.prototype.setMonth = function(num){
1556 var n = Math.ceil(-num);
1557 var back_year = Math.ceil(n/12);
1558 var month = (n % 12) ? 12 - n % 12 : 0 ;
1559 this.setFullYear(this.getFullYear() - back_year);
1560 return Date.brokenSetMonth.call(this, month);
1562 return Date.brokenSetMonth.apply(this, arguments);
1567 /** Date interval constant
1571 /** Date interval constant
1575 /** Date interval constant
1579 /** Date interval constant
1583 /** Date interval constant
1587 /** Date interval constant
1591 /** Date interval constant
1597 * Provides a convenient method of performing basic date arithmetic. This method
1598 * does not modify the Date instance being called - it creates and returns
1599 * a new Date instance containing the resulting date value.
1604 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1605 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1607 //Negative values will subtract correctly:
1608 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1609 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1611 //You can even chain several calls together in one line!
1612 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1613 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1616 * @param {String} interval A valid date interval enum value
1617 * @param {Number} value The amount to add to the current date
1618 * @return {Date} The new Date instance
1620 Date.prototype.add = function(interval, value){
1621 var d = this.clone();
1622 if (!interval || value === 0) return d;
1623 switch(interval.toLowerCase()){
1625 d.setMilliseconds(this.getMilliseconds() + value);
1628 d.setSeconds(this.getSeconds() + value);
1631 d.setMinutes(this.getMinutes() + value);
1634 d.setHours(this.getHours() + value);
1637 d.setDate(this.getDate() + value);
1640 var day = this.getDate();
1642 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1645 d.setMonth(this.getMonth() + value);
1648 d.setFullYear(this.getFullYear() + value);
1654 * Ext JS Library 1.1.1
1655 * Copyright(c) 2006-2007, Ext JS, LLC.
1657 * Originally Released Under LGPL - original licence link has changed is not relivant.
1660 * <script type="text/javascript">
1664 getViewWidth : function(full) {
1665 return full ? this.getDocumentWidth() : this.getViewportWidth();
1668 getViewHeight : function(full) {
1669 return full ? this.getDocumentHeight() : this.getViewportHeight();
1672 getDocumentHeight: function() {
1673 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1674 return Math.max(scrollHeight, this.getViewportHeight());
1677 getDocumentWidth: function() {
1678 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1679 return Math.max(scrollWidth, this.getViewportWidth());
1682 getViewportHeight: function() {
1683 var height = self.innerHeight;
1684 var mode = document.compatMode;
1686 if ((mode || Roo.isIE) && !Roo.isOpera) {
1687 height = (mode == "CSS1Compat") ?
1688 document.documentElement.clientHeight :
1689 document.body.clientHeight;
1695 getViewportWidth: function() {
1696 var width = self.innerWidth;
1697 var mode = document.compatMode;
1699 if (mode || Roo.isIE) {
1700 width = (mode == "CSS1Compat") ?
1701 document.documentElement.clientWidth :
1702 document.body.clientWidth;
1707 isAncestor : function(p, c) {
1714 if (p.contains && !Roo.isSafari) {
1715 return p.contains(c);
1716 } else if (p.compareDocumentPosition) {
1717 return !!(p.compareDocumentPosition(c) & 16);
1719 var parent = c.parentNode;
1724 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1727 parent = parent.parentNode;
1733 getRegion : function(el) {
1734 return Roo.lib.Region.getRegion(el);
1737 getY : function(el) {
1738 return this.getXY(el)[1];
1741 getX : function(el) {
1742 return this.getXY(el)[0];
1745 getXY : function(el) {
1746 var p, pe, b, scroll, bd = document.body;
1747 el = Roo.getDom(el);
1748 var fly = Roo.lib.AnimBase.fly;
1749 if (el.getBoundingClientRect) {
1750 b = el.getBoundingClientRect();
1751 scroll = fly(document).getScroll();
1752 return [b.left + scroll.left, b.top + scroll.top];
1758 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1765 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1772 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1773 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1780 if (p != el && pe.getStyle('overflow') != 'visible') {
1788 if (Roo.isSafari && hasAbsolute) {
1793 if (Roo.isGecko && !hasAbsolute) {
1795 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1796 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1800 while (p && p != bd) {
1801 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1813 setXY : function(el, xy) {
1814 el = Roo.fly(el, '_setXY');
1816 var pts = el.translatePoints(xy);
1817 if (xy[0] !== false) {
1818 el.dom.style.left = pts.left + "px";
1820 if (xy[1] !== false) {
1821 el.dom.style.top = pts.top + "px";
1825 setX : function(el, x) {
1826 this.setXY(el, [x, false]);
1829 setY : function(el, y) {
1830 this.setXY(el, [false, y]);
1834 * Portions of this file are based on pieces of Yahoo User Interface Library
1835 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1836 * YUI licensed under the BSD License:
1837 * http://developer.yahoo.net/yui/license.txt
1838 * <script type="text/javascript">
1842 Roo.lib.Event = function() {
1843 var loadComplete = false;
1845 var unloadListeners = [];
1847 var onAvailStack = [];
1849 var lastError = null;
1862 startInterval: function() {
1863 if (!this._interval) {
1865 var callback = function() {
1866 self._tryPreloadAttach();
1868 this._interval = setInterval(callback, this.POLL_INTERVAL);
1873 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1874 onAvailStack.push({ id: p_id,
1877 override: p_override,
1878 checkReady: false });
1880 retryCount = this.POLL_RETRYS;
1881 this.startInterval();
1885 addListener: function(el, eventName, fn) {
1886 el = Roo.getDom(el);
1891 if ("unload" == eventName) {
1892 unloadListeners[unloadListeners.length] =
1893 [el, eventName, fn];
1897 var wrappedFn = function(e) {
1898 return fn(Roo.lib.Event.getEvent(e));
1901 var li = [el, eventName, fn, wrappedFn];
1903 var index = listeners.length;
1904 listeners[index] = li;
1906 this.doAdd(el, eventName, wrappedFn, false);
1912 removeListener: function(el, eventName, fn) {
1915 el = Roo.getDom(el);
1918 return this.purgeElement(el, false, eventName);
1922 if ("unload" == eventName) {
1924 for (i = 0,len = unloadListeners.length; i < len; i++) {
1925 var li = unloadListeners[i];
1928 li[1] == eventName &&
1930 unloadListeners.splice(i, 1);
1938 var cacheItem = null;
1941 var index = arguments[3];
1943 if ("undefined" == typeof index) {
1944 index = this._getCacheIndex(el, eventName, fn);
1948 cacheItem = listeners[index];
1951 if (!el || !cacheItem) {
1955 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1957 delete listeners[index][this.WFN];
1958 delete listeners[index][this.FN];
1959 listeners.splice(index, 1);
1966 getTarget: function(ev, resolveTextNode) {
1967 ev = ev.browserEvent || ev;
1968 var t = ev.target || ev.srcElement;
1969 return this.resolveTextNode(t);
1973 resolveTextNode: function(node) {
1974 if (Roo.isSafari && node && 3 == node.nodeType) {
1975 return node.parentNode;
1982 getPageX: function(ev) {
1983 ev = ev.browserEvent || ev;
1985 if (!x && 0 !== x) {
1986 x = ev.clientX || 0;
1989 x += this.getScroll()[1];
1997 getPageY: function(ev) {
1998 ev = ev.browserEvent || ev;
2000 if (!y && 0 !== y) {
2001 y = ev.clientY || 0;
2004 y += this.getScroll()[0];
2013 getXY: function(ev) {
2014 ev = ev.browserEvent || ev;
2015 return [this.getPageX(ev), this.getPageY(ev)];
2019 getRelatedTarget: function(ev) {
2020 ev = ev.browserEvent || ev;
2021 var t = ev.relatedTarget;
2023 if (ev.type == "mouseout") {
2025 } else if (ev.type == "mouseover") {
2030 return this.resolveTextNode(t);
2034 getTime: function(ev) {
2035 ev = ev.browserEvent || ev;
2037 var t = new Date().getTime();
2041 this.lastError = ex;
2050 stopEvent: function(ev) {
2051 this.stopPropagation(ev);
2052 this.preventDefault(ev);
2056 stopPropagation: function(ev) {
2057 ev = ev.browserEvent || ev;
2058 if (ev.stopPropagation) {
2059 ev.stopPropagation();
2061 ev.cancelBubble = true;
2066 preventDefault: function(ev) {
2067 ev = ev.browserEvent || ev;
2068 if(ev.preventDefault) {
2069 ev.preventDefault();
2071 ev.returnValue = false;
2076 getEvent: function(e) {
2077 var ev = e || window.event;
2079 var c = this.getEvent.caller;
2081 ev = c.arguments[0];
2082 if (ev && Event == ev.constructor) {
2092 getCharCode: function(ev) {
2093 ev = ev.browserEvent || ev;
2094 return ev.charCode || ev.keyCode || 0;
2098 _getCacheIndex: function(el, eventName, fn) {
2099 for (var i = 0,len = listeners.length; i < len; ++i) {
2100 var li = listeners[i];
2102 li[this.FN] == fn &&
2103 li[this.EL] == el &&
2104 li[this.TYPE] == eventName) {
2116 getEl: function(id) {
2117 return document.getElementById(id);
2121 clearCache: function() {
2125 _load: function(e) {
2126 loadComplete = true;
2127 var EU = Roo.lib.Event;
2131 EU.doRemove(window, "load", EU._load);
2136 _tryPreloadAttach: function() {
2145 var tryAgain = !loadComplete;
2147 tryAgain = (retryCount > 0);
2152 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2153 var item = onAvailStack[i];
2155 var el = this.getEl(item.id);
2158 if (!item.checkReady ||
2161 (document && document.body)) {
2164 if (item.override) {
2165 if (item.override === true) {
2168 scope = item.override;
2171 item.fn.call(scope, item.obj);
2172 onAvailStack[i] = null;
2175 notAvail.push(item);
2180 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2184 this.startInterval();
2186 clearInterval(this._interval);
2187 this._interval = null;
2190 this.locked = false;
2197 purgeElement: function(el, recurse, eventName) {
2198 var elListeners = this.getListeners(el, eventName);
2200 for (var i = 0,len = elListeners.length; i < len; ++i) {
2201 var l = elListeners[i];
2202 this.removeListener(el, l.type, l.fn);
2206 if (recurse && el && el.childNodes) {
2207 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2208 this.purgeElement(el.childNodes[i], recurse, eventName);
2214 getListeners: function(el, eventName) {
2215 var results = [], searchLists;
2217 searchLists = [listeners, unloadListeners];
2218 } else if (eventName == "unload") {
2219 searchLists = [unloadListeners];
2221 searchLists = [listeners];
2224 for (var j = 0; j < searchLists.length; ++j) {
2225 var searchList = searchLists[j];
2226 if (searchList && searchList.length > 0) {
2227 for (var i = 0,len = searchList.length; i < len; ++i) {
2228 var l = searchList[i];
2229 if (l && l[this.EL] === el &&
2230 (!eventName || eventName === l[this.TYPE])) {
2235 adjust: l[this.ADJ_SCOPE],
2243 return (results.length) ? results : null;
2247 _unload: function(e) {
2249 var EU = Roo.lib.Event, i, j, l, len, index;
2251 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2252 l = unloadListeners[i];
2255 if (l[EU.ADJ_SCOPE]) {
2256 if (l[EU.ADJ_SCOPE] === true) {
2259 scope = l[EU.ADJ_SCOPE];
2262 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2263 unloadListeners[i] = null;
2269 unloadListeners = null;
2271 if (listeners && listeners.length > 0) {
2272 j = listeners.length;
2275 l = listeners[index];
2277 EU.removeListener(l[EU.EL], l[EU.TYPE],
2287 EU.doRemove(window, "unload", EU._unload);
2292 getScroll: function() {
2293 var dd = document.documentElement, db = document.body;
2294 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2295 return [dd.scrollTop, dd.scrollLeft];
2297 return [db.scrollTop, db.scrollLeft];
2304 doAdd: function () {
2305 if (window.addEventListener) {
2306 return function(el, eventName, fn, capture) {
2307 el.addEventListener(eventName, fn, (capture));
2309 } else if (window.attachEvent) {
2310 return function(el, eventName, fn, capture) {
2311 el.attachEvent("on" + eventName, fn);
2320 doRemove: function() {
2321 if (window.removeEventListener) {
2322 return function (el, eventName, fn, capture) {
2323 el.removeEventListener(eventName, fn, (capture));
2325 } else if (window.detachEvent) {
2326 return function (el, eventName, fn) {
2327 el.detachEvent("on" + eventName, fn);
2339 var E = Roo.lib.Event;
2340 E.on = E.addListener;
2341 E.un = E.removeListener;
2343 if (document && document.body) {
2346 E.doAdd(window, "load", E._load);
2348 E.doAdd(window, "unload", E._unload);
2349 E._tryPreloadAttach();
2353 * Portions of this file are based on pieces of Yahoo User Interface Library
2354 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2355 * YUI licensed under the BSD License:
2356 * http://developer.yahoo.net/yui/license.txt
2357 * <script type="text/javascript">
2364 request : function(method, uri, cb, data, options) {
2366 var hs = options.headers;
2369 if(hs.hasOwnProperty(h)){
2370 this.initHeader(h, hs[h], false);
2374 if(options.xmlData){
2375 this.initHeader('Content-Type', 'text/xml', false);
2377 data = options.xmlData;
2381 return this.asyncRequest(method, uri, cb, data);
2384 serializeForm : function(form) {
2385 if(typeof form == 'string') {
2386 form = (document.getElementById(form) || document.forms[form]);
2389 var el, name, val, disabled, data = '', hasSubmit = false;
2390 for (var i = 0; i < form.elements.length; i++) {
2391 el = form.elements[i];
2392 disabled = form.elements[i].disabled;
2393 name = form.elements[i].name;
2394 val = form.elements[i].value;
2396 if (!disabled && name){
2400 case 'select-multiple':
2401 for (var j = 0; j < el.options.length; j++) {
2402 if (el.options[j].selected) {
2404 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2407 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2415 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2428 if(hasSubmit == false) {
2429 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2434 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2439 data = data.substr(0, data.length - 1);
2447 useDefaultHeader:true,
2449 defaultPostHeader:'application/x-www-form-urlencoded',
2451 useDefaultXhrHeader:true,
2453 defaultXhrHeader:'XMLHttpRequest',
2455 hasDefaultHeaders:true,
2467 setProgId:function(id)
2469 this.activeX.unshift(id);
2472 setDefaultPostHeader:function(b)
2474 this.useDefaultHeader = b;
2477 setDefaultXhrHeader:function(b)
2479 this.useDefaultXhrHeader = b;
2482 setPollingInterval:function(i)
2484 if (typeof i == 'number' && isFinite(i)) {
2485 this.pollInterval = i;
2489 createXhrObject:function(transactionId)
2495 http = new XMLHttpRequest();
2497 obj = { conn:http, tId:transactionId };
2501 for (var i = 0; i < this.activeX.length; ++i) {
2505 http = new ActiveXObject(this.activeX[i]);
2507 obj = { conn:http, tId:transactionId };
2520 getConnectionObject:function()
2523 var tId = this.transactionId;
2527 o = this.createXhrObject(tId);
2529 this.transactionId++;
2540 asyncRequest:function(method, uri, callback, postData)
2542 var o = this.getConnectionObject();
2548 o.conn.open(method, uri, true);
2550 if (this.useDefaultXhrHeader) {
2551 if (!this.defaultHeaders['X-Requested-With']) {
2552 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2556 if(postData && this.useDefaultHeader){
2557 this.initHeader('Content-Type', this.defaultPostHeader);
2560 if (this.hasDefaultHeaders || this.hasHeaders) {
2564 this.handleReadyState(o, callback);
2565 o.conn.send(postData || null);
2571 handleReadyState:function(o, callback)
2575 if (callback && callback.timeout) {
2576 this.timeout[o.tId] = window.setTimeout(function() {
2577 oConn.abort(o, callback, true);
2578 }, callback.timeout);
2581 this.poll[o.tId] = window.setInterval(
2583 if (o.conn && o.conn.readyState == 4) {
2584 window.clearInterval(oConn.poll[o.tId]);
2585 delete oConn.poll[o.tId];
2587 if(callback && callback.timeout) {
2588 window.clearTimeout(oConn.timeout[o.tId]);
2589 delete oConn.timeout[o.tId];
2592 oConn.handleTransactionResponse(o, callback);
2595 , this.pollInterval);
2598 handleTransactionResponse:function(o, callback, isAbort)
2602 this.releaseObject(o);
2606 var httpStatus, responseObject;
2610 if (o.conn.status !== undefined && o.conn.status != 0) {
2611 httpStatus = o.conn.status;
2623 if (httpStatus >= 200 && httpStatus < 300) {
2624 responseObject = this.createResponseObject(o, callback.argument);
2625 if (callback.success) {
2626 if (!callback.scope) {
2627 callback.success(responseObject);
2632 callback.success.apply(callback.scope, [responseObject]);
2637 switch (httpStatus) {
2645 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2646 if (callback.failure) {
2647 if (!callback.scope) {
2648 callback.failure(responseObject);
2651 callback.failure.apply(callback.scope, [responseObject]);
2656 responseObject = this.createResponseObject(o, callback.argument);
2657 if (callback.failure) {
2658 if (!callback.scope) {
2659 callback.failure(responseObject);
2662 callback.failure.apply(callback.scope, [responseObject]);
2668 this.releaseObject(o);
2669 responseObject = null;
2672 createResponseObject:function(o, callbackArg)
2679 var headerStr = o.conn.getAllResponseHeaders();
2680 var header = headerStr.split('\n');
2681 for (var i = 0; i < header.length; i++) {
2682 var delimitPos = header[i].indexOf(':');
2683 if (delimitPos != -1) {
2684 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2692 obj.status = o.conn.status;
2693 obj.statusText = o.conn.statusText;
2694 obj.getResponseHeader = headerObj;
2695 obj.getAllResponseHeaders = headerStr;
2696 obj.responseText = o.conn.responseText;
2697 obj.responseXML = o.conn.responseXML;
2699 if (typeof callbackArg !== undefined) {
2700 obj.argument = callbackArg;
2706 createExceptionObject:function(tId, callbackArg, isAbort)
2709 var COMM_ERROR = 'communication failure';
2710 var ABORT_CODE = -1;
2711 var ABORT_ERROR = 'transaction aborted';
2717 obj.status = ABORT_CODE;
2718 obj.statusText = ABORT_ERROR;
2721 obj.status = COMM_CODE;
2722 obj.statusText = COMM_ERROR;
2726 obj.argument = callbackArg;
2732 initHeader:function(label, value, isDefault)
2734 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2736 if (headerObj[label] === undefined) {
2737 headerObj[label] = value;
2742 headerObj[label] = value + "," + headerObj[label];
2746 this.hasDefaultHeaders = true;
2749 this.hasHeaders = true;
2754 setHeader:function(o)
2756 if (this.hasDefaultHeaders) {
2757 for (var prop in this.defaultHeaders) {
2758 if (this.defaultHeaders.hasOwnProperty(prop)) {
2759 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2764 if (this.hasHeaders) {
2765 for (var prop in this.headers) {
2766 if (this.headers.hasOwnProperty(prop)) {
2767 o.conn.setRequestHeader(prop, this.headers[prop]);
2771 this.hasHeaders = false;
2775 resetDefaultHeaders:function() {
2776 delete this.defaultHeaders;
2777 this.defaultHeaders = {};
2778 this.hasDefaultHeaders = false;
2781 abort:function(o, callback, isTimeout)
2783 if(this.isCallInProgress(o)) {
2785 window.clearInterval(this.poll[o.tId]);
2786 delete this.poll[o.tId];
2788 delete this.timeout[o.tId];
2791 this.handleTransactionResponse(o, callback, true);
2801 isCallInProgress:function(o)
2804 return o.conn.readyState != 4 && o.conn.readyState != 0;
2813 releaseObject:function(o)
2822 'MSXML2.XMLHTTP.3.0',
2830 * Portions of this file are based on pieces of Yahoo User Interface Library
2831 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2832 * YUI licensed under the BSD License:
2833 * http://developer.yahoo.net/yui/license.txt
2834 * <script type="text/javascript">
2838 Roo.lib.Region = function(t, r, b, l) {
2848 Roo.lib.Region.prototype = {
2849 contains : function(region) {
2850 return ( region.left >= this.left &&
2851 region.right <= this.right &&
2852 region.top >= this.top &&
2853 region.bottom <= this.bottom );
2857 getArea : function() {
2858 return ( (this.bottom - this.top) * (this.right - this.left) );
2861 intersect : function(region) {
2862 var t = Math.max(this.top, region.top);
2863 var r = Math.min(this.right, region.right);
2864 var b = Math.min(this.bottom, region.bottom);
2865 var l = Math.max(this.left, region.left);
2867 if (b >= t && r >= l) {
2868 return new Roo.lib.Region(t, r, b, l);
2873 union : function(region) {
2874 var t = Math.min(this.top, region.top);
2875 var r = Math.max(this.right, region.right);
2876 var b = Math.max(this.bottom, region.bottom);
2877 var l = Math.min(this.left, region.left);
2879 return new Roo.lib.Region(t, r, b, l);
2882 adjust : function(t, l, b, r) {
2891 Roo.lib.Region.getRegion = function(el) {
2892 var p = Roo.lib.Dom.getXY(el);
2895 var r = p[0] + el.offsetWidth;
2896 var b = p[1] + el.offsetHeight;
2899 return new Roo.lib.Region(t, r, b, l);
2902 * Portions of this file are based on pieces of Yahoo User Interface Library
2903 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2904 * YUI licensed under the BSD License:
2905 * http://developer.yahoo.net/yui/license.txt
2906 * <script type="text/javascript">
2909 //@@dep Roo.lib.Region
2912 Roo.lib.Point = function(x, y) {
2913 if (x instanceof Array) {
2917 this.x = this.right = this.left = this[0] = x;
2918 this.y = this.top = this.bottom = this[1] = y;
2921 Roo.lib.Point.prototype = new Roo.lib.Region();
2923 * Portions of this file are based on pieces of Yahoo User Interface Library
2924 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2925 * YUI licensed under the BSD License:
2926 * http://developer.yahoo.net/yui/license.txt
2927 * <script type="text/javascript">
2934 scroll : function(el, args, duration, easing, cb, scope) {
2935 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2938 motion : function(el, args, duration, easing, cb, scope) {
2939 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2942 color : function(el, args, duration, easing, cb, scope) {
2943 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2946 run : function(el, args, duration, easing, cb, scope, type) {
2947 type = type || Roo.lib.AnimBase;
2948 if (typeof easing == "string") {
2949 easing = Roo.lib.Easing[easing];
2951 var anim = new type(el, args, duration, easing);
2952 anim.animateX(function() {
2953 Roo.callback(cb, scope);
2959 * Portions of this file are based on pieces of Yahoo User Interface Library
2960 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2961 * YUI licensed under the BSD License:
2962 * http://developer.yahoo.net/yui/license.txt
2963 * <script type="text/javascript">
2971 if (!libFlyweight) {
2972 libFlyweight = new Roo.Element.Flyweight();
2974 libFlyweight.dom = el;
2975 return libFlyweight;
2978 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2982 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2984 this.init(el, attributes, duration, method);
2988 Roo.lib.AnimBase.fly = fly;
2992 Roo.lib.AnimBase.prototype = {
2994 toString: function() {
2995 var el = this.getEl();
2996 var id = el.id || el.tagName;
2997 return ("Anim " + id);
3001 noNegatives: /width|height|opacity|padding/i,
3002 offsetAttribute: /^((width|height)|(top|left))$/,
3003 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3004 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3008 doMethod: function(attr, start, end) {
3009 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3013 setAttribute: function(attr, val, unit) {
3014 if (this.patterns.noNegatives.test(attr)) {
3015 val = (val > 0) ? val : 0;
3018 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3022 getAttribute: function(attr) {
3023 var el = this.getEl();
3024 var val = fly(el).getStyle(attr);
3026 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3027 return parseFloat(val);
3030 var a = this.patterns.offsetAttribute.exec(attr) || [];
3031 var pos = !!( a[3] );
3032 var box = !!( a[2] );
3035 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3036 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3045 getDefaultUnit: function(attr) {
3046 if (this.patterns.defaultUnit.test(attr)) {
3053 animateX : function(callback, scope) {
3054 var f = function() {
3055 this.onComplete.removeListener(f);
3056 if (typeof callback == "function") {
3057 callback.call(scope || this, this);
3060 this.onComplete.addListener(f, this);
3065 setRuntimeAttribute: function(attr) {
3068 var attributes = this.attributes;
3070 this.runtimeAttributes[attr] = {};
3072 var isset = function(prop) {
3073 return (typeof prop !== 'undefined');
3076 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3080 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3083 if (isset(attributes[attr]['to'])) {
3084 end = attributes[attr]['to'];
3085 } else if (isset(attributes[attr]['by'])) {
3086 if (start.constructor == Array) {
3088 for (var i = 0, len = start.length; i < len; ++i) {
3089 end[i] = start[i] + attributes[attr]['by'][i];
3092 end = start + attributes[attr]['by'];
3096 this.runtimeAttributes[attr].start = start;
3097 this.runtimeAttributes[attr].end = end;
3100 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3104 init: function(el, attributes, duration, method) {
3106 var isAnimated = false;
3109 var startTime = null;
3112 var actualFrames = 0;
3115 el = Roo.getDom(el);
3118 this.attributes = attributes || {};
3121 this.duration = duration || 1;
3124 this.method = method || Roo.lib.Easing.easeNone;
3127 this.useSeconds = true;
3130 this.currentFrame = 0;
3133 this.totalFrames = Roo.lib.AnimMgr.fps;
3136 this.getEl = function() {
3141 this.isAnimated = function() {
3146 this.getStartTime = function() {
3150 this.runtimeAttributes = {};
3153 this.animate = function() {
3154 if (this.isAnimated()) {
3158 this.currentFrame = 0;
3160 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3162 Roo.lib.AnimMgr.registerElement(this);
3166 this.stop = function(finish) {
3168 this.currentFrame = this.totalFrames;
3169 this._onTween.fire();
3171 Roo.lib.AnimMgr.stop(this);
3174 var onStart = function() {
3175 this.onStart.fire();
3177 this.runtimeAttributes = {};
3178 for (var attr in this.attributes) {
3179 this.setRuntimeAttribute(attr);
3184 startTime = new Date();
3188 var onTween = function() {
3190 duration: new Date() - this.getStartTime(),
3191 currentFrame: this.currentFrame
3194 data.toString = function() {
3196 'duration: ' + data.duration +
3197 ', currentFrame: ' + data.currentFrame
3201 this.onTween.fire(data);
3203 var runtimeAttributes = this.runtimeAttributes;
3205 for (var attr in runtimeAttributes) {
3206 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3212 var onComplete = function() {
3213 var actual_duration = (new Date() - startTime) / 1000 ;
3216 duration: actual_duration,
3217 frames: actualFrames,
3218 fps: actualFrames / actual_duration
3221 data.toString = function() {
3223 'duration: ' + data.duration +
3224 ', frames: ' + data.frames +
3225 ', fps: ' + data.fps
3231 this.onComplete.fire(data);
3235 this._onStart = new Roo.util.Event(this);
3236 this.onStart = new Roo.util.Event(this);
3237 this.onTween = new Roo.util.Event(this);
3238 this._onTween = new Roo.util.Event(this);
3239 this.onComplete = new Roo.util.Event(this);
3240 this._onComplete = new Roo.util.Event(this);
3241 this._onStart.addListener(onStart);
3242 this._onTween.addListener(onTween);
3243 this._onComplete.addListener(onComplete);
3248 * Portions of this file are based on pieces of Yahoo User Interface Library
3249 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3250 * YUI licensed under the BSD License:
3251 * http://developer.yahoo.net/yui/license.txt
3252 * <script type="text/javascript">
3256 Roo.lib.AnimMgr = new function() {
3273 this.registerElement = function(tween) {
3274 queue[queue.length] = tween;
3276 tween._onStart.fire();
3281 this.unRegister = function(tween, index) {
3282 tween._onComplete.fire();
3283 index = index || getIndex(tween);
3285 queue.splice(index, 1);
3289 if (tweenCount <= 0) {
3295 this.start = function() {
3296 if (thread === null) {
3297 thread = setInterval(this.run, this.delay);
3302 this.stop = function(tween) {
3304 clearInterval(thread);
3306 for (var i = 0, len = queue.length; i < len; ++i) {
3307 if (queue[0].isAnimated()) {
3308 this.unRegister(queue[0], 0);
3317 this.unRegister(tween);
3322 this.run = function() {
3323 for (var i = 0, len = queue.length; i < len; ++i) {
3324 var tween = queue[i];
3325 if (!tween || !tween.isAnimated()) {
3329 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3331 tween.currentFrame += 1;
3333 if (tween.useSeconds) {
3334 correctFrame(tween);
3336 tween._onTween.fire();
3339 Roo.lib.AnimMgr.stop(tween, i);
3344 var getIndex = function(anim) {
3345 for (var i = 0, len = queue.length; i < len; ++i) {
3346 if (queue[i] == anim) {
3354 var correctFrame = function(tween) {
3355 var frames = tween.totalFrames;
3356 var frame = tween.currentFrame;
3357 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3358 var elapsed = (new Date() - tween.getStartTime());
3361 if (elapsed < tween.duration * 1000) {
3362 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3364 tweak = frames - (frame + 1);
3366 if (tweak > 0 && isFinite(tweak)) {
3367 if (tween.currentFrame + tweak >= frames) {
3368 tweak = frames - (frame + 1);
3371 tween.currentFrame += tweak;
3375 * Portions of this file are based on pieces of Yahoo User Interface Library
3376 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3377 * YUI licensed under the BSD License:
3378 * http://developer.yahoo.net/yui/license.txt
3379 * <script type="text/javascript">
3382 Roo.lib.Bezier = new function() {
3384 this.getPosition = function(points, t) {
3385 var n = points.length;
3388 for (var i = 0; i < n; ++i) {
3389 tmp[i] = [points[i][0], points[i][1]];
3392 for (var j = 1; j < n; ++j) {
3393 for (i = 0; i < n - j; ++i) {
3394 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3395 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3399 return [ tmp[0][0], tmp[0][1] ];
3403 * Portions of this file are based on pieces of Yahoo User Interface Library
3404 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3405 * YUI licensed under the BSD License:
3406 * http://developer.yahoo.net/yui/license.txt
3407 * <script type="text/javascript">
3412 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3413 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3416 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3418 var fly = Roo.lib.AnimBase.fly;
3420 var superclass = Y.ColorAnim.superclass;
3421 var proto = Y.ColorAnim.prototype;
3423 proto.toString = function() {
3424 var el = this.getEl();
3425 var id = el.id || el.tagName;
3426 return ("ColorAnim " + id);
3429 proto.patterns.color = /color$/i;
3430 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3431 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3432 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3433 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3436 proto.parseColor = function(s) {
3437 if (s.length == 3) {
3441 var c = this.patterns.hex.exec(s);
3442 if (c && c.length == 4) {
3443 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3446 c = this.patterns.rgb.exec(s);
3447 if (c && c.length == 4) {
3448 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3451 c = this.patterns.hex3.exec(s);
3452 if (c && c.length == 4) {
3453 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3458 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3459 proto.getAttribute = function(attr) {
3460 var el = this.getEl();
3461 if (this.patterns.color.test(attr)) {
3462 var val = fly(el).getStyle(attr);
3464 if (this.patterns.transparent.test(val)) {
3465 var parent = el.parentNode;
3466 val = fly(parent).getStyle(attr);
3468 while (parent && this.patterns.transparent.test(val)) {
3469 parent = parent.parentNode;
3470 val = fly(parent).getStyle(attr);
3471 if (parent.tagName.toUpperCase() == 'HTML') {
3477 val = superclass.getAttribute.call(this, attr);
3482 proto.getAttribute = function(attr) {
3483 var el = this.getEl();
3484 if (this.patterns.color.test(attr)) {
3485 var val = fly(el).getStyle(attr);
3487 if (this.patterns.transparent.test(val)) {
3488 var parent = el.parentNode;
3489 val = fly(parent).getStyle(attr);
3491 while (parent && this.patterns.transparent.test(val)) {
3492 parent = parent.parentNode;
3493 val = fly(parent).getStyle(attr);
3494 if (parent.tagName.toUpperCase() == 'HTML') {
3500 val = superclass.getAttribute.call(this, attr);
3506 proto.doMethod = function(attr, start, end) {
3509 if (this.patterns.color.test(attr)) {
3511 for (var i = 0, len = start.length; i < len; ++i) {
3512 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3515 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3518 val = superclass.doMethod.call(this, attr, start, end);
3524 proto.setRuntimeAttribute = function(attr) {
3525 superclass.setRuntimeAttribute.call(this, attr);
3527 if (this.patterns.color.test(attr)) {
3528 var attributes = this.attributes;
3529 var start = this.parseColor(this.runtimeAttributes[attr].start);
3530 var end = this.parseColor(this.runtimeAttributes[attr].end);
3532 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3533 end = this.parseColor(attributes[attr].by);
3535 for (var i = 0, len = start.length; i < len; ++i) {
3536 end[i] = start[i] + end[i];
3540 this.runtimeAttributes[attr].start = start;
3541 this.runtimeAttributes[attr].end = end;
3547 * Portions of this file are based on pieces of Yahoo User Interface Library
3548 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3549 * YUI licensed under the BSD License:
3550 * http://developer.yahoo.net/yui/license.txt
3551 * <script type="text/javascript">
3557 easeNone: function (t, b, c, d) {
3558 return c * t / d + b;
3562 easeIn: function (t, b, c, d) {
3563 return c * (t /= d) * t + b;
3567 easeOut: function (t, b, c, d) {
3568 return -c * (t /= d) * (t - 2) + b;
3572 easeBoth: function (t, b, c, d) {
3573 if ((t /= d / 2) < 1) {
3574 return c / 2 * t * t + b;
3577 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3581 easeInStrong: function (t, b, c, d) {
3582 return c * (t /= d) * t * t * t + b;
3586 easeOutStrong: function (t, b, c, d) {
3587 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3591 easeBothStrong: function (t, b, c, d) {
3592 if ((t /= d / 2) < 1) {
3593 return c / 2 * t * t * t * t + b;
3596 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3601 elasticIn: function (t, b, c, d, a, p) {
3605 if ((t /= d) == 1) {
3612 if (!a || a < Math.abs(c)) {
3617 var s = p / (2 * Math.PI) * Math.asin(c / a);
3620 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3624 elasticOut: function (t, b, c, d, a, p) {
3628 if ((t /= d) == 1) {
3635 if (!a || a < Math.abs(c)) {
3640 var s = p / (2 * Math.PI) * Math.asin(c / a);
3643 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3647 elasticBoth: function (t, b, c, d, a, p) {
3652 if ((t /= d / 2) == 2) {
3660 if (!a || a < Math.abs(c)) {
3665 var s = p / (2 * Math.PI) * Math.asin(c / a);
3669 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3670 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3672 return a * Math.pow(2, -10 * (t -= 1)) *
3673 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3678 backIn: function (t, b, c, d, s) {
3679 if (typeof s == 'undefined') {
3682 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3686 backOut: function (t, b, c, d, s) {
3687 if (typeof s == 'undefined') {
3690 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3694 backBoth: function (t, b, c, d, s) {
3695 if (typeof s == 'undefined') {
3699 if ((t /= d / 2 ) < 1) {
3700 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3702 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3706 bounceIn: function (t, b, c, d) {
3707 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3711 bounceOut: function (t, b, c, d) {
3712 if ((t /= d) < (1 / 2.75)) {
3713 return c * (7.5625 * t * t) + b;
3714 } else if (t < (2 / 2.75)) {
3715 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3716 } else if (t < (2.5 / 2.75)) {
3717 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3719 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3723 bounceBoth: function (t, b, c, d) {
3725 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3727 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3730 * Portions of this file are based on pieces of Yahoo User Interface Library
3731 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3732 * YUI licensed under the BSD License:
3733 * http://developer.yahoo.net/yui/license.txt
3734 * <script type="text/javascript">
3738 Roo.lib.Motion = function(el, attributes, duration, method) {
3740 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3744 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3748 var superclass = Y.Motion.superclass;
3749 var proto = Y.Motion.prototype;
3751 proto.toString = function() {
3752 var el = this.getEl();
3753 var id = el.id || el.tagName;
3754 return ("Motion " + id);
3757 proto.patterns.points = /^points$/i;
3759 proto.setAttribute = function(attr, val, unit) {
3760 if (this.patterns.points.test(attr)) {
3761 unit = unit || 'px';
3762 superclass.setAttribute.call(this, 'left', val[0], unit);
3763 superclass.setAttribute.call(this, 'top', val[1], unit);
3765 superclass.setAttribute.call(this, attr, val, unit);
3769 proto.getAttribute = function(attr) {
3770 if (this.patterns.points.test(attr)) {
3772 superclass.getAttribute.call(this, 'left'),
3773 superclass.getAttribute.call(this, 'top')
3776 val = superclass.getAttribute.call(this, attr);
3782 proto.doMethod = function(attr, start, end) {
3785 if (this.patterns.points.test(attr)) {
3786 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3787 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3789 val = superclass.doMethod.call(this, attr, start, end);
3794 proto.setRuntimeAttribute = function(attr) {
3795 if (this.patterns.points.test(attr)) {
3796 var el = this.getEl();
3797 var attributes = this.attributes;
3799 var control = attributes['points']['control'] || [];
3803 if (control.length > 0 && !(control[0] instanceof Array)) {
3804 control = [control];
3807 for (i = 0,len = control.length; i < len; ++i) {
3808 tmp[i] = control[i];
3813 Roo.fly(el).position();
3815 if (isset(attributes['points']['from'])) {
3816 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3819 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3822 start = this.getAttribute('points');
3825 if (isset(attributes['points']['to'])) {
3826 end = translateValues.call(this, attributes['points']['to'], start);
3828 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3829 for (i = 0,len = control.length; i < len; ++i) {
3830 control[i] = translateValues.call(this, control[i], start);
3834 } else if (isset(attributes['points']['by'])) {
3835 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3837 for (i = 0,len = control.length; i < len; ++i) {
3838 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3842 this.runtimeAttributes[attr] = [start];
3844 if (control.length > 0) {
3845 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3848 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3851 superclass.setRuntimeAttribute.call(this, attr);
3855 var translateValues = function(val, start) {
3856 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3857 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3862 var isset = function(prop) {
3863 return (typeof prop !== 'undefined');
3867 * Portions of this file are based on pieces of Yahoo User Interface Library
3868 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3869 * YUI licensed under the BSD License:
3870 * http://developer.yahoo.net/yui/license.txt
3871 * <script type="text/javascript">
3875 Roo.lib.Scroll = function(el, attributes, duration, method) {
3877 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3881 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3885 var superclass = Y.Scroll.superclass;
3886 var proto = Y.Scroll.prototype;
3888 proto.toString = function() {
3889 var el = this.getEl();
3890 var id = el.id || el.tagName;
3891 return ("Scroll " + id);
3894 proto.doMethod = function(attr, start, end) {
3897 if (attr == 'scroll') {
3899 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3900 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3904 val = superclass.doMethod.call(this, attr, start, end);
3909 proto.getAttribute = function(attr) {
3911 var el = this.getEl();
3913 if (attr == 'scroll') {
3914 val = [ el.scrollLeft, el.scrollTop ];
3916 val = superclass.getAttribute.call(this, attr);
3922 proto.setAttribute = function(attr, val, unit) {
3923 var el = this.getEl();
3925 if (attr == 'scroll') {
3926 el.scrollLeft = val[0];
3927 el.scrollTop = val[1];
3929 superclass.setAttribute.call(this, attr, val, unit);
3935 * Ext JS Library 1.1.1
3936 * Copyright(c) 2006-2007, Ext JS, LLC.
3938 * Originally Released Under LGPL - original licence link has changed is not relivant.
3941 * <script type="text/javascript">
3946 * @class Roo.DomHelper
3947 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3948 * 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>.
3951 Roo.DomHelper = function(){
3952 var tempTableEl = null;
3953 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3954 var tableRe = /^table|tbody|tr|td$/i;
3956 // build as innerHTML where available
3958 var createHtml = function(o){
3959 if(typeof o == 'string'){
3968 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3969 if(attr == "style"){
3971 if(typeof s == "function"){
3974 if(typeof s == "string"){
3975 b += ' style="' + s + '"';
3976 }else if(typeof s == "object"){
3979 if(typeof s[key] != "function"){
3980 b += key + ":" + s[key] + ";";
3987 b += ' class="' + o["cls"] + '"';
3988 }else if(attr == "htmlFor"){
3989 b += ' for="' + o["htmlFor"] + '"';
3991 b += " " + attr + '="' + o[attr] + '"';
3995 if(emptyTags.test(o.tag)){
3999 var cn = o.children || o.cn;
4001 //http://bugs.kde.org/show_bug.cgi?id=71506
4002 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4003 for(var i = 0, len = cn.length; i < len; i++) {
4004 b += createHtml(cn[i], b);
4007 b += createHtml(cn, b);
4013 b += "</" + o.tag + ">";
4020 var createDom = function(o, parentNode){
4022 // defininition craeted..
4024 if (o.ns && o.ns != 'html') {
4026 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4027 xmlns[o.ns] = o.xmlns;
4030 if (typeof(xmlns[o.ns]) == 'undefined') {
4031 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4037 if (typeof(o) == 'string') {
4038 return parentNode.appendChild(document.createTextNode(o));
4040 o.tag = o.tag || div;
4041 if (o.ns && Roo.isIE) {
4043 o.tag = o.ns + ':' + o.tag;
4046 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4047 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4050 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4051 attr == "style" || typeof o[attr] == "function") continue;
4053 if(attr=="cls" && Roo.isIE){
4054 el.className = o["cls"];
4056 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4057 else el[attr] = o[attr];
4060 Roo.DomHelper.applyStyles(el, o.style);
4061 var cn = o.children || o.cn;
4063 //http://bugs.kde.org/show_bug.cgi?id=71506
4064 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4065 for(var i = 0, len = cn.length; i < len; i++) {
4066 createDom(cn[i], el);
4073 el.innerHTML = o.html;
4076 parentNode.appendChild(el);
4081 var ieTable = function(depth, s, h, e){
4082 tempTableEl.innerHTML = [s, h, e].join('');
4083 var i = -1, el = tempTableEl;
4090 // kill repeat to save bytes
4094 tbe = '</tbody>'+te,
4100 * Nasty code for IE's broken table implementation
4102 var insertIntoTable = function(tag, where, el, html){
4104 tempTableEl = document.createElement('div');
4109 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4112 if(where == 'beforebegin'){
4116 before = el.nextSibling;
4119 node = ieTable(4, trs, html, tre);
4121 else if(tag == 'tr'){
4122 if(where == 'beforebegin'){
4125 node = ieTable(3, tbs, html, tbe);
4126 } else if(where == 'afterend'){
4127 before = el.nextSibling;
4129 node = ieTable(3, tbs, html, tbe);
4130 } else{ // INTO a TR
4131 if(where == 'afterbegin'){
4132 before = el.firstChild;
4134 node = ieTable(4, trs, html, tre);
4136 } else if(tag == 'tbody'){
4137 if(where == 'beforebegin'){
4140 node = ieTable(2, ts, html, te);
4141 } else if(where == 'afterend'){
4142 before = el.nextSibling;
4144 node = ieTable(2, ts, html, te);
4146 if(where == 'afterbegin'){
4147 before = el.firstChild;
4149 node = ieTable(3, tbs, html, tbe);
4152 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4155 if(where == 'afterbegin'){
4156 before = el.firstChild;
4158 node = ieTable(2, ts, html, te);
4160 el.insertBefore(node, before);
4165 /** True to force the use of DOM instead of html fragments @type Boolean */
4169 * Returns the markup for the passed Element(s) config
4170 * @param {Object} o The Dom object spec (and children)
4173 markup : function(o){
4174 return createHtml(o);
4178 * Applies a style specification to an element
4179 * @param {String/HTMLElement} el The element to apply styles to
4180 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4181 * a function which returns such a specification.
4183 applyStyles : function(el, styles){
4186 if(typeof styles == "string"){
4187 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4189 while ((matches = re.exec(styles)) != null){
4190 el.setStyle(matches[1], matches[2]);
4192 }else if (typeof styles == "object"){
4193 for (var style in styles){
4194 el.setStyle(style, styles[style]);
4196 }else if (typeof styles == "function"){
4197 Roo.DomHelper.applyStyles(el, styles.call());
4203 * Inserts an HTML fragment into the Dom
4204 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4205 * @param {HTMLElement} el The context element
4206 * @param {String} html The HTML fragmenet
4207 * @return {HTMLElement} The new node
4209 insertHtml : function(where, el, html){
4210 where = where.toLowerCase();
4211 if(el.insertAdjacentHTML){
4212 if(tableRe.test(el.tagName)){
4214 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4220 el.insertAdjacentHTML('BeforeBegin', html);
4221 return el.previousSibling;
4223 el.insertAdjacentHTML('AfterBegin', html);
4224 return el.firstChild;
4226 el.insertAdjacentHTML('BeforeEnd', html);
4227 return el.lastChild;
4229 el.insertAdjacentHTML('AfterEnd', html);
4230 return el.nextSibling;
4232 throw 'Illegal insertion point -> "' + where + '"';
4234 var range = el.ownerDocument.createRange();
4238 range.setStartBefore(el);
4239 frag = range.createContextualFragment(html);
4240 el.parentNode.insertBefore(frag, el);
4241 return el.previousSibling;
4244 range.setStartBefore(el.firstChild);
4245 frag = range.createContextualFragment(html);
4246 el.insertBefore(frag, el.firstChild);
4247 return el.firstChild;
4249 el.innerHTML = html;
4250 return el.firstChild;
4254 range.setStartAfter(el.lastChild);
4255 frag = range.createContextualFragment(html);
4256 el.appendChild(frag);
4257 return el.lastChild;
4259 el.innerHTML = html;
4260 return el.lastChild;
4263 range.setStartAfter(el);
4264 frag = range.createContextualFragment(html);
4265 el.parentNode.insertBefore(frag, el.nextSibling);
4266 return el.nextSibling;
4268 throw 'Illegal insertion point -> "' + where + '"';
4272 * Creates new Dom element(s) and inserts them before el
4273 * @param {String/HTMLElement/Element} el The context element
4274 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4275 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4276 * @return {HTMLElement/Roo.Element} The new node
4278 insertBefore : function(el, o, returnElement){
4279 return this.doInsert(el, o, returnElement, "beforeBegin");
4283 * Creates new Dom element(s) and inserts them after el
4284 * @param {String/HTMLElement/Element} el The context element
4285 * @param {Object} o The Dom object spec (and children)
4286 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4287 * @return {HTMLElement/Roo.Element} The new node
4289 insertAfter : function(el, o, returnElement){
4290 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4294 * Creates new Dom element(s) and inserts them as the first child of el
4295 * @param {String/HTMLElement/Element} el The context element
4296 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4297 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4298 * @return {HTMLElement/Roo.Element} The new node
4300 insertFirst : function(el, o, returnElement){
4301 return this.doInsert(el, o, returnElement, "afterBegin");
4305 doInsert : function(el, o, returnElement, pos, sibling){
4306 el = Roo.getDom(el);
4308 if(this.useDom || o.ns){
4309 newNode = createDom(o, null);
4310 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4312 var html = createHtml(o);
4313 newNode = this.insertHtml(pos, el, html);
4315 return returnElement ? Roo.get(newNode, true) : newNode;
4319 * Creates new Dom element(s) and appends them to el
4320 * @param {String/HTMLElement/Element} el The context element
4321 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4322 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4323 * @return {HTMLElement/Roo.Element} The new node
4325 append : function(el, o, returnElement){
4326 el = Roo.getDom(el);
4328 if(this.useDom || o.ns){
4329 newNode = createDom(o, null);
4330 el.appendChild(newNode);
4332 var html = createHtml(o);
4333 newNode = this.insertHtml("beforeEnd", el, html);
4335 return returnElement ? Roo.get(newNode, true) : newNode;
4339 * Creates new Dom element(s) and overwrites the contents of el with them
4340 * @param {String/HTMLElement/Element} el The context element
4341 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4342 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4343 * @return {HTMLElement/Roo.Element} The new node
4345 overwrite : function(el, o, returnElement){
4346 el = Roo.getDom(el);
4349 while (el.childNodes.length) {
4350 el.removeChild(el.firstChild);
4354 el.innerHTML = createHtml(o);
4357 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4361 * Creates a new Roo.DomHelper.Template from the Dom object spec
4362 * @param {Object} o The Dom object spec (and children)
4363 * @return {Roo.DomHelper.Template} The new template
4365 createTemplate : function(o){
4366 var html = createHtml(o);
4367 return new Roo.Template(html);
4373 * Ext JS Library 1.1.1
4374 * Copyright(c) 2006-2007, Ext JS, LLC.
4376 * Originally Released Under LGPL - original licence link has changed is not relivant.
4379 * <script type="text/javascript">
4383 * @class Roo.Template
4384 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4385 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4388 var t = new Roo.Template(
4389 '<div name="{id}">',
4390 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4393 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4395 * 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>.
4397 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4399 Roo.Template = function(html){
4400 if(html instanceof Array){
4401 html = html.join("");
4402 }else if(arguments.length > 1){
4403 html = Array.prototype.join.call(arguments, "");
4409 Roo.Template.prototype = {
4411 * Returns an HTML fragment of this template with the specified values applied.
4412 * @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'})
4413 * @return {String} The HTML fragment
4415 applyTemplate : function(values){
4417 return this.compiled(values);
4419 var useF = this.disableFormats !== true;
4420 var fm = Roo.util.Format, tpl = this;
4421 var fn = function(m, name, format, args){
4423 if(format.substr(0, 5) == "this."){
4424 return tpl.call(format.substr(5), values[name], values);
4427 // quoted values are required for strings in compiled templates,
4428 // but for non compiled we need to strip them
4429 // quoted reversed for jsmin
4430 var re = /^\s*['"](.*)["']\s*$/;
4431 args = args.split(',');
4432 for(var i = 0, len = args.length; i < len; i++){
4433 args[i] = args[i].replace(re, "$1");
4435 args = [values[name]].concat(args);
4437 args = [values[name]];
4439 return fm[format].apply(fm, args);
4442 return values[name] !== undefined ? values[name] : "";
4445 return this.html.replace(this.re, fn);
4449 * Sets the HTML used as the template and optionally compiles it.
4450 * @param {String} html
4451 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4452 * @return {Roo.Template} this
4454 set : function(html, compile){
4456 this.compiled = null;
4464 * True to disable format functions (defaults to false)
4467 disableFormats : false,
4470 * The regular expression used to match template variables
4474 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4477 * Compiles the template into an internal function, eliminating the RegEx overhead.
4478 * @return {Roo.Template} this
4480 compile : function(){
4481 var fm = Roo.util.Format;
4482 var useF = this.disableFormats !== true;
4483 var sep = Roo.isGecko ? "+" : ",";
4484 var fn = function(m, name, format, args){
4486 args = args ? ',' + args : "";
4487 if(format.substr(0, 5) != "this."){
4488 format = "fm." + format + '(';
4490 format = 'this.call("'+ format.substr(5) + '", ';
4494 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4496 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4499 // branched to use + in gecko and [].join() in others
4501 body = "this.compiled = function(values){ return '" +
4502 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4505 body = ["this.compiled = function(values){ return ['"];
4506 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4507 body.push("'].join('');};");
4508 body = body.join('');
4518 // private function used to call members
4519 call : function(fnName, value, allValues){
4520 return this[fnName](value, allValues);
4524 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4525 * @param {String/HTMLElement/Roo.Element} el The context element
4526 * @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'})
4527 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4528 * @return {HTMLElement/Roo.Element} The new node or Element
4530 insertFirst: function(el, values, returnElement){
4531 return this.doInsert('afterBegin', el, values, returnElement);
4535 * Applies the supplied values to the template and inserts the new node(s) before el.
4536 * @param {String/HTMLElement/Roo.Element} el The context element
4537 * @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'})
4538 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4539 * @return {HTMLElement/Roo.Element} The new node or Element
4541 insertBefore: function(el, values, returnElement){
4542 return this.doInsert('beforeBegin', el, values, returnElement);
4546 * Applies the supplied values to the template and inserts the new node(s) after el.
4547 * @param {String/HTMLElement/Roo.Element} el The context element
4548 * @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'})
4549 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4550 * @return {HTMLElement/Roo.Element} The new node or Element
4552 insertAfter : function(el, values, returnElement){
4553 return this.doInsert('afterEnd', el, values, returnElement);
4557 * Applies the supplied values to the template and appends the new node(s) to el.
4558 * @param {String/HTMLElement/Roo.Element} el The context element
4559 * @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'})
4560 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4561 * @return {HTMLElement/Roo.Element} The new node or Element
4563 append : function(el, values, returnElement){
4564 return this.doInsert('beforeEnd', el, values, returnElement);
4567 doInsert : function(where, el, values, returnEl){
4568 el = Roo.getDom(el);
4569 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4570 return returnEl ? Roo.get(newNode, true) : newNode;
4574 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4575 * @param {String/HTMLElement/Roo.Element} el The context element
4576 * @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'})
4577 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4578 * @return {HTMLElement/Roo.Element} The new node or Element
4580 overwrite : function(el, values, returnElement){
4581 el = Roo.getDom(el);
4582 el.innerHTML = this.applyTemplate(values);
4583 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4587 * Alias for {@link #applyTemplate}
4590 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4593 Roo.DomHelper.Template = Roo.Template;
4596 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4597 * @param {String/HTMLElement} el A DOM element or its id
4598 * @returns {Roo.Template} The created template
4601 Roo.Template.from = function(el){
4602 el = Roo.getDom(el);
4603 return new Roo.Template(el.value || el.innerHTML);
4606 * Ext JS Library 1.1.1
4607 * Copyright(c) 2006-2007, Ext JS, LLC.
4609 * Originally Released Under LGPL - original licence link has changed is not relivant.
4612 * <script type="text/javascript">
4617 * This is code is also distributed under MIT license for use
4618 * with jQuery and prototype JavaScript libraries.
4621 * @class Roo.DomQuery
4622 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).
4624 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>
4627 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.
4629 <h4>Element Selectors:</h4>
4631 <li> <b>*</b> any element</li>
4632 <li> <b>E</b> an element with the tag E</li>
4633 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4634 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4635 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4636 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4638 <h4>Attribute Selectors:</h4>
4639 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4641 <li> <b>E[foo]</b> has an attribute "foo"</li>
4642 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4643 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4644 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4645 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4646 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4647 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4649 <h4>Pseudo Classes:</h4>
4651 <li> <b>E:first-child</b> E is the first child of its parent</li>
4652 <li> <b>E:last-child</b> E is the last child of its parent</li>
4653 <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>
4654 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4655 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4656 <li> <b>E:only-child</b> E is the only child of its parent</li>
4657 <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>
4658 <li> <b>E:first</b> the first E in the resultset</li>
4659 <li> <b>E:last</b> the last E in the resultset</li>
4660 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4661 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4662 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4663 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4664 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4665 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4666 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4667 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4668 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4670 <h4>CSS Value Selectors:</h4>
4672 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4673 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4674 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4675 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4676 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4677 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4681 Roo.DomQuery = function(){
4682 var cache = {}, simpleCache = {}, valueCache = {};
4683 var nonSpace = /\S/;
4684 var trimRe = /^\s+|\s+$/g;
4685 var tplRe = /\{(\d+)\}/g;
4686 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4687 var tagTokenRe = /^(#)?([\w-\*]+)/;
4688 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4690 function child(p, index){
4692 var n = p.firstChild;
4694 if(n.nodeType == 1){
4705 while((n = n.nextSibling) && n.nodeType != 1);
4710 while((n = n.previousSibling) && n.nodeType != 1);
4714 function children(d){
4715 var n = d.firstChild, ni = -1;
4717 var nx = n.nextSibling;
4718 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4728 function byClassName(c, a, v){
4732 var r = [], ri = -1, cn;
4733 for(var i = 0, ci; ci = c[i]; i++){
4734 if((' '+ci.className+' ').indexOf(v) != -1){
4741 function attrValue(n, attr){
4742 if(!n.tagName && typeof n.length != "undefined"){
4751 if(attr == "class" || attr == "className"){
4754 return n.getAttribute(attr) || n[attr];
4758 function getNodes(ns, mode, tagName){
4759 var result = [], ri = -1, cs;
4763 tagName = tagName || "*";
4764 if(typeof ns.getElementsByTagName != "undefined"){
4768 for(var i = 0, ni; ni = ns[i]; i++){
4769 cs = ni.getElementsByTagName(tagName);
4770 for(var j = 0, ci; ci = cs[j]; j++){
4774 }else if(mode == "/" || mode == ">"){
4775 var utag = tagName.toUpperCase();
4776 for(var i = 0, ni, cn; ni = ns[i]; i++){
4777 cn = ni.children || ni.childNodes;
4778 for(var j = 0, cj; cj = cn[j]; j++){
4779 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4784 }else if(mode == "+"){
4785 var utag = tagName.toUpperCase();
4786 for(var i = 0, n; n = ns[i]; i++){
4787 while((n = n.nextSibling) && n.nodeType != 1);
4788 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4792 }else if(mode == "~"){
4793 for(var i = 0, n; n = ns[i]; i++){
4794 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4803 function concat(a, b){
4807 for(var i = 0, l = b.length; i < l; i++){
4813 function byTag(cs, tagName){
4814 if(cs.tagName || cs == document){
4820 var r = [], ri = -1;
4821 tagName = tagName.toLowerCase();
4822 for(var i = 0, ci; ci = cs[i]; i++){
4823 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4830 function byId(cs, attr, id){
4831 if(cs.tagName || cs == document){
4837 var r = [], ri = -1;
4838 for(var i = 0,ci; ci = cs[i]; i++){
4839 if(ci && ci.id == id){
4847 function byAttribute(cs, attr, value, op, custom){
4848 var r = [], ri = -1, st = custom=="{";
4849 var f = Roo.DomQuery.operators[op];
4850 for(var i = 0, ci; ci = cs[i]; i++){
4853 a = Roo.DomQuery.getStyle(ci, attr);
4855 else if(attr == "class" || attr == "className"){
4857 }else if(attr == "for"){
4859 }else if(attr == "href"){
4860 a = ci.getAttribute("href", 2);
4862 a = ci.getAttribute(attr);
4864 if((f && f(a, value)) || (!f && a)){
4871 function byPseudo(cs, name, value){
4872 return Roo.DomQuery.pseudos[name](cs, value);
4875 // This is for IE MSXML which does not support expandos.
4876 // IE runs the same speed using setAttribute, however FF slows way down
4877 // and Safari completely fails so they need to continue to use expandos.
4878 var isIE = window.ActiveXObject ? true : false;
4880 // this eval is stop the compressor from
4881 // renaming the variable to something shorter
4883 /** eval:var:batch */
4888 function nodupIEXml(cs){
4890 cs[0].setAttribute("_nodup", d);
4892 for(var i = 1, len = cs.length; i < len; i++){
4894 if(!c.getAttribute("_nodup") != d){
4895 c.setAttribute("_nodup", d);
4899 for(var i = 0, len = cs.length; i < len; i++){
4900 cs[i].removeAttribute("_nodup");
4909 var len = cs.length, c, i, r = cs, cj, ri = -1;
4910 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4913 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4914 return nodupIEXml(cs);
4918 for(i = 1; c = cs[i]; i++){
4923 for(var j = 0; j < i; j++){
4926 for(j = i+1; cj = cs[j]; j++){
4938 function quickDiffIEXml(c1, c2){
4940 for(var i = 0, len = c1.length; i < len; i++){
4941 c1[i].setAttribute("_qdiff", d);
4944 for(var i = 0, len = c2.length; i < len; i++){
4945 if(c2[i].getAttribute("_qdiff") != d){
4946 r[r.length] = c2[i];
4949 for(var i = 0, len = c1.length; i < len; i++){
4950 c1[i].removeAttribute("_qdiff");
4955 function quickDiff(c1, c2){
4956 var len1 = c1.length;
4960 if(isIE && c1[0].selectSingleNode){
4961 return quickDiffIEXml(c1, c2);
4964 for(var i = 0; i < len1; i++){
4968 for(var i = 0, len = c2.length; i < len; i++){
4969 if(c2[i]._qdiff != d){
4970 r[r.length] = c2[i];
4976 function quickId(ns, mode, root, id){
4978 var d = root.ownerDocument || root;
4979 return d.getElementById(id);
4981 ns = getNodes(ns, mode, "*");
4982 return byId(ns, null, id);
4986 getStyle : function(el, name){
4987 return Roo.fly(el).getStyle(name);
4990 * Compiles a selector/xpath query into a reusable function. The returned function
4991 * takes one parameter "root" (optional), which is the context node from where the query should start.
4992 * @param {String} selector The selector/xpath query
4993 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4994 * @return {Function}
4996 compile : function(path, type){
4997 type = type || "select";
4999 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5000 var q = path, mode, lq;
5001 var tk = Roo.DomQuery.matchers;
5002 var tklen = tk.length;
5005 // accept leading mode switch
5006 var lmode = q.match(modeRe);
5007 if(lmode && lmode[1]){
5008 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5009 q = q.replace(lmode[1], "");
5011 // strip leading slashes
5012 while(path.substr(0, 1)=="/"){
5013 path = path.substr(1);
5016 while(q && lq != q){
5018 var tm = q.match(tagTokenRe);
5019 if(type == "select"){
5022 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5024 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5026 q = q.replace(tm[0], "");
5027 }else if(q.substr(0, 1) != '@'){
5028 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5033 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5035 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5037 q = q.replace(tm[0], "");
5040 while(!(mm = q.match(modeRe))){
5041 var matched = false;
5042 for(var j = 0; j < tklen; j++){
5044 var m = q.match(t.re);
5046 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5049 q = q.replace(m[0], "");
5054 // prevent infinite loop on bad selector
5056 throw 'Error parsing selector, parsing failed at "' + q + '"';
5060 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5061 q = q.replace(mm[1], "");
5064 fn[fn.length] = "return nodup(n);\n}";
5067 * list of variables that need from compression as they are used by eval.
5077 * eval:var:byClassName
5079 * eval:var:byAttribute
5080 * eval:var:attrValue
5088 * Selects a group of elements.
5089 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5090 * @param {Node} root (optional) The start of the query (defaults to document).
5093 select : function(path, root, type){
5094 if(!root || root == document){
5097 if(typeof root == "string"){
5098 root = document.getElementById(root);
5100 var paths = path.split(",");
5102 for(var i = 0, len = paths.length; i < len; i++){
5103 var p = paths[i].replace(trimRe, "");
5105 cache[p] = Roo.DomQuery.compile(p);
5107 throw p + " is not a valid selector";
5110 var result = cache[p](root);
5111 if(result && result != document){
5112 results = results.concat(result);
5115 if(paths.length > 1){
5116 return nodup(results);
5122 * Selects a single element.
5123 * @param {String} selector The selector/xpath query
5124 * @param {Node} root (optional) The start of the query (defaults to document).
5127 selectNode : function(path, root){
5128 return Roo.DomQuery.select(path, root)[0];
5132 * Selects the value of a node, optionally replacing null with the defaultValue.
5133 * @param {String} selector The selector/xpath query
5134 * @param {Node} root (optional) The start of the query (defaults to document).
5135 * @param {String} defaultValue
5137 selectValue : function(path, root, defaultValue){
5138 path = path.replace(trimRe, "");
5139 if(!valueCache[path]){
5140 valueCache[path] = Roo.DomQuery.compile(path, "select");
5142 var n = valueCache[path](root);
5143 n = n[0] ? n[0] : n;
5144 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5145 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5149 * Selects the value of a node, parsing integers and floats.
5150 * @param {String} selector The selector/xpath query
5151 * @param {Node} root (optional) The start of the query (defaults to document).
5152 * @param {Number} defaultValue
5155 selectNumber : function(path, root, defaultValue){
5156 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5157 return parseFloat(v);
5161 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5162 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5163 * @param {String} selector The simple selector to test
5166 is : function(el, ss){
5167 if(typeof el == "string"){
5168 el = document.getElementById(el);
5170 var isArray = (el instanceof Array);
5171 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5172 return isArray ? (result.length == el.length) : (result.length > 0);
5176 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5177 * @param {Array} el An array of elements to filter
5178 * @param {String} selector The simple selector to test
5179 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5180 * the selector instead of the ones that match
5183 filter : function(els, ss, nonMatches){
5184 ss = ss.replace(trimRe, "");
5185 if(!simpleCache[ss]){
5186 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5188 var result = simpleCache[ss](els);
5189 return nonMatches ? quickDiff(result, els) : result;
5193 * Collection of matching regular expressions and code snippets.
5197 select: 'n = byClassName(n, null, " {1} ");'
5199 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5200 select: 'n = byPseudo(n, "{1}", "{2}");'
5202 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5203 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5206 select: 'n = byId(n, null, "{1}");'
5209 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5214 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5215 * 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, > <.
5218 "=" : function(a, v){
5221 "!=" : function(a, v){
5224 "^=" : function(a, v){
5225 return a && a.substr(0, v.length) == v;
5227 "$=" : function(a, v){
5228 return a && a.substr(a.length-v.length) == v;
5230 "*=" : function(a, v){
5231 return a && a.indexOf(v) !== -1;
5233 "%=" : function(a, v){
5234 return (a % v) == 0;
5236 "|=" : function(a, v){
5237 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5239 "~=" : function(a, v){
5240 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5245 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5246 * and the argument (if any) supplied in the selector.
5249 "first-child" : function(c){
5250 var r = [], ri = -1, n;
5251 for(var i = 0, ci; ci = n = c[i]; i++){
5252 while((n = n.previousSibling) && n.nodeType != 1);
5260 "last-child" : function(c){
5261 var r = [], ri = -1, n;
5262 for(var i = 0, ci; ci = n = c[i]; i++){
5263 while((n = n.nextSibling) && n.nodeType != 1);
5271 "nth-child" : function(c, a) {
5272 var r = [], ri = -1;
5273 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5274 var f = (m[1] || 1) - 0, l = m[2] - 0;
5275 for(var i = 0, n; n = c[i]; i++){
5276 var pn = n.parentNode;
5277 if (batch != pn._batch) {
5279 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5280 if(cn.nodeType == 1){
5287 if (l == 0 || n.nodeIndex == l){
5290 } else if ((n.nodeIndex + l) % f == 0){
5298 "only-child" : function(c){
5299 var r = [], ri = -1;;
5300 for(var i = 0, ci; ci = c[i]; i++){
5301 if(!prev(ci) && !next(ci)){
5308 "empty" : function(c){
5309 var r = [], ri = -1;
5310 for(var i = 0, ci; ci = c[i]; i++){
5311 var cns = ci.childNodes, j = 0, cn, empty = true;
5314 if(cn.nodeType == 1 || cn.nodeType == 3){
5326 "contains" : function(c, v){
5327 var r = [], ri = -1;
5328 for(var i = 0, ci; ci = c[i]; i++){
5329 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5336 "nodeValue" : function(c, v){
5337 var r = [], ri = -1;
5338 for(var i = 0, ci; ci = c[i]; i++){
5339 if(ci.firstChild && ci.firstChild.nodeValue == v){
5346 "checked" : function(c){
5347 var r = [], ri = -1;
5348 for(var i = 0, ci; ci = c[i]; i++){
5349 if(ci.checked == true){
5356 "not" : function(c, ss){
5357 return Roo.DomQuery.filter(c, ss, true);
5360 "odd" : function(c){
5361 return this["nth-child"](c, "odd");
5364 "even" : function(c){
5365 return this["nth-child"](c, "even");
5368 "nth" : function(c, a){
5369 return c[a-1] || [];
5372 "first" : function(c){
5376 "last" : function(c){
5377 return c[c.length-1] || [];
5380 "has" : function(c, ss){
5381 var s = Roo.DomQuery.select;
5382 var r = [], ri = -1;
5383 for(var i = 0, ci; ci = c[i]; i++){
5384 if(s(ss, ci).length > 0){
5391 "next" : function(c, ss){
5392 var is = Roo.DomQuery.is;
5393 var r = [], ri = -1;
5394 for(var i = 0, ci; ci = c[i]; i++){
5403 "prev" : function(c, ss){
5404 var is = Roo.DomQuery.is;
5405 var r = [], ri = -1;
5406 for(var i = 0, ci; ci = c[i]; i++){
5419 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5420 * @param {String} path The selector/xpath query
5421 * @param {Node} root (optional) The start of the query (defaults to document).
5426 Roo.query = Roo.DomQuery.select;
5429 * Ext JS Library 1.1.1
5430 * Copyright(c) 2006-2007, Ext JS, LLC.
5432 * Originally Released Under LGPL - original licence link has changed is not relivant.
5435 * <script type="text/javascript">
5439 * @class Roo.util.Observable
5440 * Base class that provides a common interface for publishing events. Subclasses are expected to
5441 * to have a property "events" with all the events defined.<br>
5444 Employee = function(name){
5451 Roo.extend(Employee, Roo.util.Observable);
5453 * @param {Object} config properties to use (incuding events / listeners)
5456 Roo.util.Observable = function(cfg){
5459 this.addEvents(cfg.events || {});
5461 delete cfg.events; // make sure
5464 Roo.apply(this, cfg);
5467 this.on(this.listeners);
5468 delete this.listeners;
5471 Roo.util.Observable.prototype = {
5473 * @cfg {Object} listeners list of events and functions to call for this object,
5477 'click' : function(e) {
5487 * Fires the specified event with the passed parameters (minus the event name).
5488 * @param {String} eventName
5489 * @param {Object...} args Variable number of parameters are passed to handlers
5490 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5492 fireEvent : function(){
5493 var ce = this.events[arguments[0].toLowerCase()];
5494 if(typeof ce == "object"){
5495 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5502 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5505 * Appends an event handler to this component
5506 * @param {String} eventName The type of event to listen for
5507 * @param {Function} handler The method the event invokes
5508 * @param {Object} scope (optional) The scope in which to execute the handler
5509 * function. The handler function's "this" context.
5510 * @param {Object} options (optional) An object containing handler configuration
5511 * properties. This may contain any of the following properties:<ul>
5512 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5513 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5514 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5515 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5516 * by the specified number of milliseconds. If the event fires again within that time, the original
5517 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5520 * <b>Combining Options</b><br>
5521 * Using the options argument, it is possible to combine different types of listeners:<br>
5523 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5525 el.on('click', this.onClick, this, {
5532 * <b>Attaching multiple handlers in 1 call</b><br>
5533 * The method also allows for a single argument to be passed which is a config object containing properties
5534 * which specify multiple handlers.
5543 fn: this.onMouseOver,
5547 fn: this.onMouseOut,
5553 * Or a shorthand syntax which passes the same scope object to all handlers:
5556 'click': this.onClick,
5557 'mouseover': this.onMouseOver,
5558 'mouseout': this.onMouseOut,
5563 addListener : function(eventName, fn, scope, o){
5564 if(typeof eventName == "object"){
5567 if(this.filterOptRe.test(e)){
5570 if(typeof o[e] == "function"){
5572 this.addListener(e, o[e], o.scope, o);
5574 // individual options
5575 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5580 o = (!o || typeof o == "boolean") ? {} : o;
5581 eventName = eventName.toLowerCase();
5582 var ce = this.events[eventName] || true;
5583 if(typeof ce == "boolean"){
5584 ce = new Roo.util.Event(this, eventName);
5585 this.events[eventName] = ce;
5587 ce.addListener(fn, scope, o);
5591 * Removes a listener
5592 * @param {String} eventName The type of event to listen for
5593 * @param {Function} handler The handler to remove
5594 * @param {Object} scope (optional) The scope (this object) for the handler
5596 removeListener : function(eventName, fn, scope){
5597 var ce = this.events[eventName.toLowerCase()];
5598 if(typeof ce == "object"){
5599 ce.removeListener(fn, scope);
5604 * Removes all listeners for this object
5606 purgeListeners : function(){
5607 for(var evt in this.events){
5608 if(typeof this.events[evt] == "object"){
5609 this.events[evt].clearListeners();
5614 relayEvents : function(o, events){
5615 var createHandler = function(ename){
5617 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5620 for(var i = 0, len = events.length; i < len; i++){
5621 var ename = events[i];
5622 if(!this.events[ename]){ this.events[ename] = true; };
5623 o.on(ename, createHandler(ename), this);
5628 * Used to define events on this Observable
5629 * @param {Object} object The object with the events defined
5631 addEvents : function(o){
5635 Roo.applyIf(this.events, o);
5639 * Checks to see if this object has any listeners for a specified event
5640 * @param {String} eventName The name of the event to check for
5641 * @return {Boolean} True if the event is being listened for, else false
5643 hasListener : function(eventName){
5644 var e = this.events[eventName];
5645 return typeof e == "object" && e.listeners.length > 0;
5649 * Appends an event handler to this element (shorthand for addListener)
5650 * @param {String} eventName The type of event to listen for
5651 * @param {Function} handler The method the event invokes
5652 * @param {Object} scope (optional) The scope in which to execute the handler
5653 * function. The handler function's "this" context.
5654 * @param {Object} options (optional)
5657 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5659 * Removes a listener (shorthand for removeListener)
5660 * @param {String} eventName The type of event to listen for
5661 * @param {Function} handler The handler to remove
5662 * @param {Object} scope (optional) The scope (this object) for the handler
5665 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5668 * Starts capture on the specified Observable. All events will be passed
5669 * to the supplied function with the event name + standard signature of the event
5670 * <b>before</b> the event is fired. If the supplied function returns false,
5671 * the event will not fire.
5672 * @param {Observable} o The Observable to capture
5673 * @param {Function} fn The function to call
5674 * @param {Object} scope (optional) The scope (this object) for the fn
5677 Roo.util.Observable.capture = function(o, fn, scope){
5678 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5682 * Removes <b>all</b> added captures from the Observable.
5683 * @param {Observable} o The Observable to release
5686 Roo.util.Observable.releaseCapture = function(o){
5687 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5692 var createBuffered = function(h, o, scope){
5693 var task = new Roo.util.DelayedTask();
5695 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5699 var createSingle = function(h, e, fn, scope){
5701 e.removeListener(fn, scope);
5702 return h.apply(scope, arguments);
5706 var createDelayed = function(h, o, scope){
5708 var args = Array.prototype.slice.call(arguments, 0);
5709 setTimeout(function(){
5710 h.apply(scope, args);
5715 Roo.util.Event = function(obj, name){
5718 this.listeners = [];
5721 Roo.util.Event.prototype = {
5722 addListener : function(fn, scope, options){
5723 var o = options || {};
5724 scope = scope || this.obj;
5725 if(!this.isListening(fn, scope)){
5726 var l = {fn: fn, scope: scope, options: o};
5729 h = createDelayed(h, o, scope);
5732 h = createSingle(h, this, fn, scope);
5735 h = createBuffered(h, o, scope);
5738 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5739 this.listeners.push(l);
5741 this.listeners = this.listeners.slice(0);
5742 this.listeners.push(l);
5747 findListener : function(fn, scope){
5748 scope = scope || this.obj;
5749 var ls = this.listeners;
5750 for(var i = 0, len = ls.length; i < len; i++){
5752 if(l.fn == fn && l.scope == scope){
5759 isListening : function(fn, scope){
5760 return this.findListener(fn, scope) != -1;
5763 removeListener : function(fn, scope){
5765 if((index = this.findListener(fn, scope)) != -1){
5767 this.listeners.splice(index, 1);
5769 this.listeners = this.listeners.slice(0);
5770 this.listeners.splice(index, 1);
5777 clearListeners : function(){
5778 this.listeners = [];
5782 var ls = this.listeners, scope, len = ls.length;
5785 var args = Array.prototype.slice.call(arguments, 0);
5786 for(var i = 0; i < len; i++){
5788 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5789 this.firing = false;
5793 this.firing = false;
5800 * Ext JS Library 1.1.1
5801 * Copyright(c) 2006-2007, Ext JS, LLC.
5803 * Originally Released Under LGPL - original licence link has changed is not relivant.
5806 * <script type="text/javascript">
5810 * @class Roo.EventManager
5811 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5812 * several useful events directly.
5813 * See {@link Roo.EventObject} for more details on normalized event objects.
5816 Roo.EventManager = function(){
5817 var docReadyEvent, docReadyProcId, docReadyState = false;
5818 var resizeEvent, resizeTask, textEvent, textSize;
5819 var E = Roo.lib.Event;
5820 var D = Roo.lib.Dom;
5823 var fireDocReady = function(){
5825 docReadyState = true;
5828 clearInterval(docReadyProcId);
5830 if(Roo.isGecko || Roo.isOpera) {
5831 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5834 var defer = document.getElementById("ie-deferred-loader");
5836 defer.onreadystatechange = null;
5837 defer.parentNode.removeChild(defer);
5841 docReadyEvent.fire();
5842 docReadyEvent.clearListeners();
5847 var initDocReady = function(){
5848 docReadyEvent = new Roo.util.Event();
5849 if(Roo.isGecko || Roo.isOpera) {
5850 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5852 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5853 var defer = document.getElementById("ie-deferred-loader");
5854 defer.onreadystatechange = function(){
5855 if(this.readyState == "complete"){
5859 }else if(Roo.isSafari){
5860 docReadyProcId = setInterval(function(){
5861 var rs = document.readyState;
5862 if(rs == "complete") {
5867 // no matter what, make sure it fires on load
5868 E.on(window, "load", fireDocReady);
5871 var createBuffered = function(h, o){
5872 var task = new Roo.util.DelayedTask(h);
5874 // create new event object impl so new events don't wipe out properties
5875 e = new Roo.EventObjectImpl(e);
5876 task.delay(o.buffer, h, null, [e]);
5880 var createSingle = function(h, el, ename, fn){
5882 Roo.EventManager.removeListener(el, ename, fn);
5887 var createDelayed = function(h, o){
5889 // create new event object impl so new events don't wipe out properties
5890 e = new Roo.EventObjectImpl(e);
5891 setTimeout(function(){
5897 var listen = function(element, ename, opt, fn, scope){
5898 var o = (!opt || typeof opt == "boolean") ? {} : opt;
5899 fn = fn || o.fn; scope = scope || o.scope;
5900 var el = Roo.getDom(element);
5902 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
5904 var h = function(e){
5905 e = Roo.EventObject.setEvent(e);
5908 t = e.getTarget(o.delegate, el);
5915 if(o.stopEvent === true){
5918 if(o.preventDefault === true){
5921 if(o.stopPropagation === true){
5922 e.stopPropagation();
5925 if(o.normalized === false){
5929 fn.call(scope || el, e, t, o);
5932 h = createDelayed(h, o);
5935 h = createSingle(h, el, ename, fn);
5938 h = createBuffered(h, o);
5940 fn._handlers = fn._handlers || [];
5941 fn._handlers.push([Roo.id(el), ename, h]);
5944 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
5945 el.addEventListener("DOMMouseScroll", h, false);
5946 E.on(window, 'unload', function(){
5947 el.removeEventListener("DOMMouseScroll", h, false);
5950 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5951 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
5956 var stopListening = function(el, ename, fn){
5957 var id = Roo.id(el), hds = fn._handlers, hd = fn;
5959 for(var i = 0, len = hds.length; i < len; i++){
5961 if(h[0] == id && h[1] == ename){
5968 E.un(el, ename, hd);
5969 el = Roo.getDom(el);
5970 if(ename == "mousewheel" && el.addEventListener){
5971 el.removeEventListener("DOMMouseScroll", hd, false);
5973 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5974 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
5978 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
5985 * @scope Roo.EventManager
5990 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
5991 * object with a Roo.EventObject
5992 * @param {Function} fn The method the event invokes
5993 * @param {Object} scope An object that becomes the scope of the handler
5994 * @param {boolean} override If true, the obj passed in becomes
5995 * the execution scope of the listener
5996 * @return {Function} The wrapped function
5999 wrap : function(fn, scope, override){
6001 Roo.EventObject.setEvent(e);
6002 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6007 * Appends an event handler to an element (shorthand for addListener)
6008 * @param {String/HTMLElement} element The html element or id to assign the
6009 * @param {String} eventName The type of event to listen for
6010 * @param {Function} handler The method the event invokes
6011 * @param {Object} scope (optional) The scope in which to execute the handler
6012 * function. The handler function's "this" context.
6013 * @param {Object} options (optional) An object containing handler configuration
6014 * properties. This may contain any of the following properties:<ul>
6015 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6016 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6017 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6018 * <li>preventDefault {Boolean} True to prevent the default action</li>
6019 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6020 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6021 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6022 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6023 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6024 * by the specified number of milliseconds. If the event fires again within that time, the original
6025 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6028 * <b>Combining Options</b><br>
6029 * Using the options argument, it is possible to combine different types of listeners:<br>
6031 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6033 el.on('click', this.onClick, this, {
6040 * <b>Attaching multiple handlers in 1 call</b><br>
6041 * The method also allows for a single argument to be passed which is a config object containing properties
6042 * which specify multiple handlers.
6052 fn: this.onMouseOver
6061 * Or a shorthand syntax:<br>
6064 'click' : this.onClick,
6065 'mouseover' : this.onMouseOver,
6066 'mouseout' : this.onMouseOut
6070 addListener : function(element, eventName, fn, scope, options){
6071 if(typeof eventName == "object"){
6077 if(typeof o[e] == "function"){
6079 listen(element, e, o, o[e], o.scope);
6081 // individual options
6082 listen(element, e, o[e]);
6087 return listen(element, eventName, options, fn, scope);
6091 * Removes an event handler
6093 * @param {String/HTMLElement} element The id or html element to remove the
6095 * @param {String} eventName The type of event
6096 * @param {Function} fn
6097 * @return {Boolean} True if a listener was actually removed
6099 removeListener : function(element, eventName, fn){
6100 return stopListening(element, eventName, fn);
6104 * Fires when the document is ready (before onload and before images are loaded). Can be
6105 * accessed shorthanded Roo.onReady().
6106 * @param {Function} fn The method the event invokes
6107 * @param {Object} scope An object that becomes the scope of the handler
6108 * @param {boolean} options
6110 onDocumentReady : function(fn, scope, options){
6111 if(docReadyState){ // if it already fired
6112 docReadyEvent.addListener(fn, scope, options);
6113 docReadyEvent.fire();
6114 docReadyEvent.clearListeners();
6120 docReadyEvent.addListener(fn, scope, options);
6124 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6125 * @param {Function} fn The method the event invokes
6126 * @param {Object} scope An object that becomes the scope of the handler
6127 * @param {boolean} options
6129 onWindowResize : function(fn, scope, options){
6131 resizeEvent = new Roo.util.Event();
6132 resizeTask = new Roo.util.DelayedTask(function(){
6133 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6135 E.on(window, "resize", function(){
6137 resizeTask.delay(50);
6139 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6143 resizeEvent.addListener(fn, scope, options);
6147 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6148 * @param {Function} fn The method the event invokes
6149 * @param {Object} scope An object that becomes the scope of the handler
6150 * @param {boolean} options
6152 onTextResize : function(fn, scope, options){
6154 textEvent = new Roo.util.Event();
6155 var textEl = new Roo.Element(document.createElement('div'));
6156 textEl.dom.className = 'x-text-resize';
6157 textEl.dom.innerHTML = 'X';
6158 textEl.appendTo(document.body);
6159 textSize = textEl.dom.offsetHeight;
6160 setInterval(function(){
6161 if(textEl.dom.offsetHeight != textSize){
6162 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6164 }, this.textResizeInterval);
6166 textEvent.addListener(fn, scope, options);
6170 * Removes the passed window resize listener.
6171 * @param {Function} fn The method the event invokes
6172 * @param {Object} scope The scope of handler
6174 removeResizeListener : function(fn, scope){
6176 resizeEvent.removeListener(fn, scope);
6181 fireResize : function(){
6183 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6187 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6191 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6193 textResizeInterval : 50
6198 * @scopeAlias pub=Roo.EventManager
6202 * Appends an event handler to an element (shorthand for addListener)
6203 * @param {String/HTMLElement} element The html element or id to assign the
6204 * @param {String} eventName The type of event to listen for
6205 * @param {Function} handler The method the event invokes
6206 * @param {Object} scope (optional) The scope in which to execute the handler
6207 * function. The handler function's "this" context.
6208 * @param {Object} options (optional) An object containing handler configuration
6209 * properties. This may contain any of the following properties:<ul>
6210 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6211 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6212 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6213 * <li>preventDefault {Boolean} True to prevent the default action</li>
6214 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6215 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6216 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6217 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6218 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6219 * by the specified number of milliseconds. If the event fires again within that time, the original
6220 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6223 * <b>Combining Options</b><br>
6224 * Using the options argument, it is possible to combine different types of listeners:<br>
6226 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6228 el.on('click', this.onClick, this, {
6235 * <b>Attaching multiple handlers in 1 call</b><br>
6236 * The method also allows for a single argument to be passed which is a config object containing properties
6237 * which specify multiple handlers.
6247 fn: this.onMouseOver
6256 * Or a shorthand syntax:<br>
6259 'click' : this.onClick,
6260 'mouseover' : this.onMouseOver,
6261 'mouseout' : this.onMouseOut
6265 pub.on = pub.addListener;
6266 pub.un = pub.removeListener;
6268 pub.stoppedMouseDownEvent = new Roo.util.Event();
6272 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6273 * @param {Function} fn The method the event invokes
6274 * @param {Object} scope An object that becomes the scope of the handler
6275 * @param {boolean} override If true, the obj passed in becomes
6276 * the execution scope of the listener
6280 Roo.onReady = Roo.EventManager.onDocumentReady;
6282 Roo.onReady(function(){
6283 var bd = Roo.get(document.body);
6288 : Roo.isGecko ? "roo-gecko"
6289 : Roo.isOpera ? "roo-opera"
6290 : Roo.isSafari ? "roo-safari" : ""];
6293 cls.push("roo-mac");
6296 cls.push("roo-linux");
6298 if(Roo.isBorderBox){
6299 cls.push('roo-border-box');
6301 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6302 var p = bd.dom.parentNode;
6304 p.className += ' roo-strict';
6307 bd.addClass(cls.join(' '));
6311 * @class Roo.EventObject
6312 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6313 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6316 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6318 var target = e.getTarget();
6321 var myDiv = Roo.get("myDiv");
6322 myDiv.on("click", handleClick);
6324 Roo.EventManager.on("myDiv", 'click', handleClick);
6325 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6329 Roo.EventObject = function(){
6331 var E = Roo.lib.Event;
6333 // safari keypress events for special keys return bad keycodes
6336 63235 : 39, // right
6339 63276 : 33, // page up
6340 63277 : 34, // page down
6341 63272 : 46, // delete
6346 // normalize button clicks
6347 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6348 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6350 Roo.EventObjectImpl = function(e){
6352 this.setEvent(e.browserEvent || e);
6355 Roo.EventObjectImpl.prototype = {
6357 * Used to fix doc tools.
6358 * @scope Roo.EventObject.prototype
6364 /** The normal browser event */
6365 browserEvent : null,
6366 /** The button pressed in a mouse event */
6368 /** True if the shift key was down during the event */
6370 /** True if the control key was down during the event */
6372 /** True if the alt key was down during the event */
6431 setEvent : function(e){
6432 if(e == this || (e && e.browserEvent)){ // already wrapped
6435 this.browserEvent = e;
6437 // normalize buttons
6438 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6439 if(e.type == 'click' && this.button == -1){
6443 this.shiftKey = e.shiftKey;
6444 // mac metaKey behaves like ctrlKey
6445 this.ctrlKey = e.ctrlKey || e.metaKey;
6446 this.altKey = e.altKey;
6447 // in getKey these will be normalized for the mac
6448 this.keyCode = e.keyCode;
6449 // keyup warnings on firefox.
6450 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6451 // cache the target for the delayed and or buffered events
6452 this.target = E.getTarget(e);
6454 this.xy = E.getXY(e);
6457 this.shiftKey = false;
6458 this.ctrlKey = false;
6459 this.altKey = false;
6469 * Stop the event (preventDefault and stopPropagation)
6471 stopEvent : function(){
6472 if(this.browserEvent){
6473 if(this.browserEvent.type == 'mousedown'){
6474 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6476 E.stopEvent(this.browserEvent);
6481 * Prevents the browsers default handling of the event.
6483 preventDefault : function(){
6484 if(this.browserEvent){
6485 E.preventDefault(this.browserEvent);
6490 isNavKeyPress : function(){
6491 var k = this.keyCode;
6492 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6493 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6496 isSpecialKey : function(){
6497 var k = this.keyCode;
6498 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6499 (k == 16) || (k == 17) ||
6500 (k >= 18 && k <= 20) ||
6501 (k >= 33 && k <= 35) ||
6502 (k >= 36 && k <= 39) ||
6503 (k >= 44 && k <= 45);
6506 * Cancels bubbling of the event.
6508 stopPropagation : function(){
6509 if(this.browserEvent){
6510 if(this.type == 'mousedown'){
6511 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6513 E.stopPropagation(this.browserEvent);
6518 * Gets the key code for the event.
6521 getCharCode : function(){
6522 return this.charCode || this.keyCode;
6526 * Returns a normalized keyCode for the event.
6527 * @return {Number} The key code
6529 getKey : function(){
6530 var k = this.keyCode || this.charCode;
6531 return Roo.isSafari ? (safariKeys[k] || k) : k;
6535 * Gets the x coordinate of the event.
6538 getPageX : function(){
6543 * Gets the y coordinate of the event.
6546 getPageY : function(){
6551 * Gets the time of the event.
6554 getTime : function(){
6555 if(this.browserEvent){
6556 return E.getTime(this.browserEvent);
6562 * Gets the page coordinates of the event.
6563 * @return {Array} The xy values like [x, y]
6570 * Gets the target for the event.
6571 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6572 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6573 search as a number or element (defaults to 10 || document.body)
6574 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6575 * @return {HTMLelement}
6577 getTarget : function(selector, maxDepth, returnEl){
6578 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6581 * Gets the related target.
6582 * @return {HTMLElement}
6584 getRelatedTarget : function(){
6585 if(this.browserEvent){
6586 return E.getRelatedTarget(this.browserEvent);
6592 * Normalizes mouse wheel delta across browsers
6593 * @return {Number} The delta
6595 getWheelDelta : function(){
6596 var e = this.browserEvent;
6598 if(e.wheelDelta){ /* IE/Opera. */
6599 delta = e.wheelDelta/120;
6600 }else if(e.detail){ /* Mozilla case. */
6601 delta = -e.detail/3;
6607 * Returns true if the control, meta, shift or alt key was pressed during this event.
6610 hasModifier : function(){
6611 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6615 * Returns true if the target of this event equals el or is a child of el
6616 * @param {String/HTMLElement/Element} el
6617 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6620 within : function(el, related){
6621 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6622 return t && Roo.fly(el).contains(t);
6625 getPoint : function(){
6626 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6630 return new Roo.EventObjectImpl();
6635 * Ext JS Library 1.1.1
6636 * Copyright(c) 2006-2007, Ext JS, LLC.
6638 * Originally Released Under LGPL - original licence link has changed is not relivant.
6641 * <script type="text/javascript">
6645 // was in Composite Element!??!?!
6648 var D = Roo.lib.Dom;
6649 var E = Roo.lib.Event;
6650 var A = Roo.lib.Anim;
6652 // local style camelizing for speed
6654 var camelRe = /(-[a-z])/gi;
6655 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6656 var view = document.defaultView;
6659 * @class Roo.Element
6660 * Represents an Element in the DOM.<br><br>
6663 var el = Roo.get("my-div");
6666 var el = getEl("my-div");
6668 // or with a DOM element
6669 var el = Roo.get(myDivElement);
6671 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6672 * each call instead of constructing a new one.<br><br>
6673 * <b>Animations</b><br />
6674 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6675 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6677 Option Default Description
6678 --------- -------- ---------------------------------------------
6679 duration .35 The duration of the animation in seconds
6680 easing easeOut The YUI easing method
6681 callback none A function to execute when the anim completes
6682 scope this The scope (this) of the callback function
6684 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6685 * manipulate the animation. Here's an example:
6687 var el = Roo.get("my-div");
6692 // default animation
6693 el.setWidth(100, true);
6695 // animation with some options set
6702 // using the "anim" property to get the Anim object
6708 el.setWidth(100, opt);
6710 if(opt.anim.isAnimated()){
6714 * <b> Composite (Collections of) Elements</b><br />
6715 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6716 * @constructor Create a new Element directly.
6717 * @param {String/HTMLElement} element
6718 * @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).
6720 Roo.Element = function(element, forceNew){
6721 var dom = typeof element == "string" ?
6722 document.getElementById(element) : element;
6723 if(!dom){ // invalid id/element
6727 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6728 return Roo.Element.cache[id];
6738 * The DOM element ID
6741 this.id = id || Roo.id(dom);
6744 var El = Roo.Element;
6748 * The element's default display mode (defaults to "")
6751 originalDisplay : "",
6755 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6760 * Sets the element's visibility mode. When setVisible() is called it
6761 * will use this to determine whether to set the visibility or the display property.
6762 * @param visMode Element.VISIBILITY or Element.DISPLAY
6763 * @return {Roo.Element} this
6765 setVisibilityMode : function(visMode){
6766 this.visibilityMode = visMode;
6770 * Convenience method for setVisibilityMode(Element.DISPLAY)
6771 * @param {String} display (optional) What to set display to when visible
6772 * @return {Roo.Element} this
6774 enableDisplayMode : function(display){
6775 this.setVisibilityMode(El.DISPLAY);
6776 if(typeof display != "undefined") this.originalDisplay = display;
6781 * 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)
6782 * @param {String} selector The simple selector to test
6783 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6784 search as a number or element (defaults to 10 || document.body)
6785 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6786 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6788 findParent : function(simpleSelector, maxDepth, returnEl){
6789 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6790 maxDepth = maxDepth || 50;
6791 if(typeof maxDepth != "number"){
6792 stopEl = Roo.getDom(maxDepth);
6795 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6796 if(dq.is(p, simpleSelector)){
6797 return returnEl ? Roo.get(p) : p;
6807 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6808 * @param {String} selector The simple selector to test
6809 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6810 search as a number or element (defaults to 10 || document.body)
6811 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6812 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6814 findParentNode : function(simpleSelector, maxDepth, returnEl){
6815 var p = Roo.fly(this.dom.parentNode, '_internal');
6816 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6820 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6821 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6822 * @param {String} selector The simple selector to test
6823 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6824 search as a number or element (defaults to 10 || document.body)
6825 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6827 up : function(simpleSelector, maxDepth){
6828 return this.findParentNode(simpleSelector, maxDepth, true);
6834 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6835 * @param {String} selector The simple selector to test
6836 * @return {Boolean} True if this element matches the selector, else false
6838 is : function(simpleSelector){
6839 return Roo.DomQuery.is(this.dom, simpleSelector);
6843 * Perform animation on this element.
6844 * @param {Object} args The YUI animation control args
6845 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6846 * @param {Function} onComplete (optional) Function to call when animation completes
6847 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6848 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6849 * @return {Roo.Element} this
6851 animate : function(args, duration, onComplete, easing, animType){
6852 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6857 * @private Internal animation call
6859 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6860 animType = animType || 'run';
6862 var anim = Roo.lib.Anim[animType](
6864 (opt.duration || defaultDur) || .35,
6865 (opt.easing || defaultEase) || 'easeOut',
6867 Roo.callback(cb, this);
6868 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6876 // private legacy anim prep
6877 preanim : function(a, i){
6878 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6882 * Removes worthless text nodes
6883 * @param {Boolean} forceReclean (optional) By default the element
6884 * keeps track if it has been cleaned already so
6885 * you can call this over and over. However, if you update the element and
6886 * need to force a reclean, you can pass true.
6888 clean : function(forceReclean){
6889 if(this.isCleaned && forceReclean !== true){
6893 var d = this.dom, n = d.firstChild, ni = -1;
6895 var nx = n.nextSibling;
6896 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
6903 this.isCleaned = true;
6908 calcOffsetsTo : function(el){
6911 var restorePos = false;
6912 if(el.getStyle('position') == 'static'){
6913 el.position('relative');
6918 while(op && op != d && op.tagName != 'HTML'){
6921 op = op.offsetParent;
6924 el.position('static');
6930 * Scrolls this element into view within the passed container.
6931 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
6932 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
6933 * @return {Roo.Element} this
6935 scrollIntoView : function(container, hscroll){
6936 var c = Roo.getDom(container) || document.body;
6939 var o = this.calcOffsetsTo(c),
6942 b = t+el.offsetHeight,
6943 r = l+el.offsetWidth;
6945 var ch = c.clientHeight;
6946 var ct = parseInt(c.scrollTop, 10);
6947 var cl = parseInt(c.scrollLeft, 10);
6949 var cr = cl + c.clientWidth;
6957 if(hscroll !== false){
6961 c.scrollLeft = r-c.clientWidth;
6968 scrollChildIntoView : function(child, hscroll){
6969 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
6973 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
6974 * the new height may not be available immediately.
6975 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
6976 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
6977 * @param {Function} onComplete (optional) Function to call when animation completes
6978 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
6979 * @return {Roo.Element} this
6981 autoHeight : function(animate, duration, onComplete, easing){
6982 var oldHeight = this.getHeight();
6984 this.setHeight(1); // force clipping
6985 setTimeout(function(){
6986 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
6988 this.setHeight(height);
6990 if(typeof onComplete == "function"){
6994 this.setHeight(oldHeight); // restore original height
6995 this.setHeight(height, animate, duration, function(){
6997 if(typeof onComplete == "function") onComplete();
6998 }.createDelegate(this), easing);
7000 }.createDelegate(this), 0);
7005 * Returns true if this element is an ancestor of the passed element
7006 * @param {HTMLElement/String} el The element to check
7007 * @return {Boolean} True if this element is an ancestor of el, else false
7009 contains : function(el){
7010 if(!el){return false;}
7011 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7015 * Checks whether the element is currently visible using both visibility and display properties.
7016 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7017 * @return {Boolean} True if the element is currently visible, else false
7019 isVisible : function(deep) {
7020 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7021 if(deep !== true || !vis){
7024 var p = this.dom.parentNode;
7025 while(p && p.tagName.toLowerCase() != "body"){
7026 if(!Roo.fly(p, '_isVisible').isVisible()){
7035 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7036 * @param {String} selector The CSS selector
7037 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7038 * @return {CompositeElement/CompositeElementLite} The composite element
7040 select : function(selector, unique){
7041 return El.select(selector, unique, this.dom);
7045 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7046 * @param {String} selector The CSS selector
7047 * @return {Array} An array of the matched nodes
7049 query : function(selector, unique){
7050 return Roo.DomQuery.select(selector, this.dom);
7054 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7055 * @param {String} selector The CSS selector
7056 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7057 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7059 child : function(selector, returnDom){
7060 var n = Roo.DomQuery.selectNode(selector, this.dom);
7061 return returnDom ? n : Roo.get(n);
7065 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7066 * @param {String} selector The CSS selector
7067 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7068 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7070 down : function(selector, returnDom){
7071 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7072 return returnDom ? n : Roo.get(n);
7076 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7077 * @param {String} group The group the DD object is member of
7078 * @param {Object} config The DD config object
7079 * @param {Object} overrides An object containing methods to override/implement on the DD object
7080 * @return {Roo.dd.DD} The DD object
7082 initDD : function(group, config, overrides){
7083 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7084 return Roo.apply(dd, overrides);
7088 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7089 * @param {String} group The group the DDProxy object is member of
7090 * @param {Object} config The DDProxy config object
7091 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7092 * @return {Roo.dd.DDProxy} The DDProxy object
7094 initDDProxy : function(group, config, overrides){
7095 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7096 return Roo.apply(dd, overrides);
7100 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7101 * @param {String} group The group the DDTarget object is member of
7102 * @param {Object} config The DDTarget config object
7103 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7104 * @return {Roo.dd.DDTarget} The DDTarget object
7106 initDDTarget : function(group, config, overrides){
7107 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7108 return Roo.apply(dd, overrides);
7112 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7113 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7114 * @param {Boolean} visible Whether the element is visible
7115 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7116 * @return {Roo.Element} this
7118 setVisible : function(visible, animate){
7120 if(this.visibilityMode == El.DISPLAY){
7121 this.setDisplayed(visible);
7124 this.dom.style.visibility = visible ? "visible" : "hidden";
7127 // closure for composites
7129 var visMode = this.visibilityMode;
7131 this.setOpacity(.01);
7132 this.setVisible(true);
7134 this.anim({opacity: { to: (visible?1:0) }},
7135 this.preanim(arguments, 1),
7136 null, .35, 'easeIn', function(){
7138 if(visMode == El.DISPLAY){
7139 dom.style.display = "none";
7141 dom.style.visibility = "hidden";
7143 Roo.get(dom).setOpacity(1);
7151 * Returns true if display is not "none"
7154 isDisplayed : function() {
7155 return this.getStyle("display") != "none";
7159 * Toggles the element's visibility or display, depending on visibility mode.
7160 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7161 * @return {Roo.Element} this
7163 toggle : function(animate){
7164 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7169 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7170 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7171 * @return {Roo.Element} this
7173 setDisplayed : function(value) {
7174 if(typeof value == "boolean"){
7175 value = value ? this.originalDisplay : "none";
7177 this.setStyle("display", value);
7182 * Tries to focus the element. Any exceptions are caught and ignored.
7183 * @return {Roo.Element} this
7185 focus : function() {
7193 * Tries to blur the element. Any exceptions are caught and ignored.
7194 * @return {Roo.Element} this
7204 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7205 * @param {String/Array} className The CSS class to add, or an array of classes
7206 * @return {Roo.Element} this
7208 addClass : function(className){
7209 if(className instanceof Array){
7210 for(var i = 0, len = className.length; i < len; i++) {
7211 this.addClass(className[i]);
7214 if(className && !this.hasClass(className)){
7215 this.dom.className = this.dom.className + " " + className;
7222 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7223 * @param {String/Array} className The CSS class to add, or an array of classes
7224 * @return {Roo.Element} this
7226 radioClass : function(className){
7227 var siblings = this.dom.parentNode.childNodes;
7228 for(var i = 0; i < siblings.length; i++) {
7229 var s = siblings[i];
7230 if(s.nodeType == 1){
7231 Roo.get(s).removeClass(className);
7234 this.addClass(className);
7239 * Removes one or more CSS classes from the element.
7240 * @param {String/Array} className The CSS class to remove, or an array of classes
7241 * @return {Roo.Element} this
7243 removeClass : function(className){
7244 if(!className || !this.dom.className){
7247 if(className instanceof Array){
7248 for(var i = 0, len = className.length; i < len; i++) {
7249 this.removeClass(className[i]);
7252 if(this.hasClass(className)){
7253 var re = this.classReCache[className];
7255 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7256 this.classReCache[className] = re;
7258 this.dom.className =
7259 this.dom.className.replace(re, " ");
7269 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7270 * @param {String} className The CSS class to toggle
7271 * @return {Roo.Element} this
7273 toggleClass : function(className){
7274 if(this.hasClass(className)){
7275 this.removeClass(className);
7277 this.addClass(className);
7283 * Checks if the specified CSS class exists on this element's DOM node.
7284 * @param {String} className The CSS class to check for
7285 * @return {Boolean} True if the class exists, else false
7287 hasClass : function(className){
7288 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7292 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7293 * @param {String} oldClassName The CSS class to replace
7294 * @param {String} newClassName The replacement CSS class
7295 * @return {Roo.Element} this
7297 replaceClass : function(oldClassName, newClassName){
7298 this.removeClass(oldClassName);
7299 this.addClass(newClassName);
7304 * Returns an object with properties matching the styles requested.
7305 * For example, el.getStyles('color', 'font-size', 'width') might return
7306 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7307 * @param {String} style1 A style name
7308 * @param {String} style2 A style name
7309 * @param {String} etc.
7310 * @return {Object} The style object
7312 getStyles : function(){
7313 var a = arguments, len = a.length, r = {};
7314 for(var i = 0; i < len; i++){
7315 r[a[i]] = this.getStyle(a[i]);
7321 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7322 * @param {String} property The style property whose value is returned.
7323 * @return {String} The current value of the style property for this element.
7325 getStyle : function(){
7326 return view && view.getComputedStyle ?
7328 var el = this.dom, v, cs, camel;
7329 if(prop == 'float'){
7332 if(el.style && (v = el.style[prop])){
7335 if(cs = view.getComputedStyle(el, "")){
7336 if(!(camel = propCache[prop])){
7337 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7344 var el = this.dom, v, cs, camel;
7345 if(prop == 'opacity'){
7346 if(typeof el.style.filter == 'string'){
7347 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7349 var fv = parseFloat(m[1]);
7351 return fv ? fv / 100 : 0;
7356 }else if(prop == 'float'){
7357 prop = "styleFloat";
7359 if(!(camel = propCache[prop])){
7360 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7362 if(v = el.style[camel]){
7365 if(cs = el.currentStyle){
7373 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7374 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7375 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7376 * @return {Roo.Element} this
7378 setStyle : function(prop, value){
7379 if(typeof prop == "string"){
7381 if(!(camel = propCache[prop])){
7382 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7384 if(camel == 'opacity') {
7385 this.setOpacity(value);
7387 this.dom.style[camel] = value;
7390 for(var style in prop){
7391 if(typeof prop[style] != "function"){
7392 this.setStyle(style, prop[style]);
7400 * More flexible version of {@link #setStyle} for setting style properties.
7401 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7402 * a function which returns such a specification.
7403 * @return {Roo.Element} this
7405 applyStyles : function(style){
7406 Roo.DomHelper.applyStyles(this.dom, style);
7411 * 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).
7412 * @return {Number} The X position of the element
7415 return D.getX(this.dom);
7419 * 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).
7420 * @return {Number} The Y position of the element
7423 return D.getY(this.dom);
7427 * 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).
7428 * @return {Array} The XY position of the element
7431 return D.getXY(this.dom);
7435 * 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).
7436 * @param {Number} The X position of the element
7437 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7438 * @return {Roo.Element} this
7440 setX : function(x, animate){
7442 D.setX(this.dom, x);
7444 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7450 * 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).
7451 * @param {Number} The Y position of the element
7452 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7453 * @return {Roo.Element} this
7455 setY : function(y, animate){
7457 D.setY(this.dom, y);
7459 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7465 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7466 * @param {String} left The left CSS property value
7467 * @return {Roo.Element} this
7469 setLeft : function(left){
7470 this.setStyle("left", this.addUnits(left));
7475 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7476 * @param {String} top The top CSS property value
7477 * @return {Roo.Element} this
7479 setTop : function(top){
7480 this.setStyle("top", this.addUnits(top));
7485 * Sets the element's CSS right style.
7486 * @param {String} right The right CSS property value
7487 * @return {Roo.Element} this
7489 setRight : function(right){
7490 this.setStyle("right", this.addUnits(right));
7495 * Sets the element's CSS bottom style.
7496 * @param {String} bottom The bottom CSS property value
7497 * @return {Roo.Element} this
7499 setBottom : function(bottom){
7500 this.setStyle("bottom", this.addUnits(bottom));
7505 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7506 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7507 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7508 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7509 * @return {Roo.Element} this
7511 setXY : function(pos, animate){
7513 D.setXY(this.dom, pos);
7515 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7521 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7522 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7523 * @param {Number} x X value for new position (coordinates are page-based)
7524 * @param {Number} y Y value for new position (coordinates are page-based)
7525 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7526 * @return {Roo.Element} this
7528 setLocation : function(x, y, animate){
7529 this.setXY([x, y], this.preanim(arguments, 2));
7534 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7535 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7536 * @param {Number} x X value for new position (coordinates are page-based)
7537 * @param {Number} y Y value for new position (coordinates are page-based)
7538 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7539 * @return {Roo.Element} this
7541 moveTo : function(x, y, animate){
7542 this.setXY([x, y], this.preanim(arguments, 2));
7547 * Returns the region of the given element.
7548 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7549 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7551 getRegion : function(){
7552 return D.getRegion(this.dom);
7556 * Returns the offset height of the element
7557 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7558 * @return {Number} The element's height
7560 getHeight : function(contentHeight){
7561 var h = this.dom.offsetHeight || 0;
7562 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7566 * Returns the offset width of the element
7567 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7568 * @return {Number} The element's width
7570 getWidth : function(contentWidth){
7571 var w = this.dom.offsetWidth || 0;
7572 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7576 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7577 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7578 * if a height has not been set using CSS.
7581 getComputedHeight : function(){
7582 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7584 h = parseInt(this.getStyle('height'), 10) || 0;
7585 if(!this.isBorderBox()){
7586 h += this.getFrameWidth('tb');
7593 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7594 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7595 * if a width has not been set using CSS.
7598 getComputedWidth : function(){
7599 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7601 w = parseInt(this.getStyle('width'), 10) || 0;
7602 if(!this.isBorderBox()){
7603 w += this.getFrameWidth('lr');
7610 * Returns the size of the element.
7611 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7612 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7614 getSize : function(contentSize){
7615 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7619 * Returns the width and height of the viewport.
7620 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7622 getViewSize : function(){
7623 var d = this.dom, doc = document, aw = 0, ah = 0;
7624 if(d == doc || d == doc.body){
7625 return {width : D.getViewWidth(), height: D.getViewHeight()};
7628 width : d.clientWidth,
7629 height: d.clientHeight
7635 * Returns the value of the "value" attribute
7636 * @param {Boolean} asNumber true to parse the value as a number
7637 * @return {String/Number}
7639 getValue : function(asNumber){
7640 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7644 adjustWidth : function(width){
7645 if(typeof width == "number"){
7646 if(this.autoBoxAdjust && !this.isBorderBox()){
7647 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7657 adjustHeight : function(height){
7658 if(typeof height == "number"){
7659 if(this.autoBoxAdjust && !this.isBorderBox()){
7660 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7670 * Set the width of the element
7671 * @param {Number} width The new width
7672 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7673 * @return {Roo.Element} this
7675 setWidth : function(width, animate){
7676 width = this.adjustWidth(width);
7678 this.dom.style.width = this.addUnits(width);
7680 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7686 * Set the height of the element
7687 * @param {Number} height The new height
7688 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7689 * @return {Roo.Element} this
7691 setHeight : function(height, animate){
7692 height = this.adjustHeight(height);
7694 this.dom.style.height = this.addUnits(height);
7696 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7702 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7703 * @param {Number} width The new width
7704 * @param {Number} height The new height
7705 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7706 * @return {Roo.Element} this
7708 setSize : function(width, height, animate){
7709 if(typeof width == "object"){ // in case of object from getSize()
7710 height = width.height; width = width.width;
7712 width = this.adjustWidth(width); height = this.adjustHeight(height);
7714 this.dom.style.width = this.addUnits(width);
7715 this.dom.style.height = this.addUnits(height);
7717 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7723 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7724 * @param {Number} x X value for new position (coordinates are page-based)
7725 * @param {Number} y Y value for new position (coordinates are page-based)
7726 * @param {Number} width The new width
7727 * @param {Number} height The new height
7728 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7729 * @return {Roo.Element} this
7731 setBounds : function(x, y, width, height, animate){
7733 this.setSize(width, height);
7734 this.setLocation(x, y);
7736 width = this.adjustWidth(width); height = this.adjustHeight(height);
7737 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7738 this.preanim(arguments, 4), 'motion');
7744 * 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.
7745 * @param {Roo.lib.Region} region The region to fill
7746 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7747 * @return {Roo.Element} this
7749 setRegion : function(region, animate){
7750 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7755 * Appends an event handler
7757 * @param {String} eventName The type of event to append
7758 * @param {Function} fn The method the event invokes
7759 * @param {Object} scope (optional) The scope (this object) of the fn
7760 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7762 addListener : function(eventName, fn, scope, options){
7763 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7767 * Removes an event handler from this element
7768 * @param {String} eventName the type of event to remove
7769 * @param {Function} fn the method the event invokes
7770 * @return {Roo.Element} this
7772 removeListener : function(eventName, fn){
7773 Roo.EventManager.removeListener(this.dom, eventName, fn);
7778 * Removes all previous added listeners from this element
7779 * @return {Roo.Element} this
7781 removeAllListeners : function(){
7782 E.purgeElement(this.dom);
7786 relayEvent : function(eventName, observable){
7787 this.on(eventName, function(e){
7788 observable.fireEvent(eventName, e);
7793 * Set the opacity of the element
7794 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7795 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7796 * @return {Roo.Element} this
7798 setOpacity : function(opacity, animate){
7800 var s = this.dom.style;
7803 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7804 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7806 s.opacity = opacity;
7809 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7815 * Gets the left X coordinate
7816 * @param {Boolean} local True to get the local css position instead of page coordinate
7819 getLeft : function(local){
7823 return parseInt(this.getStyle("left"), 10) || 0;
7828 * Gets the right X coordinate of the element (element X position + element width)
7829 * @param {Boolean} local True to get the local css position instead of page coordinate
7832 getRight : function(local){
7834 return this.getX() + this.getWidth();
7836 return (this.getLeft(true) + this.getWidth()) || 0;
7841 * Gets the top Y coordinate
7842 * @param {Boolean} local True to get the local css position instead of page coordinate
7845 getTop : function(local) {
7849 return parseInt(this.getStyle("top"), 10) || 0;
7854 * Gets the bottom Y coordinate of the element (element Y position + element height)
7855 * @param {Boolean} local True to get the local css position instead of page coordinate
7858 getBottom : function(local){
7860 return this.getY() + this.getHeight();
7862 return (this.getTop(true) + this.getHeight()) || 0;
7867 * Initializes positioning on this element. If a desired position is not passed, it will make the
7868 * the element positioned relative IF it is not already positioned.
7869 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7870 * @param {Number} zIndex (optional) The zIndex to apply
7871 * @param {Number} x (optional) Set the page X position
7872 * @param {Number} y (optional) Set the page Y position
7874 position : function(pos, zIndex, x, y){
7876 if(this.getStyle('position') == 'static'){
7877 this.setStyle('position', 'relative');
7880 this.setStyle("position", pos);
7883 this.setStyle("z-index", zIndex);
7885 if(x !== undefined && y !== undefined){
7887 }else if(x !== undefined){
7889 }else if(y !== undefined){
7895 * Clear positioning back to the default when the document was loaded
7896 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7897 * @return {Roo.Element} this
7899 clearPositioning : function(value){
7907 "position" : "static"
7913 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7914 * snapshot before performing an update and then restoring the element.
7917 getPositioning : function(){
7918 var l = this.getStyle("left");
7919 var t = this.getStyle("top");
7921 "position" : this.getStyle("position"),
7923 "right" : l ? "" : this.getStyle("right"),
7925 "bottom" : t ? "" : this.getStyle("bottom"),
7926 "z-index" : this.getStyle("z-index")
7931 * Gets the width of the border(s) for the specified side(s)
7932 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7933 * passing lr would get the border (l)eft width + the border (r)ight width.
7934 * @return {Number} The width of the sides passed added together
7936 getBorderWidth : function(side){
7937 return this.addStyles(side, El.borders);
7941 * Gets the width of the padding(s) for the specified side(s)
7942 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7943 * passing lr would get the padding (l)eft + the padding (r)ight.
7944 * @return {Number} The padding of the sides passed added together
7946 getPadding : function(side){
7947 return this.addStyles(side, El.paddings);
7951 * Set positioning with an object returned by getPositioning().
7952 * @param {Object} posCfg
7953 * @return {Roo.Element} this
7955 setPositioning : function(pc){
7956 this.applyStyles(pc);
7957 if(pc.right == "auto"){
7958 this.dom.style.right = "";
7960 if(pc.bottom == "auto"){
7961 this.dom.style.bottom = "";
7967 fixDisplay : function(){
7968 if(this.getStyle("display") == "none"){
7969 this.setStyle("visibility", "hidden");
7970 this.setStyle("display", this.originalDisplay); // first try reverting to default
7971 if(this.getStyle("display") == "none"){ // if that fails, default to block
7972 this.setStyle("display", "block");
7978 * Quick set left and top adding default units
7979 * @param {String} left The left CSS property value
7980 * @param {String} top The top CSS property value
7981 * @return {Roo.Element} this
7983 setLeftTop : function(left, top){
7984 this.dom.style.left = this.addUnits(left);
7985 this.dom.style.top = this.addUnits(top);
7990 * Move this element relative to its current position.
7991 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
7992 * @param {Number} distance How far to move the element in pixels
7993 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7994 * @return {Roo.Element} this
7996 move : function(direction, distance, animate){
7997 var xy = this.getXY();
7998 direction = direction.toLowerCase();
8002 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8006 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8011 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8016 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8023 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8024 * @return {Roo.Element} this
8027 if(!this.isClipped){
8028 this.isClipped = true;
8029 this.originalClip = {
8030 "o": this.getStyle("overflow"),
8031 "x": this.getStyle("overflow-x"),
8032 "y": this.getStyle("overflow-y")
8034 this.setStyle("overflow", "hidden");
8035 this.setStyle("overflow-x", "hidden");
8036 this.setStyle("overflow-y", "hidden");
8042 * Return clipping (overflow) to original clipping before clip() was called
8043 * @return {Roo.Element} this
8045 unclip : function(){
8047 this.isClipped = false;
8048 var o = this.originalClip;
8049 if(o.o){this.setStyle("overflow", o.o);}
8050 if(o.x){this.setStyle("overflow-x", o.x);}
8051 if(o.y){this.setStyle("overflow-y", o.y);}
8058 * Gets the x,y coordinates specified by the anchor position on the element.
8059 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8060 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8061 * {width: (target width), height: (target height)} (defaults to the element's current size)
8062 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8063 * @return {Array} [x, y] An array containing the element's x and y coordinates
8065 getAnchorXY : function(anchor, local, s){
8066 //Passing a different size is useful for pre-calculating anchors,
8067 //especially for anchored animations that change the el size.
8069 var w, h, vp = false;
8072 if(d == document.body || d == document){
8074 w = D.getViewWidth(); h = D.getViewHeight();
8076 w = this.getWidth(); h = this.getHeight();
8079 w = s.width; h = s.height;
8081 var x = 0, y = 0, r = Math.round;
8082 switch((anchor || "tl").toLowerCase()){
8124 var sc = this.getScroll();
8125 return [x + sc.left, y + sc.top];
8127 //Add the element's offset xy
8128 var o = this.getXY();
8129 return [x+o[0], y+o[1]];
8133 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8134 * supported position values.
8135 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8136 * @param {String} position The position to align to.
8137 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8138 * @return {Array} [x, y]
8140 getAlignToXY : function(el, p, o){
8144 throw "Element.alignTo with an element that doesn't exist";
8146 var c = false; //constrain to viewport
8147 var p1 = "", p2 = "";
8154 }else if(p.indexOf("-") == -1){
8157 p = p.toLowerCase();
8158 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8160 throw "Element.alignTo with an invalid alignment " + p;
8162 p1 = m[1]; p2 = m[2]; c = !!m[3];
8164 //Subtract the aligned el's internal xy from the target's offset xy
8165 //plus custom offset to get the aligned el's new offset xy
8166 var a1 = this.getAnchorXY(p1, true);
8167 var a2 = el.getAnchorXY(p2, false);
8168 var x = a2[0] - a1[0] + o[0];
8169 var y = a2[1] - a1[1] + o[1];
8171 //constrain the aligned el to viewport if necessary
8172 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8173 // 5px of margin for ie
8174 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8176 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8177 //perpendicular to the vp border, allow the aligned el to slide on that border,
8178 //otherwise swap the aligned el to the opposite border of the target.
8179 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8180 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8181 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8182 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8185 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8186 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8188 if((x+w) > dw + scrollX){
8189 x = swapX ? r.left-w : dw+scrollX-w;
8192 x = swapX ? r.right : scrollX;
8194 if((y+h) > dh + scrollY){
8195 y = swapY ? r.top-h : dh+scrollY-h;
8198 y = swapY ? r.bottom : scrollY;
8205 getConstrainToXY : function(){
8206 var os = {top:0, left:0, bottom:0, right: 0};
8208 return function(el, local, offsets, proposedXY){
8210 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8212 var vw, vh, vx = 0, vy = 0;
8213 if(el.dom == document.body || el.dom == document){
8214 vw = Roo.lib.Dom.getViewWidth();
8215 vh = Roo.lib.Dom.getViewHeight();
8217 vw = el.dom.clientWidth;
8218 vh = el.dom.clientHeight;
8220 var vxy = el.getXY();
8226 var s = el.getScroll();
8228 vx += offsets.left + s.left;
8229 vy += offsets.top + s.top;
8231 vw -= offsets.right;
8232 vh -= offsets.bottom;
8237 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8238 var x = xy[0], y = xy[1];
8239 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8241 // only move it if it needs it
8244 // first validate right/bottom
8253 // then make sure top/left isn't negative
8262 return moved ? [x, y] : false;
8267 adjustForConstraints : function(xy, parent, offsets){
8268 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8272 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8273 * document it aligns it to the viewport.
8274 * The position parameter is optional, and can be specified in any one of the following formats:
8276 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8277 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8278 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8279 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8280 * <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
8281 * element's anchor point, and the second value is used as the target's anchor point.</li>
8283 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8284 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8285 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8286 * that specified in order to enforce the viewport constraints.
8287 * Following are all of the supported anchor positions:
8290 ----- -----------------------------
8291 tl The top left corner (default)
8292 t The center of the top edge
8293 tr The top right corner
8294 l The center of the left edge
8295 c In the center of the element
8296 r The center of the right edge
8297 bl The bottom left corner
8298 b The center of the bottom edge
8299 br The bottom right corner
8303 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8304 el.alignTo("other-el");
8306 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8307 el.alignTo("other-el", "tr?");
8309 // align the bottom right corner of el with the center left edge of other-el
8310 el.alignTo("other-el", "br-l?");
8312 // align the center of el with the bottom left corner of other-el and
8313 // adjust the x position by -6 pixels (and the y position by 0)
8314 el.alignTo("other-el", "c-bl", [-6, 0]);
8316 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8317 * @param {String} position The position to align to.
8318 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8319 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8320 * @return {Roo.Element} this
8322 alignTo : function(element, position, offsets, animate){
8323 var xy = this.getAlignToXY(element, position, offsets);
8324 this.setXY(xy, this.preanim(arguments, 3));
8329 * Anchors an element to another element and realigns it when the window is resized.
8330 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8331 * @param {String} position The position to align to.
8332 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8333 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8334 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8335 * is a number, it is used as the buffer delay (defaults to 50ms).
8336 * @param {Function} callback The function to call after the animation finishes
8337 * @return {Roo.Element} this
8339 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8340 var action = function(){
8341 this.alignTo(el, alignment, offsets, animate);
8342 Roo.callback(callback, this);
8344 Roo.EventManager.onWindowResize(action, this);
8345 var tm = typeof monitorScroll;
8346 if(tm != 'undefined'){
8347 Roo.EventManager.on(window, 'scroll', action, this,
8348 {buffer: tm == 'number' ? monitorScroll : 50});
8350 action.call(this); // align immediately
8354 * Clears any opacity settings from this element. Required in some cases for IE.
8355 * @return {Roo.Element} this
8357 clearOpacity : function(){
8358 if (window.ActiveXObject) {
8359 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8360 this.dom.style.filter = "";
8363 this.dom.style.opacity = "";
8364 this.dom.style["-moz-opacity"] = "";
8365 this.dom.style["-khtml-opacity"] = "";
8371 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8372 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8373 * @return {Roo.Element} this
8375 hide : function(animate){
8376 this.setVisible(false, this.preanim(arguments, 0));
8381 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8382 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8383 * @return {Roo.Element} this
8385 show : function(animate){
8386 this.setVisible(true, this.preanim(arguments, 0));
8391 * @private Test if size has a unit, otherwise appends the default
8393 addUnits : function(size){
8394 return Roo.Element.addUnits(size, this.defaultUnit);
8398 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8399 * @return {Roo.Element} this
8401 beginMeasure : function(){
8403 if(el.offsetWidth || el.offsetHeight){
8404 return this; // offsets work already
8407 var p = this.dom, b = document.body; // start with this element
8408 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8409 var pe = Roo.get(p);
8410 if(pe.getStyle('display') == 'none'){
8411 changed.push({el: p, visibility: pe.getStyle("visibility")});
8412 p.style.visibility = "hidden";
8413 p.style.display = "block";
8417 this._measureChanged = changed;
8423 * Restores displays to before beginMeasure was called
8424 * @return {Roo.Element} this
8426 endMeasure : function(){
8427 var changed = this._measureChanged;
8429 for(var i = 0, len = changed.length; i < len; i++) {
8431 r.el.style.visibility = r.visibility;
8432 r.el.style.display = "none";
8434 this._measureChanged = null;
8440 * Update the innerHTML of this element, optionally searching for and processing scripts
8441 * @param {String} html The new HTML
8442 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8443 * @param {Function} callback For async script loading you can be noticed when the update completes
8444 * @return {Roo.Element} this
8446 update : function(html, loadScripts, callback){
8447 if(typeof html == "undefined"){
8450 if(loadScripts !== true){
8451 this.dom.innerHTML = html;
8452 if(typeof callback == "function"){
8460 html += '<span id="' + id + '"></span>';
8462 E.onAvailable(id, function(){
8463 var hd = document.getElementsByTagName("head")[0];
8464 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8465 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8466 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8469 while(match = re.exec(html)){
8470 var attrs = match[1];
8471 var srcMatch = attrs ? attrs.match(srcRe) : false;
8472 if(srcMatch && srcMatch[2]){
8473 var s = document.createElement("script");
8474 s.src = srcMatch[2];
8475 var typeMatch = attrs.match(typeRe);
8476 if(typeMatch && typeMatch[2]){
8477 s.type = typeMatch[2];
8480 }else if(match[2] && match[2].length > 0){
8481 if(window.execScript) {
8482 window.execScript(match[2]);
8490 window.eval(match[2]);
8494 var el = document.getElementById(id);
8495 if(el){el.parentNode.removeChild(el);}
8496 if(typeof callback == "function"){
8500 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8505 * Direct access to the UpdateManager update() method (takes the same parameters).
8506 * @param {String/Function} url The url for this request or a function to call to get the url
8507 * @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}
8508 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8509 * @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.
8510 * @return {Roo.Element} this
8513 var um = this.getUpdateManager();
8514 um.update.apply(um, arguments);
8519 * Gets this element's UpdateManager
8520 * @return {Roo.UpdateManager} The UpdateManager
8522 getUpdateManager : function(){
8523 if(!this.updateManager){
8524 this.updateManager = new Roo.UpdateManager(this);
8526 return this.updateManager;
8530 * Disables text selection for this element (normalized across browsers)
8531 * @return {Roo.Element} this
8533 unselectable : function(){
8534 this.dom.unselectable = "on";
8535 this.swallowEvent("selectstart", true);
8536 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8537 this.addClass("x-unselectable");
8542 * Calculates the x, y to center this element on the screen
8543 * @return {Array} The x, y values [x, y]
8545 getCenterXY : function(){
8546 return this.getAlignToXY(document, 'c-c');
8550 * Centers the Element in either the viewport, or another Element.
8551 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8553 center : function(centerIn){
8554 this.alignTo(centerIn || document, 'c-c');
8559 * Tests various css rules/browsers to determine if this element uses a border box
8562 isBorderBox : function(){
8563 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8567 * Return a box {x, y, width, height} that can be used to set another elements
8568 * size/location to match this element.
8569 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8570 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8571 * @return {Object} box An object in the format {x, y, width, height}
8573 getBox : function(contentBox, local){
8578 var left = parseInt(this.getStyle("left"), 10) || 0;
8579 var top = parseInt(this.getStyle("top"), 10) || 0;
8582 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8584 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8586 var l = this.getBorderWidth("l")+this.getPadding("l");
8587 var r = this.getBorderWidth("r")+this.getPadding("r");
8588 var t = this.getBorderWidth("t")+this.getPadding("t");
8589 var b = this.getBorderWidth("b")+this.getPadding("b");
8590 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)};
8592 bx.right = bx.x + bx.width;
8593 bx.bottom = bx.y + bx.height;
8598 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8599 for more information about the sides.
8600 * @param {String} sides
8603 getFrameWidth : function(sides, onlyContentBox){
8604 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8608 * 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.
8609 * @param {Object} box The box to fill {x, y, width, height}
8610 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8611 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8612 * @return {Roo.Element} this
8614 setBox : function(box, adjust, animate){
8615 var w = box.width, h = box.height;
8616 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8617 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8618 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8620 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8625 * Forces the browser to repaint this element
8626 * @return {Roo.Element} this
8628 repaint : function(){
8630 this.addClass("x-repaint");
8631 setTimeout(function(){
8632 Roo.get(dom).removeClass("x-repaint");
8638 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8639 * then it returns the calculated width of the sides (see getPadding)
8640 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8641 * @return {Object/Number}
8643 getMargins : function(side){
8646 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8647 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8648 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8649 right: parseInt(this.getStyle("margin-right"), 10) || 0
8652 return this.addStyles(side, El.margins);
8657 addStyles : function(sides, styles){
8659 for(var i = 0, len = sides.length; i < len; i++){
8660 v = this.getStyle(styles[sides.charAt(i)]);
8662 w = parseInt(v, 10);
8670 * Creates a proxy element of this element
8671 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8672 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8673 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8674 * @return {Roo.Element} The new proxy element
8676 createProxy : function(config, renderTo, matchBox){
8678 renderTo = Roo.getDom(renderTo);
8680 renderTo = document.body;
8682 config = typeof config == "object" ?
8683 config : {tag : "div", cls: config};
8684 var proxy = Roo.DomHelper.append(renderTo, config, true);
8686 proxy.setBox(this.getBox());
8692 * Puts a mask over this element to disable user interaction. Requires core.css.
8693 * This method can only be applied to elements which accept child nodes.
8694 * @param {String} msg (optional) A message to display in the mask
8695 * @param {String} msgCls (optional) A css class to apply to the msg element
8696 * @return {Element} The mask element
8698 mask : function(msg, msgCls){
8699 if(this.getStyle("position") == "static"){
8700 this.setStyle("position", "relative");
8703 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8705 this.addClass("x-masked");
8706 this._mask.setDisplayed(true);
8707 if(typeof msg == 'string'){
8709 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8711 var mm = this._maskMsg;
8712 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8713 mm.dom.firstChild.innerHTML = msg;
8714 mm.setDisplayed(true);
8717 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8718 this._mask.setHeight(this.getHeight());
8724 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8725 * it is cached for reuse.
8727 unmask : function(removeEl){
8729 if(removeEl === true){
8730 this._mask.remove();
8733 this._maskMsg.remove();
8734 delete this._maskMsg;
8737 this._mask.setDisplayed(false);
8739 this._maskMsg.setDisplayed(false);
8743 this.removeClass("x-masked");
8747 * Returns true if this element is masked
8750 isMasked : function(){
8751 return this._mask && this._mask.isVisible();
8755 * Creates an iframe shim for this element to keep selects and other windowed objects from
8757 * @return {Roo.Element} The new shim element
8759 createShim : function(){
8760 var el = document.createElement('iframe');
8761 el.frameBorder = 'no';
8762 el.className = 'roo-shim';
8763 if(Roo.isIE && Roo.isSecure){
8764 el.src = Roo.SSL_SECURE_URL;
8766 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8767 shim.autoBoxAdjust = false;
8772 * Removes this element from the DOM and deletes it from the cache
8774 remove : function(){
8775 if(this.dom.parentNode){
8776 this.dom.parentNode.removeChild(this.dom);
8778 delete El.cache[this.dom.id];
8782 * Sets up event handlers to add and remove a css class when the mouse is over this element
8783 * @param {String} className
8784 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8785 * mouseout events for children elements
8786 * @return {Roo.Element} this
8788 addClassOnOver : function(className, preventFlicker){
8789 this.on("mouseover", function(){
8790 Roo.fly(this, '_internal').addClass(className);
8792 var removeFn = function(e){
8793 if(preventFlicker !== true || !e.within(this, true)){
8794 Roo.fly(this, '_internal').removeClass(className);
8797 this.on("mouseout", removeFn, this.dom);
8802 * Sets up event handlers to add and remove a css class when this element has the focus
8803 * @param {String} className
8804 * @return {Roo.Element} this
8806 addClassOnFocus : function(className){
8807 this.on("focus", function(){
8808 Roo.fly(this, '_internal').addClass(className);
8810 this.on("blur", function(){
8811 Roo.fly(this, '_internal').removeClass(className);
8816 * 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)
8817 * @param {String} className
8818 * @return {Roo.Element} this
8820 addClassOnClick : function(className){
8822 this.on("mousedown", function(){
8823 Roo.fly(dom, '_internal').addClass(className);
8824 var d = Roo.get(document);
8825 var fn = function(){
8826 Roo.fly(dom, '_internal').removeClass(className);
8827 d.removeListener("mouseup", fn);
8829 d.on("mouseup", fn);
8835 * Stops the specified event from bubbling and optionally prevents the default action
8836 * @param {String} eventName
8837 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8838 * @return {Roo.Element} this
8840 swallowEvent : function(eventName, preventDefault){
8841 var fn = function(e){
8842 e.stopPropagation();
8847 if(eventName instanceof Array){
8848 for(var i = 0, len = eventName.length; i < len; i++){
8849 this.on(eventName[i], fn);
8853 this.on(eventName, fn);
8860 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8863 * Sizes this element to its parent element's dimensions performing
8864 * neccessary box adjustments.
8865 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8866 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8867 * @return {Roo.Element} this
8869 fitToParent : function(monitorResize, targetParent) {
8870 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8871 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8872 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8875 var p = Roo.get(targetParent || this.dom.parentNode);
8876 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8877 if (monitorResize === true) {
8878 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8879 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8885 * Gets the next sibling, skipping text nodes
8886 * @return {HTMLElement} The next sibling or null
8888 getNextSibling : function(){
8889 var n = this.dom.nextSibling;
8890 while(n && n.nodeType != 1){
8897 * Gets the previous sibling, skipping text nodes
8898 * @return {HTMLElement} The previous sibling or null
8900 getPrevSibling : function(){
8901 var n = this.dom.previousSibling;
8902 while(n && n.nodeType != 1){
8903 n = n.previousSibling;
8910 * Appends the passed element(s) to this element
8911 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8912 * @return {Roo.Element} this
8914 appendChild: function(el){
8921 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8922 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8923 * automatically generated with the specified attributes.
8924 * @param {HTMLElement} insertBefore (optional) a child element of this element
8925 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8926 * @return {Roo.Element} The new child element
8928 createChild: function(config, insertBefore, returnDom){
8929 config = config || {tag:'div'};
8931 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8933 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8937 * Appends this element to the passed element
8938 * @param {String/HTMLElement/Element} el The new parent element
8939 * @return {Roo.Element} this
8941 appendTo: function(el){
8942 el = Roo.getDom(el);
8943 el.appendChild(this.dom);
8948 * Inserts this element before the passed element in the DOM
8949 * @param {String/HTMLElement/Element} el The element to insert before
8950 * @return {Roo.Element} this
8952 insertBefore: function(el){
8953 el = Roo.getDom(el);
8954 el.parentNode.insertBefore(this.dom, el);
8959 * Inserts this element after the passed element in the DOM
8960 * @param {String/HTMLElement/Element} el The element to insert after
8961 * @return {Roo.Element} this
8963 insertAfter: function(el){
8964 el = Roo.getDom(el);
8965 el.parentNode.insertBefore(this.dom, el.nextSibling);
8970 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
8971 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8972 * @return {Roo.Element} The new child
8974 insertFirst: function(el, returnDom){
8976 if(typeof el == 'object' && !el.nodeType){ // dh config
8977 return this.createChild(el, this.dom.firstChild, returnDom);
8979 el = Roo.getDom(el);
8980 this.dom.insertBefore(el, this.dom.firstChild);
8981 return !returnDom ? Roo.get(el) : el;
8986 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
8987 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8988 * @param {String} where (optional) 'before' or 'after' defaults to before
8989 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8990 * @return {Roo.Element} the inserted Element
8992 insertSibling: function(el, where, returnDom){
8993 where = where ? where.toLowerCase() : 'before';
8995 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
8997 if(typeof el == 'object' && !el.nodeType){ // dh config
8998 if(where == 'after' && !this.dom.nextSibling){
8999 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9001 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9005 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9006 where == 'before' ? this.dom : this.dom.nextSibling);
9015 * Creates and wraps this element with another element
9016 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9017 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9018 * @return {HTMLElement/Element} The newly created wrapper element
9020 wrap: function(config, returnDom){
9022 config = {tag: "div"};
9024 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9025 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9030 * Replaces the passed element with this element
9031 * @param {String/HTMLElement/Element} el The element to replace
9032 * @return {Roo.Element} this
9034 replace: function(el){
9036 this.insertBefore(el);
9042 * Inserts an html fragment into this element
9043 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9044 * @param {String} html The HTML fragment
9045 * @param {Boolean} returnEl True to return an Roo.Element
9046 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9048 insertHtml : function(where, html, returnEl){
9049 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9050 return returnEl ? Roo.get(el) : el;
9054 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9055 * @param {Object} o The object with the attributes
9056 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9057 * @return {Roo.Element} this
9059 set : function(o, useSet){
9061 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9063 if(attr == "style" || typeof o[attr] == "function") continue;
9065 el.className = o["cls"];
9067 if(useSet) el.setAttribute(attr, o[attr]);
9068 else el[attr] = o[attr];
9072 Roo.DomHelper.applyStyles(el, o.style);
9078 * Convenience method for constructing a KeyMap
9079 * @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:
9080 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9081 * @param {Function} fn The function to call
9082 * @param {Object} scope (optional) The scope of the function
9083 * @return {Roo.KeyMap} The KeyMap created
9085 addKeyListener : function(key, fn, scope){
9087 if(typeof key != "object" || key instanceof Array){
9103 return new Roo.KeyMap(this, config);
9107 * Creates a KeyMap for this element
9108 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9109 * @return {Roo.KeyMap} The KeyMap created
9111 addKeyMap : function(config){
9112 return new Roo.KeyMap(this, config);
9116 * Returns true if this element is scrollable.
9119 isScrollable : function(){
9121 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9125 * 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().
9126 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9127 * @param {Number} value The new scroll value
9128 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9129 * @return {Element} this
9132 scrollTo : function(side, value, animate){
9133 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9135 this.dom[prop] = value;
9137 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9138 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9144 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9145 * within this element's scrollable range.
9146 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9147 * @param {Number} distance How far to scroll the element in pixels
9148 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9149 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9150 * was scrolled as far as it could go.
9152 scroll : function(direction, distance, animate){
9153 if(!this.isScrollable()){
9157 var l = el.scrollLeft, t = el.scrollTop;
9158 var w = el.scrollWidth, h = el.scrollHeight;
9159 var cw = el.clientWidth, ch = el.clientHeight;
9160 direction = direction.toLowerCase();
9161 var scrolled = false;
9162 var a = this.preanim(arguments, 2);
9167 var v = Math.min(l + distance, w-cw);
9168 this.scrollTo("left", v, a);
9175 var v = Math.max(l - distance, 0);
9176 this.scrollTo("left", v, a);
9184 var v = Math.max(t - distance, 0);
9185 this.scrollTo("top", v, a);
9193 var v = Math.min(t + distance, h-ch);
9194 this.scrollTo("top", v, a);
9203 * Translates the passed page coordinates into left/top css values for this element
9204 * @param {Number/Array} x The page x or an array containing [x, y]
9205 * @param {Number} y The page y
9206 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9208 translatePoints : function(x, y){
9209 if(typeof x == 'object' || x instanceof Array){
9212 var p = this.getStyle('position');
9213 var o = this.getXY();
9215 var l = parseInt(this.getStyle('left'), 10);
9216 var t = parseInt(this.getStyle('top'), 10);
9219 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9222 t = (p == "relative") ? 0 : this.dom.offsetTop;
9225 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9229 * Returns the current scroll position of the element.
9230 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9232 getScroll : function(){
9233 var d = this.dom, doc = document;
9234 if(d == doc || d == doc.body){
9235 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9236 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9237 return {left: l, top: t};
9239 return {left: d.scrollLeft, top: d.scrollTop};
9244 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9245 * are convert to standard 6 digit hex color.
9246 * @param {String} attr The css attribute
9247 * @param {String} defaultValue The default value to use when a valid color isn't found
9248 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9251 getColor : function(attr, defaultValue, prefix){
9252 var v = this.getStyle(attr);
9253 if(!v || v == "transparent" || v == "inherit") {
9254 return defaultValue;
9256 var color = typeof prefix == "undefined" ? "#" : prefix;
9257 if(v.substr(0, 4) == "rgb("){
9258 var rvs = v.slice(4, v.length -1).split(",");
9259 for(var i = 0; i < 3; i++){
9260 var h = parseInt(rvs[i]).toString(16);
9267 if(v.substr(0, 1) == "#"){
9269 for(var i = 1; i < 4; i++){
9270 var c = v.charAt(i);
9273 }else if(v.length == 7){
9274 color += v.substr(1);
9278 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9282 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9283 * gradient background, rounded corners and a 4-way shadow.
9284 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9285 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9286 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9287 * @return {Roo.Element} this
9289 boxWrap : function(cls){
9290 cls = cls || 'x-box';
9291 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9292 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9297 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9298 * @param {String} namespace The namespace in which to look for the attribute
9299 * @param {String} name The attribute name
9300 * @return {String} The attribute value
9302 getAttributeNS : Roo.isIE ? function(ns, name){
9304 var type = typeof d[ns+":"+name];
9305 if(type != 'undefined' && type != 'unknown'){
9306 return d[ns+":"+name];
9309 } : function(ns, name){
9311 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9315 var ep = El.prototype;
9318 * Appends an event handler (Shorthand for addListener)
9319 * @param {String} eventName The type of event to append
9320 * @param {Function} fn The method the event invokes
9321 * @param {Object} scope (optional) The scope (this object) of the fn
9322 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9325 ep.on = ep.addListener;
9327 ep.mon = ep.addListener;
9330 * Removes an event handler from this element (shorthand for removeListener)
9331 * @param {String} eventName the type of event to remove
9332 * @param {Function} fn the method the event invokes
9333 * @return {Roo.Element} this
9336 ep.un = ep.removeListener;
9339 * true to automatically adjust width and height settings for box-model issues (default to true)
9341 ep.autoBoxAdjust = true;
9344 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9347 El.addUnits = function(v, defaultUnit){
9348 if(v === "" || v == "auto"){
9351 if(v === undefined){
9354 if(typeof v == "number" || !El.unitPattern.test(v)){
9355 return v + (defaultUnit || 'px');
9360 // special markup used throughout Roo when box wrapping elements
9361 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>';
9363 * Visibility mode constant - Use visibility to hide element
9369 * Visibility mode constant - Use display to hide element
9375 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9376 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9377 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9389 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9390 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9391 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9392 * @return {Element} The Element object
9395 El.get = function(el){
9397 if(!el){ return null; }
9398 if(typeof el == "string"){ // element id
9399 if(!(elm = document.getElementById(el))){
9402 if(ex = El.cache[el]){
9405 ex = El.cache[el] = new El(elm);
9408 }else if(el.tagName){ // dom element
9412 if(ex = El.cache[id]){
9415 ex = El.cache[id] = new El(el);
9418 }else if(el instanceof El){
9420 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9421 // catch case where it hasn't been appended
9422 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9425 }else if(el.isComposite){
9427 }else if(el instanceof Array){
9428 return El.select(el);
9429 }else if(el == document){
9430 // create a bogus element object representing the document object
9432 var f = function(){};
9433 f.prototype = El.prototype;
9435 docEl.dom = document;
9443 El.uncache = function(el){
9444 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9446 delete El.cache[a[i].id || a[i]];
9452 // Garbage collection - uncache elements/purge listeners on orphaned elements
9453 // so we don't hold a reference and cause the browser to retain them
9454 El.garbageCollect = function(){
9455 if(!Roo.enableGarbageCollector){
9456 clearInterval(El.collectorThread);
9459 for(var eid in El.cache){
9460 var el = El.cache[eid], d = el.dom;
9461 // -------------------------------------------------------
9462 // Determining what is garbage:
9463 // -------------------------------------------------------
9465 // dom node is null, definitely garbage
9466 // -------------------------------------------------------
9468 // no parentNode == direct orphan, definitely garbage
9469 // -------------------------------------------------------
9470 // !d.offsetParent && !document.getElementById(eid)
9471 // display none elements have no offsetParent so we will
9472 // also try to look it up by it's id. However, check
9473 // offsetParent first so we don't do unneeded lookups.
9474 // This enables collection of elements that are not orphans
9475 // directly, but somewhere up the line they have an orphan
9477 // -------------------------------------------------------
9478 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9479 delete El.cache[eid];
9480 if(d && Roo.enableListenerCollection){
9486 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9490 El.Flyweight = function(dom){
9493 El.Flyweight.prototype = El.prototype;
9495 El._flyweights = {};
9497 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9498 * the dom node can be overwritten by other code.
9499 * @param {String/HTMLElement} el The dom node or id
9500 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9501 * prevent conflicts (e.g. internally Roo uses "_internal")
9503 * @return {Element} The shared Element object
9505 El.fly = function(el, named){
9506 named = named || '_global';
9507 el = Roo.getDom(el);
9511 if(!El._flyweights[named]){
9512 El._flyweights[named] = new El.Flyweight();
9514 El._flyweights[named].dom = el;
9515 return El._flyweights[named];
9519 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9520 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9521 * Shorthand of {@link Roo.Element#get}
9522 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9523 * @return {Element} The Element object
9529 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9530 * the dom node can be overwritten by other code.
9531 * Shorthand of {@link Roo.Element#fly}
9532 * @param {String/HTMLElement} el The dom node or id
9533 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9534 * prevent conflicts (e.g. internally Roo uses "_internal")
9536 * @return {Element} The shared Element object
9542 // speedy lookup for elements never to box adjust
9543 var noBoxAdjust = Roo.isStrict ? {
9546 input:1, select:1, textarea:1
9548 if(Roo.isIE || Roo.isGecko){
9549 noBoxAdjust['button'] = 1;
9553 Roo.EventManager.on(window, 'unload', function(){
9555 delete El._flyweights;
9563 Roo.Element.selectorFunction = Roo.DomQuery.select;
9566 Roo.Element.select = function(selector, unique, root){
9568 if(typeof selector == "string"){
9569 els = Roo.Element.selectorFunction(selector, root);
9570 }else if(selector.length !== undefined){
9573 throw "Invalid selector";
9575 if(unique === true){
9576 return new Roo.CompositeElement(els);
9578 return new Roo.CompositeElementLite(els);
9582 * Selects elements based on the passed CSS selector to enable working on them as 1.
9583 * @param {String/Array} selector The CSS selector or an array of elements
9584 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9585 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9586 * @return {CompositeElementLite/CompositeElement}
9590 Roo.select = Roo.Element.select;
9607 * Ext JS Library 1.1.1
9608 * Copyright(c) 2006-2007, Ext JS, LLC.
9610 * Originally Released Under LGPL - original licence link has changed is not relivant.
9613 * <script type="text/javascript">
9618 //Notifies Element that fx methods are available
9619 Roo.enableFx = true;
9623 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9624 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9625 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9626 * Element effects to work.</p><br/>
9628 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9629 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9630 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9631 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9632 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9633 * expected results and should be done with care.</p><br/>
9635 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9636 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9639 ----- -----------------------------
9640 tl The top left corner
9641 t The center of the top edge
9642 tr The top right corner
9643 l The center of the left edge
9644 r The center of the right edge
9645 bl The bottom left corner
9646 b The center of the bottom edge
9647 br The bottom right corner
9649 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9650 * below are common options that can be passed to any Fx method.</b>
9651 * @cfg {Function} callback A function called when the effect is finished
9652 * @cfg {Object} scope The scope of the effect function
9653 * @cfg {String} easing A valid Easing value for the effect
9654 * @cfg {String} afterCls A css class to apply after the effect
9655 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9656 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9657 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9658 * effects that end with the element being visually hidden, ignored otherwise)
9659 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9660 * a function which returns such a specification that will be applied to the Element after the effect finishes
9661 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9662 * @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
9663 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9667 * Slides the element into view. An anchor point can be optionally passed to set the point of
9668 * origin for the slide effect. This function automatically handles wrapping the element with
9669 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9672 // default: slide the element in from the top
9675 // custom: slide the element in from the right with a 2-second duration
9676 el.slideIn('r', { duration: 2 });
9678 // common config options shown with default values
9684 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9685 * @param {Object} options (optional) Object literal with any of the Fx config options
9686 * @return {Roo.Element} The Element
9688 slideIn : function(anchor, o){
9689 var el = this.getFxEl();
9692 el.queueFx(o, function(){
9694 anchor = anchor || "t";
9696 // fix display to visibility
9699 // restore values after effect
9700 var r = this.getFxRestore();
9701 var b = this.getBox();
9702 // fixed size for slide
9706 var wrap = this.fxWrap(r.pos, o, "hidden");
9708 var st = this.dom.style;
9709 st.visibility = "visible";
9710 st.position = "absolute";
9712 // clear out temp styles after slide and unwrap
9713 var after = function(){
9714 el.fxUnwrap(wrap, r.pos, o);
9716 st.height = r.height;
9719 // time to calc the positions
9720 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9722 switch(anchor.toLowerCase()){
9724 wrap.setSize(b.width, 0);
9725 st.left = st.bottom = "0";
9729 wrap.setSize(0, b.height);
9730 st.right = st.top = "0";
9734 wrap.setSize(0, b.height);
9736 st.left = st.top = "0";
9737 a = {width: bw, points: pt};
9740 wrap.setSize(b.width, 0);
9741 wrap.setY(b.bottom);
9742 st.left = st.top = "0";
9743 a = {height: bh, points: pt};
9747 st.right = st.bottom = "0";
9748 a = {width: bw, height: bh};
9752 wrap.setY(b.y+b.height);
9753 st.right = st.top = "0";
9754 a = {width: bw, height: bh, points: pt};
9758 wrap.setXY([b.right, b.bottom]);
9759 st.left = st.top = "0";
9760 a = {width: bw, height: bh, points: pt};
9764 wrap.setX(b.x+b.width);
9765 st.left = st.bottom = "0";
9766 a = {width: bw, height: bh, points: pt};
9769 this.dom.style.visibility = "visible";
9772 arguments.callee.anim = wrap.fxanim(a,
9782 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9783 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9784 * 'hidden') but block elements will still take up space in the document. The element must be removed
9785 * from the DOM using the 'remove' config option if desired. This function automatically handles
9786 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9789 // default: slide the element out to the top
9792 // custom: slide the element out to the right with a 2-second duration
9793 el.slideOut('r', { duration: 2 });
9795 // common config options shown with default values
9803 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9804 * @param {Object} options (optional) Object literal with any of the Fx config options
9805 * @return {Roo.Element} The Element
9807 slideOut : function(anchor, o){
9808 var el = this.getFxEl();
9811 el.queueFx(o, function(){
9813 anchor = anchor || "t";
9815 // restore values after effect
9816 var r = this.getFxRestore();
9818 var b = this.getBox();
9819 // fixed size for slide
9823 var wrap = this.fxWrap(r.pos, o, "visible");
9825 var st = this.dom.style;
9826 st.visibility = "visible";
9827 st.position = "absolute";
9831 var after = function(){
9833 el.setDisplayed(false);
9838 el.fxUnwrap(wrap, r.pos, o);
9841 st.height = r.height;
9846 var a, zero = {to: 0};
9847 switch(anchor.toLowerCase()){
9849 st.left = st.bottom = "0";
9853 st.right = st.top = "0";
9857 st.left = st.top = "0";
9858 a = {width: zero, points: {to:[b.right, b.y]}};
9861 st.left = st.top = "0";
9862 a = {height: zero, points: {to:[b.x, b.bottom]}};
9865 st.right = st.bottom = "0";
9866 a = {width: zero, height: zero};
9869 st.right = st.top = "0";
9870 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9873 st.left = st.top = "0";
9874 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9877 st.left = st.bottom = "0";
9878 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9882 arguments.callee.anim = wrap.fxanim(a,
9892 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
9893 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
9894 * The element must be removed from the DOM using the 'remove' config option if desired.
9900 // common config options shown with default values
9908 * @param {Object} options (optional) Object literal with any of the Fx config options
9909 * @return {Roo.Element} The Element
9912 var el = this.getFxEl();
9915 el.queueFx(o, function(){
9916 this.clearOpacity();
9919 // restore values after effect
9920 var r = this.getFxRestore();
9921 var st = this.dom.style;
9923 var after = function(){
9925 el.setDisplayed(false);
9932 el.setPositioning(r.pos);
9934 st.height = r.height;
9939 var width = this.getWidth();
9940 var height = this.getHeight();
9942 arguments.callee.anim = this.fxanim({
9943 width : {to: this.adjustWidth(width * 2)},
9944 height : {to: this.adjustHeight(height * 2)},
9945 points : {by: [-(width * .5), -(height * .5)]},
9947 fontSize: {to:200, unit: "%"}
9958 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
9959 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
9960 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
9966 // all config options shown with default values
9974 * @param {Object} options (optional) Object literal with any of the Fx config options
9975 * @return {Roo.Element} The Element
9977 switchOff : function(o){
9978 var el = this.getFxEl();
9981 el.queueFx(o, function(){
9982 this.clearOpacity();
9985 // restore values after effect
9986 var r = this.getFxRestore();
9987 var st = this.dom.style;
9989 var after = function(){
9991 el.setDisplayed(false);
9997 el.setPositioning(r.pos);
9999 st.height = r.height;
10004 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10005 this.clearOpacity();
10009 points:{by:[0, this.getHeight() * .5]}
10010 }, o, 'motion', 0.3, 'easeIn', after);
10011 }).defer(100, this);
10018 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10019 * changed using the "attr" config option) and then fading back to the original color. If no original
10020 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10023 // default: highlight background to yellow
10026 // custom: highlight foreground text to blue for 2 seconds
10027 el.highlight("0000ff", { attr: 'color', duration: 2 });
10029 // common config options shown with default values
10030 el.highlight("ffff9c", {
10031 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10032 endColor: (current color) or "ffffff",
10037 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10038 * @param {Object} options (optional) Object literal with any of the Fx config options
10039 * @return {Roo.Element} The Element
10041 highlight : function(color, o){
10042 var el = this.getFxEl();
10045 el.queueFx(o, function(){
10046 color = color || "ffff9c";
10047 attr = o.attr || "backgroundColor";
10049 this.clearOpacity();
10052 var origColor = this.getColor(attr);
10053 var restoreColor = this.dom.style[attr];
10054 endColor = (o.endColor || origColor) || "ffffff";
10056 var after = function(){
10057 el.dom.style[attr] = restoreColor;
10062 a[attr] = {from: color, to: endColor};
10063 arguments.callee.anim = this.fxanim(a,
10073 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10076 // default: a single light blue ripple
10079 // custom: 3 red ripples lasting 3 seconds total
10080 el.frame("ff0000", 3, { duration: 3 });
10082 // common config options shown with default values
10083 el.frame("C3DAF9", 1, {
10084 duration: 1 //duration of entire animation (not each individual ripple)
10085 // Note: Easing is not configurable and will be ignored if included
10088 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10089 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10090 * @param {Object} options (optional) Object literal with any of the Fx config options
10091 * @return {Roo.Element} The Element
10093 frame : function(color, count, o){
10094 var el = this.getFxEl();
10097 el.queueFx(o, function(){
10098 color = color || "#C3DAF9";
10099 if(color.length == 6){
10100 color = "#" + color;
10102 count = count || 1;
10103 duration = o.duration || 1;
10106 var b = this.getBox();
10107 var animFn = function(){
10108 var proxy = this.createProxy({
10111 visbility:"hidden",
10112 position:"absolute",
10113 "z-index":"35000", // yee haw
10114 border:"0px solid " + color
10117 var scale = Roo.isBorderBox ? 2 : 1;
10119 top:{from:b.y, to:b.y - 20},
10120 left:{from:b.x, to:b.x - 20},
10121 borderWidth:{from:0, to:10},
10122 opacity:{from:1, to:0},
10123 height:{from:b.height, to:(b.height + (20*scale))},
10124 width:{from:b.width, to:(b.width + (20*scale))}
10125 }, duration, function(){
10129 animFn.defer((duration/2)*1000, this);
10140 * Creates a pause before any subsequent queued effects begin. If there are
10141 * no effects queued after the pause it will have no effect.
10146 * @param {Number} seconds The length of time to pause (in seconds)
10147 * @return {Roo.Element} The Element
10149 pause : function(seconds){
10150 var el = this.getFxEl();
10153 el.queueFx(o, function(){
10154 setTimeout(function(){
10156 }, seconds * 1000);
10162 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10163 * using the "endOpacity" config option.
10166 // default: fade in from opacity 0 to 100%
10169 // custom: fade in from opacity 0 to 75% over 2 seconds
10170 el.fadeIn({ endOpacity: .75, duration: 2});
10172 // common config options shown with default values
10174 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10179 * @param {Object} options (optional) Object literal with any of the Fx config options
10180 * @return {Roo.Element} The Element
10182 fadeIn : function(o){
10183 var el = this.getFxEl();
10185 el.queueFx(o, function(){
10186 this.setOpacity(0);
10188 this.dom.style.visibility = 'visible';
10189 var to = o.endOpacity || 1;
10190 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10191 o, null, .5, "easeOut", function(){
10193 this.clearOpacity();
10202 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10203 * using the "endOpacity" config option.
10206 // default: fade out from the element's current opacity to 0
10209 // custom: fade out from the element's current opacity to 25% over 2 seconds
10210 el.fadeOut({ endOpacity: .25, duration: 2});
10212 // common config options shown with default values
10214 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10221 * @param {Object} options (optional) Object literal with any of the Fx config options
10222 * @return {Roo.Element} The Element
10224 fadeOut : function(o){
10225 var el = this.getFxEl();
10227 el.queueFx(o, function(){
10228 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10229 o, null, .5, "easeOut", function(){
10230 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10231 this.dom.style.display = "none";
10233 this.dom.style.visibility = "hidden";
10235 this.clearOpacity();
10243 * Animates the transition of an element's dimensions from a starting height/width
10244 * to an ending height/width.
10247 // change height and width to 100x100 pixels
10248 el.scale(100, 100);
10250 // common config options shown with default values. The height and width will default to
10251 // the element's existing values if passed as null.
10254 [element's height], {
10259 * @param {Number} width The new width (pass undefined to keep the original width)
10260 * @param {Number} height The new height (pass undefined to keep the original height)
10261 * @param {Object} options (optional) Object literal with any of the Fx config options
10262 * @return {Roo.Element} The Element
10264 scale : function(w, h, o){
10265 this.shift(Roo.apply({}, o, {
10273 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10274 * Any of these properties not specified in the config object will not be changed. This effect
10275 * requires that at least one new dimension, position or opacity setting must be passed in on
10276 * the config object in order for the function to have any effect.
10279 // slide the element horizontally to x position 200 while changing the height and opacity
10280 el.shift({ x: 200, height: 50, opacity: .8 });
10282 // common config options shown with default values.
10284 width: [element's width],
10285 height: [element's height],
10286 x: [element's x position],
10287 y: [element's y position],
10288 opacity: [element's opacity],
10293 * @param {Object} options Object literal with any of the Fx config options
10294 * @return {Roo.Element} The Element
10296 shift : function(o){
10297 var el = this.getFxEl();
10299 el.queueFx(o, function(){
10300 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10301 if(w !== undefined){
10302 a.width = {to: this.adjustWidth(w)};
10304 if(h !== undefined){
10305 a.height = {to: this.adjustHeight(h)};
10307 if(x !== undefined || y !== undefined){
10309 x !== undefined ? x : this.getX(),
10310 y !== undefined ? y : this.getY()
10313 if(op !== undefined){
10314 a.opacity = {to: op};
10316 if(o.xy !== undefined){
10317 a.points = {to: o.xy};
10319 arguments.callee.anim = this.fxanim(a,
10320 o, 'motion', .35, "easeOut", function(){
10328 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10329 * ending point of the effect.
10332 // default: slide the element downward while fading out
10335 // custom: slide the element out to the right with a 2-second duration
10336 el.ghost('r', { duration: 2 });
10338 // common config options shown with default values
10346 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10347 * @param {Object} options (optional) Object literal with any of the Fx config options
10348 * @return {Roo.Element} The Element
10350 ghost : function(anchor, o){
10351 var el = this.getFxEl();
10354 el.queueFx(o, function(){
10355 anchor = anchor || "b";
10357 // restore values after effect
10358 var r = this.getFxRestore();
10359 var w = this.getWidth(),
10360 h = this.getHeight();
10362 var st = this.dom.style;
10364 var after = function(){
10366 el.setDisplayed(false);
10372 el.setPositioning(r.pos);
10373 st.width = r.width;
10374 st.height = r.height;
10379 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10380 switch(anchor.toLowerCase()){
10407 arguments.callee.anim = this.fxanim(a,
10417 * Ensures that all effects queued after syncFx is called on the element are
10418 * run concurrently. This is the opposite of {@link #sequenceFx}.
10419 * @return {Roo.Element} The Element
10421 syncFx : function(){
10422 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10431 * Ensures that all effects queued after sequenceFx is called on the element are
10432 * run in sequence. This is the opposite of {@link #syncFx}.
10433 * @return {Roo.Element} The Element
10435 sequenceFx : function(){
10436 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10438 concurrent : false,
10445 nextFx : function(){
10446 var ef = this.fxQueue[0];
10453 * Returns true if the element has any effects actively running or queued, else returns false.
10454 * @return {Boolean} True if element has active effects, else false
10456 hasActiveFx : function(){
10457 return this.fxQueue && this.fxQueue[0];
10461 * Stops any running effects and clears the element's internal effects queue if it contains
10462 * any additional effects that haven't started yet.
10463 * @return {Roo.Element} The Element
10465 stopFx : function(){
10466 if(this.hasActiveFx()){
10467 var cur = this.fxQueue[0];
10468 if(cur && cur.anim && cur.anim.isAnimated()){
10469 this.fxQueue = [cur]; // clear out others
10470 cur.anim.stop(true);
10477 beforeFx : function(o){
10478 if(this.hasActiveFx() && !o.concurrent){
10489 * Returns true if the element is currently blocking so that no other effect can be queued
10490 * until this effect is finished, else returns false if blocking is not set. This is commonly
10491 * used to ensure that an effect initiated by a user action runs to completion prior to the
10492 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10493 * @return {Boolean} True if blocking, else false
10495 hasFxBlock : function(){
10496 var q = this.fxQueue;
10497 return q && q[0] && q[0].block;
10501 queueFx : function(o, fn){
10505 if(!this.hasFxBlock()){
10506 Roo.applyIf(o, this.fxDefaults);
10508 var run = this.beforeFx(o);
10509 fn.block = o.block;
10510 this.fxQueue.push(fn);
10522 fxWrap : function(pos, o, vis){
10524 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10527 wrapXY = this.getXY();
10529 var div = document.createElement("div");
10530 div.style.visibility = vis;
10531 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10532 wrap.setPositioning(pos);
10533 if(wrap.getStyle("position") == "static"){
10534 wrap.position("relative");
10536 this.clearPositioning('auto');
10538 wrap.dom.appendChild(this.dom);
10540 wrap.setXY(wrapXY);
10547 fxUnwrap : function(wrap, pos, o){
10548 this.clearPositioning();
10549 this.setPositioning(pos);
10551 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10557 getFxRestore : function(){
10558 var st = this.dom.style;
10559 return {pos: this.getPositioning(), width: st.width, height : st.height};
10563 afterFx : function(o){
10565 this.applyStyles(o.afterStyle);
10568 this.addClass(o.afterCls);
10570 if(o.remove === true){
10573 Roo.callback(o.callback, o.scope, [this]);
10575 this.fxQueue.shift();
10581 getFxEl : function(){ // support for composite element fx
10582 return Roo.get(this.dom);
10586 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10587 animType = animType || 'run';
10589 var anim = Roo.lib.Anim[animType](
10591 (opt.duration || defaultDur) || .35,
10592 (opt.easing || defaultEase) || 'easeOut',
10594 Roo.callback(cb, this);
10603 // backwords compat
10604 Roo.Fx.resize = Roo.Fx.scale;
10606 //When included, Roo.Fx is automatically applied to Element so that all basic
10607 //effects are available directly via the Element API
10608 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10610 * Ext JS Library 1.1.1
10611 * Copyright(c) 2006-2007, Ext JS, LLC.
10613 * Originally Released Under LGPL - original licence link has changed is not relivant.
10616 * <script type="text/javascript">
10621 * @class Roo.CompositeElement
10622 * Standard composite class. Creates a Roo.Element for every element in the collection.
10624 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10625 * actions will be performed on all the elements in this collection.</b>
10627 * All methods return <i>this</i> and can be chained.
10629 var els = Roo.select("#some-el div.some-class", true);
10630 // or select directly from an existing element
10631 var el = Roo.get('some-el');
10632 el.select('div.some-class', true);
10634 els.setWidth(100); // all elements become 100 width
10635 els.hide(true); // all elements fade out and hide
10637 els.setWidth(100).hide(true);
10640 Roo.CompositeElement = function(els){
10641 this.elements = [];
10642 this.addElements(els);
10644 Roo.CompositeElement.prototype = {
10646 addElements : function(els){
10647 if(!els) return this;
10648 if(typeof els == "string"){
10649 els = Roo.Element.selectorFunction(els);
10651 var yels = this.elements;
10652 var index = yels.length-1;
10653 for(var i = 0, len = els.length; i < len; i++) {
10654 yels[++index] = Roo.get(els[i]);
10660 * Clears this composite and adds the elements returned by the passed selector.
10661 * @param {String/Array} els A string CSS selector, an array of elements or an element
10662 * @return {CompositeElement} this
10664 fill : function(els){
10665 this.elements = [];
10671 * Filters this composite to only elements that match the passed selector.
10672 * @param {String} selector A string CSS selector
10673 * @return {CompositeElement} this
10675 filter : function(selector){
10677 this.each(function(el){
10678 if(el.is(selector)){
10679 els[els.length] = el.dom;
10686 invoke : function(fn, args){
10687 var els = this.elements;
10688 for(var i = 0, len = els.length; i < len; i++) {
10689 Roo.Element.prototype[fn].apply(els[i], args);
10694 * Adds elements to this composite.
10695 * @param {String/Array} els A string CSS selector, an array of elements or an element
10696 * @return {CompositeElement} this
10698 add : function(els){
10699 if(typeof els == "string"){
10700 this.addElements(Roo.Element.selectorFunction(els));
10701 }else if(els.length !== undefined){
10702 this.addElements(els);
10704 this.addElements([els]);
10709 * Calls the passed function passing (el, this, index) for each element in this composite.
10710 * @param {Function} fn The function to call
10711 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10712 * @return {CompositeElement} this
10714 each : function(fn, scope){
10715 var els = this.elements;
10716 for(var i = 0, len = els.length; i < len; i++){
10717 if(fn.call(scope || els[i], els[i], this, i) === false) {
10725 * Returns the Element object at the specified index
10726 * @param {Number} index
10727 * @return {Roo.Element}
10729 item : function(index){
10730 return this.elements[index] || null;
10734 * Returns the first Element
10735 * @return {Roo.Element}
10737 first : function(){
10738 return this.item(0);
10742 * Returns the last Element
10743 * @return {Roo.Element}
10746 return this.item(this.elements.length-1);
10750 * Returns the number of elements in this composite
10753 getCount : function(){
10754 return this.elements.length;
10758 * Returns true if this composite contains the passed element
10761 contains : function(el){
10762 return this.indexOf(el) !== -1;
10766 * Returns true if this composite contains the passed element
10769 indexOf : function(el){
10770 return this.elements.indexOf(Roo.get(el));
10775 * Removes the specified element(s).
10776 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10777 * or an array of any of those.
10778 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10779 * @return {CompositeElement} this
10781 removeElement : function(el, removeDom){
10782 if(el instanceof Array){
10783 for(var i = 0, len = el.length; i < len; i++){
10784 this.removeElement(el[i]);
10788 var index = typeof el == 'number' ? el : this.indexOf(el);
10791 var d = this.elements[index];
10795 d.parentNode.removeChild(d);
10798 this.elements.splice(index, 1);
10804 * Replaces the specified element with the passed element.
10805 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10807 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10808 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10809 * @return {CompositeElement} this
10811 replaceElement : function(el, replacement, domReplace){
10812 var index = typeof el == 'number' ? el : this.indexOf(el);
10815 this.elements[index].replaceWith(replacement);
10817 this.elements.splice(index, 1, Roo.get(replacement))
10824 * Removes all elements.
10826 clear : function(){
10827 this.elements = [];
10831 Roo.CompositeElement.createCall = function(proto, fnName){
10832 if(!proto[fnName]){
10833 proto[fnName] = function(){
10834 return this.invoke(fnName, arguments);
10838 for(var fnName in Roo.Element.prototype){
10839 if(typeof Roo.Element.prototype[fnName] == "function"){
10840 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10846 * Ext JS Library 1.1.1
10847 * Copyright(c) 2006-2007, Ext JS, LLC.
10849 * Originally Released Under LGPL - original licence link has changed is not relivant.
10852 * <script type="text/javascript">
10856 * @class Roo.CompositeElementLite
10857 * @extends Roo.CompositeElement
10858 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10860 var els = Roo.select("#some-el div.some-class");
10861 // or select directly from an existing element
10862 var el = Roo.get('some-el');
10863 el.select('div.some-class');
10865 els.setWidth(100); // all elements become 100 width
10866 els.hide(true); // all elements fade out and hide
10868 els.setWidth(100).hide(true);
10869 </code></pre><br><br>
10870 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10871 * actions will be performed on all the elements in this collection.</b>
10873 Roo.CompositeElementLite = function(els){
10874 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10875 this.el = new Roo.Element.Flyweight();
10877 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10878 addElements : function(els){
10880 if(els instanceof Array){
10881 this.elements = this.elements.concat(els);
10883 var yels = this.elements;
10884 var index = yels.length-1;
10885 for(var i = 0, len = els.length; i < len; i++) {
10886 yels[++index] = els[i];
10892 invoke : function(fn, args){
10893 var els = this.elements;
10895 for(var i = 0, len = els.length; i < len; i++) {
10897 Roo.Element.prototype[fn].apply(el, args);
10902 * Returns a flyweight Element of the dom element object at the specified index
10903 * @param {Number} index
10904 * @return {Roo.Element}
10906 item : function(index){
10907 if(!this.elements[index]){
10910 this.el.dom = this.elements[index];
10914 // fixes scope with flyweight
10915 addListener : function(eventName, handler, scope, opt){
10916 var els = this.elements;
10917 for(var i = 0, len = els.length; i < len; i++) {
10918 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
10924 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
10925 * passed is the flyweight (shared) Roo.Element instance, so if you require a
10926 * a reference to the dom node, use el.dom.</b>
10927 * @param {Function} fn The function to call
10928 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10929 * @return {CompositeElement} this
10931 each : function(fn, scope){
10932 var els = this.elements;
10934 for(var i = 0, len = els.length; i < len; i++){
10936 if(fn.call(scope || el, el, this, i) === false){
10943 indexOf : function(el){
10944 return this.elements.indexOf(Roo.getDom(el));
10947 replaceElement : function(el, replacement, domReplace){
10948 var index = typeof el == 'number' ? el : this.indexOf(el);
10950 replacement = Roo.getDom(replacement);
10952 var d = this.elements[index];
10953 d.parentNode.insertBefore(replacement, d);
10954 d.parentNode.removeChild(d);
10956 this.elements.splice(index, 1, replacement);
10961 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
10965 * Ext JS Library 1.1.1
10966 * Copyright(c) 2006-2007, Ext JS, LLC.
10968 * Originally Released Under LGPL - original licence link has changed is not relivant.
10971 * <script type="text/javascript">
10977 * @class Roo.data.Connection
10978 * @extends Roo.util.Observable
10979 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
10980 * either to a configured URL, or to a URL specified at request time.<br><br>
10982 * Requests made by this class are asynchronous, and will return immediately. No data from
10983 * the server will be available to the statement immediately following the {@link #request} call.
10984 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
10986 * Note: If you are doing a file upload, you will not get a normal response object sent back to
10987 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
10988 * The response object is created using the innerHTML of the IFRAME's document as the responseText
10989 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
10990 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
10991 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
10992 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
10993 * standard DOM methods.
10995 * @param {Object} config a configuration object.
10997 Roo.data.Connection = function(config){
10998 Roo.apply(this, config);
11001 * @event beforerequest
11002 * Fires before a network request is made to retrieve a data object.
11003 * @param {Connection} conn This Connection object.
11004 * @param {Object} options The options config object passed to the {@link #request} method.
11006 "beforerequest" : true,
11008 * @event requestcomplete
11009 * Fires if the request was successfully completed.
11010 * @param {Connection} conn This Connection object.
11011 * @param {Object} response The XHR object containing the response data.
11012 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11013 * @param {Object} options The options config object passed to the {@link #request} method.
11015 "requestcomplete" : true,
11017 * @event requestexception
11018 * Fires if an error HTTP status was returned from the server.
11019 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11020 * @param {Connection} conn This Connection object.
11021 * @param {Object} response The XHR object containing the response data.
11022 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11023 * @param {Object} options The options config object passed to the {@link #request} method.
11025 "requestexception" : true
11027 Roo.data.Connection.superclass.constructor.call(this);
11030 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11032 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11035 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11036 * extra parameters to each request made by this object. (defaults to undefined)
11039 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11040 * to each request made by this object. (defaults to undefined)
11043 * @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)
11046 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11050 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11056 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11059 disableCaching: true,
11062 * Sends an HTTP request to a remote server.
11063 * @param {Object} options An object which may contain the following properties:<ul>
11064 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11065 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11066 * request, a url encoded string or a function to call to get either.</li>
11067 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11068 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11069 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11070 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11071 * <li>options {Object} The parameter to the request call.</li>
11072 * <li>success {Boolean} True if the request succeeded.</li>
11073 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11075 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11076 * The callback is passed the following parameters:<ul>
11077 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11078 * <li>options {Object} The parameter to the request call.</li>
11080 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11081 * The callback is passed the following parameters:<ul>
11082 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11083 * <li>options {Object} The parameter to the request call.</li>
11085 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11086 * for the callback function. Defaults to the browser window.</li>
11087 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11088 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11089 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11090 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11091 * params for the post data. Any params will be appended to the URL.</li>
11092 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11094 * @return {Number} transactionId
11096 request : function(o){
11097 if(this.fireEvent("beforerequest", this, o) !== false){
11100 if(typeof p == "function"){
11101 p = p.call(o.scope||window, o);
11103 if(typeof p == "object"){
11104 p = Roo.urlEncode(o.params);
11106 if(this.extraParams){
11107 var extras = Roo.urlEncode(this.extraParams);
11108 p = p ? (p + '&' + extras) : extras;
11111 var url = o.url || this.url;
11112 if(typeof url == 'function'){
11113 url = url.call(o.scope||window, o);
11117 var form = Roo.getDom(o.form);
11118 url = url || form.action;
11120 var enctype = form.getAttribute("enctype");
11121 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11122 return this.doFormUpload(o, p, url);
11124 var f = Roo.lib.Ajax.serializeForm(form);
11125 p = p ? (p + '&' + f) : f;
11128 var hs = o.headers;
11129 if(this.defaultHeaders){
11130 hs = Roo.apply(hs || {}, this.defaultHeaders);
11137 success: this.handleResponse,
11138 failure: this.handleFailure,
11140 argument: {options: o},
11141 timeout : this.timeout
11144 var method = o.method||this.method||(p ? "POST" : "GET");
11146 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11147 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11150 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11154 }else if(this.autoAbort !== false){
11158 if((method == 'GET' && p) || o.xmlData){
11159 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11162 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11163 return this.transId;
11165 Roo.callback(o.callback, o.scope, [o, null, null]);
11171 * Determine whether this object has a request outstanding.
11172 * @param {Number} transactionId (Optional) defaults to the last transaction
11173 * @return {Boolean} True if there is an outstanding request.
11175 isLoading : function(transId){
11177 return Roo.lib.Ajax.isCallInProgress(transId);
11179 return this.transId ? true : false;
11184 * Aborts any outstanding request.
11185 * @param {Number} transactionId (Optional) defaults to the last transaction
11187 abort : function(transId){
11188 if(transId || this.isLoading()){
11189 Roo.lib.Ajax.abort(transId || this.transId);
11194 handleResponse : function(response){
11195 this.transId = false;
11196 var options = response.argument.options;
11197 response.argument = options ? options.argument : null;
11198 this.fireEvent("requestcomplete", this, response, options);
11199 Roo.callback(options.success, options.scope, [response, options]);
11200 Roo.callback(options.callback, options.scope, [options, true, response]);
11204 handleFailure : function(response, e){
11205 this.transId = false;
11206 var options = response.argument.options;
11207 response.argument = options ? options.argument : null;
11208 this.fireEvent("requestexception", this, response, options, e);
11209 Roo.callback(options.failure, options.scope, [response, options]);
11210 Roo.callback(options.callback, options.scope, [options, false, response]);
11214 doFormUpload : function(o, ps, url){
11216 var frame = document.createElement('iframe');
11219 frame.className = 'x-hidden';
11221 frame.src = Roo.SSL_SECURE_URL;
11223 document.body.appendChild(frame);
11226 document.frames[id].name = id;
11229 var form = Roo.getDom(o.form);
11231 form.method = 'POST';
11232 form.enctype = form.encoding = 'multipart/form-data';
11238 if(ps){ // add dynamic params
11240 ps = Roo.urlDecode(ps, false);
11242 if(ps.hasOwnProperty(k)){
11243 hd = document.createElement('input');
11244 hd.type = 'hidden';
11247 form.appendChild(hd);
11254 var r = { // bogus response object
11259 r.argument = o ? o.argument : null;
11264 doc = frame.contentWindow.document;
11266 doc = (frame.contentDocument || window.frames[id].document);
11268 if(doc && doc.body){
11269 r.responseText = doc.body.innerHTML;
11271 if(doc && doc.XMLDocument){
11272 r.responseXML = doc.XMLDocument;
11274 r.responseXML = doc;
11281 Roo.EventManager.removeListener(frame, 'load', cb, this);
11283 this.fireEvent("requestcomplete", this, r, o);
11284 Roo.callback(o.success, o.scope, [r, o]);
11285 Roo.callback(o.callback, o.scope, [o, true, r]);
11287 setTimeout(function(){document.body.removeChild(frame);}, 100);
11290 Roo.EventManager.on(frame, 'load', cb, this);
11293 if(hiddens){ // remove dynamic params
11294 for(var i = 0, len = hiddens.length; i < len; i++){
11295 form.removeChild(hiddens[i]);
11303 * @extends Roo.data.Connection
11304 * Global Ajax request class.
11308 Roo.Ajax = new Roo.data.Connection({
11311 * @cfg {String} url @hide
11314 * @cfg {Object} extraParams @hide
11317 * @cfg {Object} defaultHeaders @hide
11320 * @cfg {String} method (Optional) @hide
11323 * @cfg {Number} timeout (Optional) @hide
11326 * @cfg {Boolean} autoAbort (Optional) @hide
11330 * @cfg {Boolean} disableCaching (Optional) @hide
11334 * @property disableCaching
11335 * True to add a unique cache-buster param to GET requests. (defaults to true)
11340 * The default URL to be used for requests to the server. (defaults to undefined)
11344 * @property extraParams
11345 * An object containing properties which are used as
11346 * extra parameters to each request made by this object. (defaults to undefined)
11350 * @property defaultHeaders
11351 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11356 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11360 * @property timeout
11361 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11366 * @property autoAbort
11367 * Whether a new request should abort any pending requests. (defaults to false)
11373 * Serialize the passed form into a url encoded string
11374 * @param {String/HTMLElement} form
11377 serializeForm : function(form){
11378 return Roo.lib.Ajax.serializeForm(form);
11382 * Ext JS Library 1.1.1
11383 * Copyright(c) 2006-2007, Ext JS, LLC.
11385 * Originally Released Under LGPL - original licence link has changed is not relivant.
11388 * <script type="text/javascript">
11393 * @extends Roo.data.Connection
11394 * Global Ajax request class.
11396 * @instanceOf Roo.data.Connection
11398 Roo.Ajax = new Roo.data.Connection({
11407 * @cfg {String} url @hide
11410 * @cfg {Object} extraParams @hide
11413 * @cfg {Object} defaultHeaders @hide
11416 * @cfg {String} method (Optional) @hide
11419 * @cfg {Number} timeout (Optional) @hide
11422 * @cfg {Boolean} autoAbort (Optional) @hide
11426 * @cfg {Boolean} disableCaching (Optional) @hide
11430 * @property disableCaching
11431 * True to add a unique cache-buster param to GET requests. (defaults to true)
11436 * The default URL to be used for requests to the server. (defaults to undefined)
11440 * @property extraParams
11441 * An object containing properties which are used as
11442 * extra parameters to each request made by this object. (defaults to undefined)
11446 * @property defaultHeaders
11447 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11452 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11456 * @property timeout
11457 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11462 * @property autoAbort
11463 * Whether a new request should abort any pending requests. (defaults to false)
11469 * Serialize the passed form into a url encoded string
11470 * @param {String/HTMLElement} form
11473 serializeForm : function(form){
11474 return Roo.lib.Ajax.serializeForm(form);
11478 * Ext JS Library 1.1.1
11479 * Copyright(c) 2006-2007, Ext JS, LLC.
11481 * Originally Released Under LGPL - original licence link has changed is not relivant.
11484 * <script type="text/javascript">
11489 * @class Roo.UpdateManager
11490 * @extends Roo.util.Observable
11491 * Provides AJAX-style update for Element object.<br><br>
11494 * // Get it from a Roo.Element object
11495 * var el = Roo.get("foo");
11496 * var mgr = el.getUpdateManager();
11497 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11499 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11501 * // or directly (returns the same UpdateManager instance)
11502 * var mgr = new Roo.UpdateManager("myElementId");
11503 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11504 * mgr.on("update", myFcnNeedsToKnow);
11506 // short handed call directly from the element object
11507 Roo.get("foo").load({
11511 text: "Loading Foo..."
11515 * Create new UpdateManager directly.
11516 * @param {String/HTMLElement/Roo.Element} el The element to update
11517 * @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).
11519 Roo.UpdateManager = function(el, forceNew){
11521 if(!forceNew && el.updateManager){
11522 return el.updateManager;
11525 * The Element object
11526 * @type Roo.Element
11530 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11533 this.defaultUrl = null;
11537 * @event beforeupdate
11538 * Fired before an update is made, return false from your handler and the update is cancelled.
11539 * @param {Roo.Element} el
11540 * @param {String/Object/Function} url
11541 * @param {String/Object} params
11543 "beforeupdate": true,
11546 * Fired after successful update is made.
11547 * @param {Roo.Element} el
11548 * @param {Object} oResponseObject The response Object
11553 * Fired on update failure.
11554 * @param {Roo.Element} el
11555 * @param {Object} oResponseObject The response Object
11559 var d = Roo.UpdateManager.defaults;
11561 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11564 this.sslBlankUrl = d.sslBlankUrl;
11566 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11569 this.disableCaching = d.disableCaching;
11571 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11574 this.indicatorText = d.indicatorText;
11576 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11579 this.showLoadIndicator = d.showLoadIndicator;
11581 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11584 this.timeout = d.timeout;
11587 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11590 this.loadScripts = d.loadScripts;
11593 * Transaction object of current executing transaction
11595 this.transaction = null;
11600 this.autoRefreshProcId = null;
11602 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11605 this.refreshDelegate = this.refresh.createDelegate(this);
11607 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11610 this.updateDelegate = this.update.createDelegate(this);
11612 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11615 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11619 this.successDelegate = this.processSuccess.createDelegate(this);
11623 this.failureDelegate = this.processFailure.createDelegate(this);
11625 if(!this.renderer){
11627 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11629 this.renderer = new Roo.UpdateManager.BasicRenderer();
11632 Roo.UpdateManager.superclass.constructor.call(this);
11635 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11637 * Get the Element this UpdateManager is bound to
11638 * @return {Roo.Element} The element
11640 getEl : function(){
11644 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11645 * @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:
11648 url: "your-url.php",<br/>
11649 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11650 callback: yourFunction,<br/>
11651 scope: yourObject, //(optional scope) <br/>
11652 discardUrl: false, <br/>
11653 nocache: false,<br/>
11654 text: "Loading...",<br/>
11656 scripts: false<br/>
11659 * The only required property is url. The optional properties nocache, text and scripts
11660 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11661 * @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}
11662 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11663 * @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.
11665 update : function(url, params, callback, discardUrl){
11666 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11667 var method = this.method, cfg;
11668 if(typeof url == "object"){ // must be config object
11671 params = params || cfg.params;
11672 callback = callback || cfg.callback;
11673 discardUrl = discardUrl || cfg.discardUrl;
11674 if(callback && cfg.scope){
11675 callback = callback.createDelegate(cfg.scope);
11677 if(typeof cfg.method != "undefined"){method = cfg.method;};
11678 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11679 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11680 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11681 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11683 this.showLoading();
11685 this.defaultUrl = url;
11687 if(typeof url == "function"){
11688 url = url.call(this);
11691 method = method || (params ? "POST" : "GET");
11692 if(method == "GET"){
11693 url = this.prepareUrl(url);
11696 var o = Roo.apply(cfg ||{}, {
11699 success: this.successDelegate,
11700 failure: this.failureDelegate,
11701 callback: undefined,
11702 timeout: (this.timeout*1000),
11703 argument: {"url": url, "form": null, "callback": callback, "params": params}
11706 this.transaction = Roo.Ajax.request(o);
11711 * 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.
11712 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11713 * @param {String/HTMLElement} form The form Id or form element
11714 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11715 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11716 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11718 formUpdate : function(form, url, reset, callback){
11719 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11720 if(typeof url == "function"){
11721 url = url.call(this);
11723 form = Roo.getDom(form);
11724 this.transaction = Roo.Ajax.request({
11727 success: this.successDelegate,
11728 failure: this.failureDelegate,
11729 timeout: (this.timeout*1000),
11730 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11732 this.showLoading.defer(1, this);
11737 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11738 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11740 refresh : function(callback){
11741 if(this.defaultUrl == null){
11744 this.update(this.defaultUrl, null, callback, true);
11748 * Set this element to auto refresh.
11749 * @param {Number} interval How often to update (in seconds).
11750 * @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)
11751 * @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}
11752 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11753 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11755 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11757 this.update(url || this.defaultUrl, params, callback, true);
11759 if(this.autoRefreshProcId){
11760 clearInterval(this.autoRefreshProcId);
11762 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11766 * Stop auto refresh on this element.
11768 stopAutoRefresh : function(){
11769 if(this.autoRefreshProcId){
11770 clearInterval(this.autoRefreshProcId);
11771 delete this.autoRefreshProcId;
11775 isAutoRefreshing : function(){
11776 return this.autoRefreshProcId ? true : false;
11779 * Called to update the element to "Loading" state. Override to perform custom action.
11781 showLoading : function(){
11782 if(this.showLoadIndicator){
11783 this.el.update(this.indicatorText);
11788 * Adds unique parameter to query string if disableCaching = true
11791 prepareUrl : function(url){
11792 if(this.disableCaching){
11793 var append = "_dc=" + (new Date().getTime());
11794 if(url.indexOf("?") !== -1){
11795 url += "&" + append;
11797 url += "?" + append;
11806 processSuccess : function(response){
11807 this.transaction = null;
11808 if(response.argument.form && response.argument.reset){
11809 try{ // put in try/catch since some older FF releases had problems with this
11810 response.argument.form.reset();
11813 if(this.loadScripts){
11814 this.renderer.render(this.el, response, this,
11815 this.updateComplete.createDelegate(this, [response]));
11817 this.renderer.render(this.el, response, this);
11818 this.updateComplete(response);
11822 updateComplete : function(response){
11823 this.fireEvent("update", this.el, response);
11824 if(typeof response.argument.callback == "function"){
11825 response.argument.callback(this.el, true, response);
11832 processFailure : function(response){
11833 this.transaction = null;
11834 this.fireEvent("failure", this.el, response);
11835 if(typeof response.argument.callback == "function"){
11836 response.argument.callback(this.el, false, response);
11841 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11842 * @param {Object} renderer The object implementing the render() method
11844 setRenderer : function(renderer){
11845 this.renderer = renderer;
11848 getRenderer : function(){
11849 return this.renderer;
11853 * Set the defaultUrl used for updates
11854 * @param {String/Function} defaultUrl The url or a function to call to get the url
11856 setDefaultUrl : function(defaultUrl){
11857 this.defaultUrl = defaultUrl;
11861 * Aborts the executing transaction
11863 abort : function(){
11864 if(this.transaction){
11865 Roo.Ajax.abort(this.transaction);
11870 * Returns true if an update is in progress
11871 * @return {Boolean}
11873 isUpdating : function(){
11874 if(this.transaction){
11875 return Roo.Ajax.isLoading(this.transaction);
11882 * @class Roo.UpdateManager.defaults
11883 * @static (not really - but it helps the doc tool)
11884 * The defaults collection enables customizing the default properties of UpdateManager
11886 Roo.UpdateManager.defaults = {
11888 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
11894 * True to process scripts by default (Defaults to false).
11897 loadScripts : false,
11900 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
11903 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
11905 * Whether to append unique parameter on get request to disable caching (Defaults to false).
11908 disableCaching : false,
11910 * Whether to show indicatorText when loading (Defaults to true).
11913 showLoadIndicator : true,
11915 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
11918 indicatorText : '<div class="loading-indicator">Loading...</div>'
11922 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
11924 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
11925 * @param {String/HTMLElement/Roo.Element} el The element to update
11926 * @param {String} url The url
11927 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
11928 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
11931 * @member Roo.UpdateManager
11933 Roo.UpdateManager.updateElement = function(el, url, params, options){
11934 var um = Roo.get(el, true).getUpdateManager();
11935 Roo.apply(um, options);
11936 um.update(url, params, options ? options.callback : null);
11938 // alias for backwards compat
11939 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
11941 * @class Roo.UpdateManager.BasicRenderer
11942 * Default Content renderer. Updates the elements innerHTML with the responseText.
11944 Roo.UpdateManager.BasicRenderer = function(){};
11946 Roo.UpdateManager.BasicRenderer.prototype = {
11948 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
11949 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
11950 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
11951 * @param {Roo.Element} el The element being rendered
11952 * @param {Object} response The YUI Connect response object
11953 * @param {UpdateManager} updateManager The calling update manager
11954 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
11956 render : function(el, response, updateManager, callback){
11957 el.update(response.responseText, updateManager.loadScripts, callback);
11962 * Ext JS Library 1.1.1
11963 * Copyright(c) 2006-2007, Ext JS, LLC.
11965 * Originally Released Under LGPL - original licence link has changed is not relivant.
11968 * <script type="text/javascript">
11972 * @class Roo.util.DelayedTask
11973 * Provides a convenient method of performing setTimeout where a new
11974 * timeout cancels the old timeout. An example would be performing validation on a keypress.
11975 * You can use this class to buffer
11976 * the keypress events for a certain number of milliseconds, and perform only if they stop
11977 * for that amount of time.
11978 * @constructor The parameters to this constructor serve as defaults and are not required.
11979 * @param {Function} fn (optional) The default function to timeout
11980 * @param {Object} scope (optional) The default scope of that timeout
11981 * @param {Array} args (optional) The default Array of arguments
11983 Roo.util.DelayedTask = function(fn, scope, args){
11984 var id = null, d, t;
11986 var call = function(){
11987 var now = new Date().getTime();
11991 fn.apply(scope, args || []);
11995 * Cancels any pending timeout and queues a new one
11996 * @param {Number} delay The milliseconds to delay
11997 * @param {Function} newFn (optional) Overrides function passed to constructor
11998 * @param {Object} newScope (optional) Overrides scope passed to constructor
11999 * @param {Array} newArgs (optional) Overrides args passed to constructor
12001 this.delay = function(delay, newFn, newScope, newArgs){
12002 if(id && delay != d){
12006 t = new Date().getTime();
12008 scope = newScope || scope;
12009 args = newArgs || args;
12011 id = setInterval(call, d);
12016 * Cancel the last queued timeout
12018 this.cancel = function(){
12026 * Ext JS Library 1.1.1
12027 * Copyright(c) 2006-2007, Ext JS, LLC.
12029 * Originally Released Under LGPL - original licence link has changed is not relivant.
12032 * <script type="text/javascript">
12036 Roo.util.TaskRunner = function(interval){
12037 interval = interval || 10;
12038 var tasks = [], removeQueue = [];
12040 var running = false;
12042 var stopThread = function(){
12048 var startThread = function(){
12051 id = setInterval(runTasks, interval);
12055 var removeTask = function(task){
12056 removeQueue.push(task);
12062 var runTasks = function(){
12063 if(removeQueue.length > 0){
12064 for(var i = 0, len = removeQueue.length; i < len; i++){
12065 tasks.remove(removeQueue[i]);
12068 if(tasks.length < 1){
12073 var now = new Date().getTime();
12074 for(var i = 0, len = tasks.length; i < len; ++i){
12076 var itime = now - t.taskRunTime;
12077 if(t.interval <= itime){
12078 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12079 t.taskRunTime = now;
12080 if(rt === false || t.taskRunCount === t.repeat){
12085 if(t.duration && t.duration <= (now - t.taskStartTime)){
12092 * Queues a new task.
12093 * @param {Object} task
12095 this.start = function(task){
12097 task.taskStartTime = new Date().getTime();
12098 task.taskRunTime = 0;
12099 task.taskRunCount = 0;
12104 this.stop = function(task){
12109 this.stopAll = function(){
12111 for(var i = 0, len = tasks.length; i < len; i++){
12112 if(tasks[i].onStop){
12121 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12123 * Ext JS Library 1.1.1
12124 * Copyright(c) 2006-2007, Ext JS, LLC.
12126 * Originally Released Under LGPL - original licence link has changed is not relivant.
12129 * <script type="text/javascript">
12134 * @class Roo.util.MixedCollection
12135 * @extends Roo.util.Observable
12136 * A Collection class that maintains both numeric indexes and keys and exposes events.
12138 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12139 * collection (defaults to false)
12140 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12141 * and return the key value for that item. This is used when available to look up the key on items that
12142 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12143 * equivalent to providing an implementation for the {@link #getKey} method.
12145 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12153 * Fires when the collection is cleared.
12158 * Fires when an item is added to the collection.
12159 * @param {Number} index The index at which the item was added.
12160 * @param {Object} o The item added.
12161 * @param {String} key The key associated with the added item.
12166 * Fires when an item is replaced in the collection.
12167 * @param {String} key he key associated with the new added.
12168 * @param {Object} old The item being replaced.
12169 * @param {Object} new The new item.
12174 * Fires when an item is removed from the collection.
12175 * @param {Object} o The item being removed.
12176 * @param {String} key (optional) The key associated with the removed item.
12181 this.allowFunctions = allowFunctions === true;
12183 this.getKey = keyFn;
12185 Roo.util.MixedCollection.superclass.constructor.call(this);
12188 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12189 allowFunctions : false,
12192 * Adds an item to the collection.
12193 * @param {String} key The key to associate with the item
12194 * @param {Object} o The item to add.
12195 * @return {Object} The item added.
12197 add : function(key, o){
12198 if(arguments.length == 1){
12200 key = this.getKey(o);
12202 if(typeof key == "undefined" || key === null){
12204 this.items.push(o);
12205 this.keys.push(null);
12207 var old = this.map[key];
12209 return this.replace(key, o);
12212 this.items.push(o);
12214 this.keys.push(key);
12216 this.fireEvent("add", this.length-1, o, key);
12221 * MixedCollection has a generic way to fetch keys if you implement getKey.
12224 var mc = new Roo.util.MixedCollection();
12225 mc.add(someEl.dom.id, someEl);
12226 mc.add(otherEl.dom.id, otherEl);
12230 var mc = new Roo.util.MixedCollection();
12231 mc.getKey = function(el){
12237 // or via the constructor
12238 var mc = new Roo.util.MixedCollection(false, function(el){
12244 * @param o {Object} The item for which to find the key.
12245 * @return {Object} The key for the passed item.
12247 getKey : function(o){
12252 * Replaces an item in the collection.
12253 * @param {String} key The key associated with the item to replace, or the item to replace.
12254 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12255 * @return {Object} The new item.
12257 replace : function(key, o){
12258 if(arguments.length == 1){
12260 key = this.getKey(o);
12262 var old = this.item(key);
12263 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12264 return this.add(key, o);
12266 var index = this.indexOfKey(key);
12267 this.items[index] = o;
12269 this.fireEvent("replace", key, old, o);
12274 * Adds all elements of an Array or an Object to the collection.
12275 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12276 * an Array of values, each of which are added to the collection.
12278 addAll : function(objs){
12279 if(arguments.length > 1 || objs instanceof Array){
12280 var args = arguments.length > 1 ? arguments : objs;
12281 for(var i = 0, len = args.length; i < len; i++){
12285 for(var key in objs){
12286 if(this.allowFunctions || typeof objs[key] != "function"){
12287 this.add(key, objs[key]);
12294 * Executes the specified function once for every item in the collection, passing each
12295 * item as the first and only parameter. returning false from the function will stop the iteration.
12296 * @param {Function} fn The function to execute for each item.
12297 * @param {Object} scope (optional) The scope in which to execute the function.
12299 each : function(fn, scope){
12300 var items = [].concat(this.items); // each safe for removal
12301 for(var i = 0, len = items.length; i < len; i++){
12302 if(fn.call(scope || items[i], items[i], i, len) === false){
12309 * Executes the specified function once for every key in the collection, passing each
12310 * key, and its associated item as the first two parameters.
12311 * @param {Function} fn The function to execute for each item.
12312 * @param {Object} scope (optional) The scope in which to execute the function.
12314 eachKey : function(fn, scope){
12315 for(var i = 0, len = this.keys.length; i < len; i++){
12316 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12321 * Returns the first item in the collection which elicits a true return value from the
12322 * passed selection function.
12323 * @param {Function} fn The selection function to execute for each item.
12324 * @param {Object} scope (optional) The scope in which to execute the function.
12325 * @return {Object} The first item in the collection which returned true from the selection function.
12327 find : function(fn, scope){
12328 for(var i = 0, len = this.items.length; i < len; i++){
12329 if(fn.call(scope || window, this.items[i], this.keys[i])){
12330 return this.items[i];
12337 * Inserts an item at the specified index in the collection.
12338 * @param {Number} index The index to insert the item at.
12339 * @param {String} key The key to associate with the new item, or the item itself.
12340 * @param {Object} o (optional) If the second parameter was a key, the new item.
12341 * @return {Object} The item inserted.
12343 insert : function(index, key, o){
12344 if(arguments.length == 2){
12346 key = this.getKey(o);
12348 if(index >= this.length){
12349 return this.add(key, o);
12352 this.items.splice(index, 0, o);
12353 if(typeof key != "undefined" && key != null){
12356 this.keys.splice(index, 0, key);
12357 this.fireEvent("add", index, o, key);
12362 * Removed an item from the collection.
12363 * @param {Object} o The item to remove.
12364 * @return {Object} The item removed.
12366 remove : function(o){
12367 return this.removeAt(this.indexOf(o));
12371 * Remove an item from a specified index in the collection.
12372 * @param {Number} index The index within the collection of the item to remove.
12374 removeAt : function(index){
12375 if(index < this.length && index >= 0){
12377 var o = this.items[index];
12378 this.items.splice(index, 1);
12379 var key = this.keys[index];
12380 if(typeof key != "undefined"){
12381 delete this.map[key];
12383 this.keys.splice(index, 1);
12384 this.fireEvent("remove", o, key);
12389 * Removed an item associated with the passed key fom the collection.
12390 * @param {String} key The key of the item to remove.
12392 removeKey : function(key){
12393 return this.removeAt(this.indexOfKey(key));
12397 * Returns the number of items in the collection.
12398 * @return {Number} the number of items in the collection.
12400 getCount : function(){
12401 return this.length;
12405 * Returns index within the collection of the passed Object.
12406 * @param {Object} o The item to find the index of.
12407 * @return {Number} index of the item.
12409 indexOf : function(o){
12410 if(!this.items.indexOf){
12411 for(var i = 0, len = this.items.length; i < len; i++){
12412 if(this.items[i] == o) return i;
12416 return this.items.indexOf(o);
12421 * Returns index within the collection of the passed key.
12422 * @param {String} key The key to find the index of.
12423 * @return {Number} index of the key.
12425 indexOfKey : function(key){
12426 if(!this.keys.indexOf){
12427 for(var i = 0, len = this.keys.length; i < len; i++){
12428 if(this.keys[i] == key) return i;
12432 return this.keys.indexOf(key);
12437 * Returns the item associated with the passed key OR index. Key has priority over index.
12438 * @param {String/Number} key The key or index of the item.
12439 * @return {Object} The item associated with the passed key.
12441 item : function(key){
12442 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12443 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12447 * Returns the item at the specified index.
12448 * @param {Number} index The index of the item.
12451 itemAt : function(index){
12452 return this.items[index];
12456 * Returns the item associated with the passed key.
12457 * @param {String/Number} key The key of the item.
12458 * @return {Object} The item associated with the passed key.
12460 key : function(key){
12461 return this.map[key];
12465 * Returns true if the collection contains the passed Object as an item.
12466 * @param {Object} o The Object to look for in the collection.
12467 * @return {Boolean} True if the collection contains the Object as an item.
12469 contains : function(o){
12470 return this.indexOf(o) != -1;
12474 * Returns true if the collection contains the passed Object as a key.
12475 * @param {String} key The key to look for in the collection.
12476 * @return {Boolean} True if the collection contains the Object as a key.
12478 containsKey : function(key){
12479 return typeof this.map[key] != "undefined";
12483 * Removes all items from the collection.
12485 clear : function(){
12490 this.fireEvent("clear");
12494 * Returns the first item in the collection.
12495 * @return {Object} the first item in the collection..
12497 first : function(){
12498 return this.items[0];
12502 * Returns the last item in the collection.
12503 * @return {Object} the last item in the collection..
12506 return this.items[this.length-1];
12509 _sort : function(property, dir, fn){
12510 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12511 fn = fn || function(a, b){
12514 var c = [], k = this.keys, items = this.items;
12515 for(var i = 0, len = items.length; i < len; i++){
12516 c[c.length] = {key: k[i], value: items[i], index: i};
12518 c.sort(function(a, b){
12519 var v = fn(a[property], b[property]) * dsc;
12521 v = (a.index < b.index ? -1 : 1);
12525 for(var i = 0, len = c.length; i < len; i++){
12526 items[i] = c[i].value;
12529 this.fireEvent("sort", this);
12533 * Sorts this collection with the passed comparison function
12534 * @param {String} direction (optional) "ASC" or "DESC"
12535 * @param {Function} fn (optional) comparison function
12537 sort : function(dir, fn){
12538 this._sort("value", dir, fn);
12542 * Sorts this collection by keys
12543 * @param {String} direction (optional) "ASC" or "DESC"
12544 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12546 keySort : function(dir, fn){
12547 this._sort("key", dir, fn || function(a, b){
12548 return String(a).toUpperCase()-String(b).toUpperCase();
12553 * Returns a range of items in this collection
12554 * @param {Number} startIndex (optional) defaults to 0
12555 * @param {Number} endIndex (optional) default to the last item
12556 * @return {Array} An array of items
12558 getRange : function(start, end){
12559 var items = this.items;
12560 if(items.length < 1){
12563 start = start || 0;
12564 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12567 for(var i = start; i <= end; i++) {
12568 r[r.length] = items[i];
12571 for(var i = start; i >= end; i--) {
12572 r[r.length] = items[i];
12579 * Filter the <i>objects</i> in this collection by a specific property.
12580 * Returns a new collection that has been filtered.
12581 * @param {String} property A property on your objects
12582 * @param {String/RegExp} value Either string that the property values
12583 * should start with or a RegExp to test against the property
12584 * @return {MixedCollection} The new filtered collection
12586 filter : function(property, value){
12587 if(!value.exec){ // not a regex
12588 value = String(value);
12589 if(value.length == 0){
12590 return this.clone();
12592 value = new RegExp("^" + Roo.escapeRe(value), "i");
12594 return this.filterBy(function(o){
12595 return o && value.test(o[property]);
12600 * Filter by a function. * Returns a new collection that has been filtered.
12601 * The passed function will be called with each
12602 * object in the collection. If the function returns true, the value is included
12603 * otherwise it is filtered.
12604 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12605 * @param {Object} scope (optional) The scope of the function (defaults to this)
12606 * @return {MixedCollection} The new filtered collection
12608 filterBy : function(fn, scope){
12609 var r = new Roo.util.MixedCollection();
12610 r.getKey = this.getKey;
12611 var k = this.keys, it = this.items;
12612 for(var i = 0, len = it.length; i < len; i++){
12613 if(fn.call(scope||this, it[i], k[i])){
12614 r.add(k[i], it[i]);
12621 * Creates a duplicate of this collection
12622 * @return {MixedCollection}
12624 clone : function(){
12625 var r = new Roo.util.MixedCollection();
12626 var k = this.keys, it = this.items;
12627 for(var i = 0, len = it.length; i < len; i++){
12628 r.add(k[i], it[i]);
12630 r.getKey = this.getKey;
12635 * Returns the item associated with the passed key or index.
12637 * @param {String/Number} key The key or index of the item.
12638 * @return {Object} The item associated with the passed key.
12640 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12642 * Ext JS Library 1.1.1
12643 * Copyright(c) 2006-2007, Ext JS, LLC.
12645 * Originally Released Under LGPL - original licence link has changed is not relivant.
12648 * <script type="text/javascript">
12651 * @class Roo.util.JSON
12652 * Modified version of Douglas Crockford"s json.js that doesn"t
12653 * mess with the Object prototype
12654 * http://www.json.org/js.html
12657 Roo.util.JSON = new (function(){
12658 var useHasOwn = {}.hasOwnProperty ? true : false;
12660 // crashes Safari in some instances
12661 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12663 var pad = function(n) {
12664 return n < 10 ? "0" + n : n;
12677 var encodeString = function(s){
12678 if (/["\\\x00-\x1f]/.test(s)) {
12679 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12684 c = b.charCodeAt();
12686 Math.floor(c / 16).toString(16) +
12687 (c % 16).toString(16);
12690 return '"' + s + '"';
12693 var encodeArray = function(o){
12694 var a = ["["], b, i, l = o.length, v;
12695 for (i = 0; i < l; i += 1) {
12697 switch (typeof v) {
12706 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12714 var encodeDate = function(o){
12715 return '"' + o.getFullYear() + "-" +
12716 pad(o.getMonth() + 1) + "-" +
12717 pad(o.getDate()) + "T" +
12718 pad(o.getHours()) + ":" +
12719 pad(o.getMinutes()) + ":" +
12720 pad(o.getSeconds()) + '"';
12724 * Encodes an Object, Array or other value
12725 * @param {Mixed} o The variable to encode
12726 * @return {String} The JSON string
12728 this.encode = function(o){
12729 if(typeof o == "undefined" || o === null){
12731 }else if(o instanceof Array){
12732 return encodeArray(o);
12733 }else if(o instanceof Date){
12734 return encodeDate(o);
12735 }else if(typeof o == "string"){
12736 return encodeString(o);
12737 }else if(typeof o == "number"){
12738 return isFinite(o) ? String(o) : "null";
12739 }else if(typeof o == "boolean"){
12742 var a = ["{"], b, i, v;
12744 if(!useHasOwn || o.hasOwnProperty(i)) {
12746 switch (typeof v) {
12755 a.push(this.encode(i), ":",
12756 v === null ? "null" : this.encode(v));
12767 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12768 * @param {String} json The JSON string
12769 * @return {Object} The resulting object
12771 this.decode = function(json){
12775 return eval("(" + json + ')');
12779 * Shorthand for {@link Roo.util.JSON#encode}
12780 * @member Roo encode
12782 Roo.encode = Roo.util.JSON.encode;
12784 * Shorthand for {@link Roo.util.JSON#decode}
12785 * @member Roo decode
12787 Roo.decode = Roo.util.JSON.decode;
12790 * Ext JS Library 1.1.1
12791 * Copyright(c) 2006-2007, Ext JS, LLC.
12793 * Originally Released Under LGPL - original licence link has changed is not relivant.
12796 * <script type="text/javascript">
12800 * @class Roo.util.Format
12801 * Reusable data formatting functions
12804 Roo.util.Format = function(){
12805 var trimRe = /^\s+|\s+$/g;
12808 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12809 * @param {String} value The string to truncate
12810 * @param {Number} length The maximum length to allow before truncating
12811 * @return {String} The converted text
12813 ellipsis : function(value, len){
12814 if(value && value.length > len){
12815 return value.substr(0, len-3)+"...";
12821 * Checks a reference and converts it to empty string if it is undefined
12822 * @param {Mixed} value Reference to check
12823 * @return {Mixed} Empty string if converted, otherwise the original value
12825 undef : function(value){
12826 return typeof value != "undefined" ? value : "";
12830 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12831 * @param {String} value The string to encode
12832 * @return {String} The encoded text
12834 htmlEncode : function(value){
12835 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12839 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12840 * @param {String} value The string to decode
12841 * @return {String} The decoded text
12843 htmlDecode : function(value){
12844 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12848 * Trims any whitespace from either side of a string
12849 * @param {String} value The text to trim
12850 * @return {String} The trimmed text
12852 trim : function(value){
12853 return String(value).replace(trimRe, "");
12857 * Returns a substring from within an original string
12858 * @param {String} value The original text
12859 * @param {Number} start The start index of the substring
12860 * @param {Number} length The length of the substring
12861 * @return {String} The substring
12863 substr : function(value, start, length){
12864 return String(value).substr(start, length);
12868 * Converts a string to all lower case letters
12869 * @param {String} value The text to convert
12870 * @return {String} The converted text
12872 lowercase : function(value){
12873 return String(value).toLowerCase();
12877 * Converts a string to all upper case letters
12878 * @param {String} value The text to convert
12879 * @return {String} The converted text
12881 uppercase : function(value){
12882 return String(value).toUpperCase();
12886 * Converts the first character only of a string to upper case
12887 * @param {String} value The text to convert
12888 * @return {String} The converted text
12890 capitalize : function(value){
12891 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
12895 call : function(value, fn){
12896 if(arguments.length > 2){
12897 var args = Array.prototype.slice.call(arguments, 2);
12898 args.unshift(value);
12900 return /** eval:var:value */ eval(fn).apply(window, args);
12902 /** eval:var:value */
12903 return /** eval:var:value */ eval(fn).call(window, value);
12908 * Format a number as US currency
12909 * @param {Number/String} value The numeric value to format
12910 * @return {String} The formatted currency string
12912 usMoney : function(v){
12913 v = (Math.round((v-0)*100))/100;
12914 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
12916 var ps = v.split('.');
12918 var sub = ps[1] ? '.'+ ps[1] : '.00';
12919 var r = /(\d+)(\d{3})/;
12920 while (r.test(whole)) {
12921 whole = whole.replace(r, '$1' + ',' + '$2');
12923 return "$" + whole + sub ;
12927 * Parse a value into a formatted date using the specified format pattern.
12928 * @param {Mixed} value The value to format
12929 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
12930 * @return {String} The formatted date string
12932 date : function(v, format){
12936 if(!(v instanceof Date)){
12937 v = new Date(Date.parse(v));
12939 return v.dateFormat(format || "m/d/Y");
12943 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
12944 * @param {String} format Any valid date format string
12945 * @return {Function} The date formatting function
12947 dateRenderer : function(format){
12948 return function(v){
12949 return Roo.util.Format.date(v, format);
12954 stripTagsRE : /<\/?[^>]+>/gi,
12957 * Strips all HTML tags
12958 * @param {Mixed} value The text from which to strip tags
12959 * @return {String} The stripped text
12961 stripTags : function(v){
12962 return !v ? v : String(v).replace(this.stripTagsRE, "");
12967 * Ext JS Library 1.1.1
12968 * Copyright(c) 2006-2007, Ext JS, LLC.
12970 * Originally Released Under LGPL - original licence link has changed is not relivant.
12973 * <script type="text/javascript">
12980 * @class Roo.MasterTemplate
12981 * @extends Roo.Template
12982 * Provides a template that can have child templates. The syntax is:
12984 var t = new Roo.MasterTemplate(
12985 '<select name="{name}">',
12986 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
12989 t.add('options', {value: 'foo', text: 'bar'});
12990 // or you can add multiple child elements in one shot
12991 t.addAll('options', [
12992 {value: 'foo', text: 'bar'},
12993 {value: 'foo2', text: 'bar2'},
12994 {value: 'foo3', text: 'bar3'}
12996 // then append, applying the master template values
12997 t.append('my-form', {name: 'my-select'});
12999 * A name attribute for the child template is not required if you have only one child
13000 * template or you want to refer to them by index.
13002 Roo.MasterTemplate = function(){
13003 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13004 this.originalHtml = this.html;
13006 var m, re = this.subTemplateRe;
13009 while(m = re.exec(this.html)){
13010 var name = m[1], content = m[2];
13015 tpl : new Roo.Template(content)
13018 st[name] = st[subIndex];
13020 st[subIndex].tpl.compile();
13021 st[subIndex].tpl.call = this.call.createDelegate(this);
13024 this.subCount = subIndex;
13027 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13029 * The regular expression used to match sub templates
13033 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13036 * Applies the passed values to a child template.
13037 * @param {String/Number} name (optional) The name or index of the child template
13038 * @param {Array/Object} values The values to be applied to the template
13039 * @return {MasterTemplate} this
13041 add : function(name, values){
13042 if(arguments.length == 1){
13043 values = arguments[0];
13046 var s = this.subs[name];
13047 s.buffer[s.buffer.length] = s.tpl.apply(values);
13052 * Applies all the passed values to a child template.
13053 * @param {String/Number} name (optional) The name or index of the child template
13054 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13055 * @param {Boolean} reset (optional) True to reset the template first
13056 * @return {MasterTemplate} this
13058 fill : function(name, values, reset){
13060 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13068 for(var i = 0, len = values.length; i < len; i++){
13069 this.add(name, values[i]);
13075 * Resets the template for reuse
13076 * @return {MasterTemplate} this
13078 reset : function(){
13080 for(var i = 0; i < this.subCount; i++){
13086 applyTemplate : function(values){
13088 var replaceIndex = -1;
13089 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13090 return s[++replaceIndex].buffer.join("");
13092 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13095 apply : function(){
13096 return this.applyTemplate.apply(this, arguments);
13099 compile : function(){return this;}
13103 * Alias for fill().
13106 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13108 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13109 * var tpl = Roo.MasterTemplate.from('element-id');
13110 * @param {String/HTMLElement} el
13111 * @param {Object} config
13114 Roo.MasterTemplate.from = function(el, config){
13115 el = Roo.getDom(el);
13116 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13119 * Ext JS Library 1.1.1
13120 * Copyright(c) 2006-2007, Ext JS, LLC.
13122 * Originally Released Under LGPL - original licence link has changed is not relivant.
13125 * <script type="text/javascript">
13130 * @class Roo.util.CSS
13131 * Utility class for manipulating CSS rules
13134 Roo.util.CSS = function(){
13136 var doc = document;
13138 var camelRe = /(-[a-z])/gi;
13139 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13143 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13144 * tag and appended to the HEAD of the document.
13145 * @param {String} cssText The text containing the css rules
13146 * @param {String} id An id to add to the stylesheet for later removal
13147 * @return {StyleSheet}
13149 createStyleSheet : function(cssText, id){
13151 var head = doc.getElementsByTagName("head")[0];
13152 var rules = doc.createElement("style");
13153 rules.setAttribute("type", "text/css");
13155 rules.setAttribute("id", id);
13158 head.appendChild(rules);
13159 ss = rules.styleSheet;
13160 ss.cssText = cssText;
13163 rules.appendChild(doc.createTextNode(cssText));
13165 rules.cssText = cssText;
13167 head.appendChild(rules);
13168 ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13170 this.cacheStyleSheet(ss);
13175 * Removes a style or link tag by id
13176 * @param {String} id The id of the tag
13178 removeStyleSheet : function(id){
13179 var existing = doc.getElementById(id);
13181 existing.parentNode.removeChild(existing);
13186 * Dynamically swaps an existing stylesheet reference for a new one
13187 * @param {String} id The id of an existing link tag to remove
13188 * @param {String} url The href of the new stylesheet to include
13190 swapStyleSheet : function(id, url){
13191 this.removeStyleSheet(id);
13192 var ss = doc.createElement("link");
13193 ss.setAttribute("rel", "stylesheet");
13194 ss.setAttribute("type", "text/css");
13195 ss.setAttribute("id", id);
13196 ss.setAttribute("href", url);
13197 doc.getElementsByTagName("head")[0].appendChild(ss);
13201 * Refresh the rule cache if you have dynamically added stylesheets
13202 * @return {Object} An object (hash) of rules indexed by selector
13204 refreshCache : function(){
13205 return this.getRules(true);
13209 cacheStyleSheet : function(ss){
13213 try{// try catch for cross domain access issue
13214 var ssRules = ss.cssRules || ss.rules;
13215 for(var j = ssRules.length-1; j >= 0; --j){
13216 rules[ssRules[j].selectorText] = ssRules[j];
13222 * Gets all css rules for the document
13223 * @param {Boolean} refreshCache true to refresh the internal cache
13224 * @return {Object} An object (hash) of rules indexed by selector
13226 getRules : function(refreshCache){
13227 if(rules == null || refreshCache){
13229 var ds = doc.styleSheets;
13230 for(var i =0, len = ds.length; i < len; i++){
13232 this.cacheStyleSheet(ds[i]);
13240 * Gets an an individual CSS rule by selector(s)
13241 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13242 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13243 * @return {CSSRule} The CSS rule or null if one is not found
13245 getRule : function(selector, refreshCache){
13246 var rs = this.getRules(refreshCache);
13247 if(!(selector instanceof Array)){
13248 return rs[selector];
13250 for(var i = 0; i < selector.length; i++){
13251 if(rs[selector[i]]){
13252 return rs[selector[i]];
13260 * Updates a rule property
13261 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13262 * @param {String} property The css property
13263 * @param {String} value The new value for the property
13264 * @return {Boolean} true If a rule was found and updated
13266 updateRule : function(selector, property, value){
13267 if(!(selector instanceof Array)){
13268 var rule = this.getRule(selector);
13270 rule.style[property.replace(camelRe, camelFn)] = value;
13274 for(var i = 0; i < selector.length; i++){
13275 if(this.updateRule(selector[i], property, value)){
13285 * Ext JS Library 1.1.1
13286 * Copyright(c) 2006-2007, Ext JS, LLC.
13288 * Originally Released Under LGPL - original licence link has changed is not relivant.
13291 * <script type="text/javascript">
13297 * @class Roo.util.ClickRepeater
13298 * @extends Roo.util.Observable
13300 * A wrapper class which can be applied to any element. Fires a "click" event while the
13301 * mouse is pressed. The interval between firings may be specified in the config but
13302 * defaults to 10 milliseconds.
13304 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13306 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13307 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13308 * Similar to an autorepeat key delay.
13309 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13310 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13311 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13312 * "interval" and "delay" are ignored. "immediate" is honored.
13313 * @cfg {Boolean} preventDefault True to prevent the default click event
13314 * @cfg {Boolean} stopDefault True to stop the default click event
13317 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13318 * 2007-02-02 jvs Renamed to ClickRepeater
13319 * 2007-02-03 jvs Modifications for FF Mac and Safari
13322 * @param {String/HTMLElement/Element} el The element to listen on
13323 * @param {Object} config
13325 Roo.util.ClickRepeater = function(el, config)
13327 this.el = Roo.get(el);
13328 this.el.unselectable();
13330 Roo.apply(this, config);
13335 * Fires when the mouse button is depressed.
13336 * @param {Roo.util.ClickRepeater} this
13338 "mousedown" : true,
13341 * Fires on a specified interval during the time the element is pressed.
13342 * @param {Roo.util.ClickRepeater} this
13347 * Fires when the mouse key is released.
13348 * @param {Roo.util.ClickRepeater} this
13353 this.el.on("mousedown", this.handleMouseDown, this);
13354 if(this.preventDefault || this.stopDefault){
13355 this.el.on("click", function(e){
13356 if(this.preventDefault){
13357 e.preventDefault();
13359 if(this.stopDefault){
13365 // allow inline handler
13367 this.on("click", this.handler, this.scope || this);
13370 Roo.util.ClickRepeater.superclass.constructor.call(this);
13373 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13376 preventDefault : true,
13377 stopDefault : false,
13381 handleMouseDown : function(){
13382 clearTimeout(this.timer);
13384 if(this.pressClass){
13385 this.el.addClass(this.pressClass);
13387 this.mousedownTime = new Date();
13389 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13390 this.el.on("mouseout", this.handleMouseOut, this);
13392 this.fireEvent("mousedown", this);
13393 this.fireEvent("click", this);
13395 this.timer = this.click.defer(this.delay || this.interval, this);
13399 click : function(){
13400 this.fireEvent("click", this);
13401 this.timer = this.click.defer(this.getInterval(), this);
13405 getInterval: function(){
13406 if(!this.accelerate){
13407 return this.interval;
13409 var pressTime = this.mousedownTime.getElapsed();
13410 if(pressTime < 500){
13412 }else if(pressTime < 1700){
13414 }else if(pressTime < 2600){
13416 }else if(pressTime < 3500){
13418 }else if(pressTime < 4400){
13420 }else if(pressTime < 5300){
13422 }else if(pressTime < 6200){
13430 handleMouseOut : function(){
13431 clearTimeout(this.timer);
13432 if(this.pressClass){
13433 this.el.removeClass(this.pressClass);
13435 this.el.on("mouseover", this.handleMouseReturn, this);
13439 handleMouseReturn : function(){
13440 this.el.un("mouseover", this.handleMouseReturn);
13441 if(this.pressClass){
13442 this.el.addClass(this.pressClass);
13448 handleMouseUp : function(){
13449 clearTimeout(this.timer);
13450 this.el.un("mouseover", this.handleMouseReturn);
13451 this.el.un("mouseout", this.handleMouseOut);
13452 Roo.get(document).un("mouseup", this.handleMouseUp);
13453 this.el.removeClass(this.pressClass);
13454 this.fireEvent("mouseup", this);
13458 * Ext JS Library 1.1.1
13459 * Copyright(c) 2006-2007, Ext JS, LLC.
13461 * Originally Released Under LGPL - original licence link has changed is not relivant.
13464 * <script type="text/javascript">
13469 * @class Roo.KeyNav
13470 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13471 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13472 * way to implement custom navigation schemes for any UI component.</p>
13473 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13474 * pageUp, pageDown, del, home, end. Usage:</p>
13476 var nav = new Roo.KeyNav("my-element", {
13477 "left" : function(e){
13478 this.moveLeft(e.ctrlKey);
13480 "right" : function(e){
13481 this.moveRight(e.ctrlKey);
13483 "enter" : function(e){
13490 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13491 * @param {Object} config The config
13493 Roo.KeyNav = function(el, config){
13494 this.el = Roo.get(el);
13495 Roo.apply(this, config);
13496 if(!this.disabled){
13497 this.disabled = true;
13502 Roo.KeyNav.prototype = {
13504 * @cfg {Boolean} disabled
13505 * True to disable this KeyNav instance (defaults to false)
13509 * @cfg {String} defaultEventAction
13510 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13511 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13512 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13514 defaultEventAction: "stopEvent",
13516 * @cfg {Boolean} forceKeyDown
13517 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13518 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13519 * handle keydown instead of keypress.
13521 forceKeyDown : false,
13524 prepareEvent : function(e){
13525 var k = e.getKey();
13526 var h = this.keyToHandler[k];
13527 //if(h && this[h]){
13528 // e.stopPropagation();
13530 if(Roo.isSafari && h && k >= 37 && k <= 40){
13536 relay : function(e){
13537 var k = e.getKey();
13538 var h = this.keyToHandler[k];
13540 if(this.doRelay(e, this[h], h) !== true){
13541 e[this.defaultEventAction]();
13547 doRelay : function(e, h, hname){
13548 return h.call(this.scope || this, e);
13551 // possible handlers
13565 // quick lookup hash
13582 * Enable this KeyNav
13584 enable: function(){
13586 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13587 // the EventObject will normalize Safari automatically
13588 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13589 this.el.on("keydown", this.relay, this);
13591 this.el.on("keydown", this.prepareEvent, this);
13592 this.el.on("keypress", this.relay, this);
13594 this.disabled = false;
13599 * Disable this KeyNav
13601 disable: function(){
13602 if(!this.disabled){
13603 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13604 this.el.un("keydown", this.relay);
13606 this.el.un("keydown", this.prepareEvent);
13607 this.el.un("keypress", this.relay);
13609 this.disabled = true;
13614 * Ext JS Library 1.1.1
13615 * Copyright(c) 2006-2007, Ext JS, LLC.
13617 * Originally Released Under LGPL - original licence link has changed is not relivant.
13620 * <script type="text/javascript">
13625 * @class Roo.KeyMap
13626 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13627 * The constructor accepts the same config object as defined by {@link #addBinding}.
13628 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13629 * combination it will call the function with this signature (if the match is a multi-key
13630 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13631 * A KeyMap can also handle a string representation of keys.<br />
13634 // map one key by key code
13635 var map = new Roo.KeyMap("my-element", {
13636 key: 13, // or Roo.EventObject.ENTER
13641 // map multiple keys to one action by string
13642 var map = new Roo.KeyMap("my-element", {
13648 // map multiple keys to multiple actions by strings and array of codes
13649 var map = new Roo.KeyMap("my-element", [
13652 fn: function(){ alert("Return was pressed"); }
13655 fn: function(){ alert('a, b or c was pressed'); }
13660 fn: function(){ alert('Control + shift + tab was pressed.'); }
13664 * <b>Note: A KeyMap starts enabled</b>
13666 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13667 * @param {Object} config The config (see {@link #addBinding})
13668 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13670 Roo.KeyMap = function(el, config, eventName){
13671 this.el = Roo.get(el);
13672 this.eventName = eventName || "keydown";
13673 this.bindings = [];
13675 this.addBinding(config);
13680 Roo.KeyMap.prototype = {
13682 * True to stop the event from bubbling and prevent the default browser action if the
13683 * key was handled by the KeyMap (defaults to false)
13689 * Add a new binding to this KeyMap. The following config object properties are supported:
13691 Property Type Description
13692 ---------- --------------- ----------------------------------------------------------------------
13693 key String/Array A single keycode or an array of keycodes to handle
13694 shift Boolean True to handle key only when shift is pressed (defaults to false)
13695 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13696 alt Boolean True to handle key only when alt is pressed (defaults to false)
13697 fn Function The function to call when KeyMap finds the expected key combination
13698 scope Object The scope of the callback function
13704 var map = new Roo.KeyMap(document, {
13705 key: Roo.EventObject.ENTER,
13710 //Add a new binding to the existing KeyMap later
13718 * @param {Object/Array} config A single KeyMap config or an array of configs
13720 addBinding : function(config){
13721 if(config instanceof Array){
13722 for(var i = 0, len = config.length; i < len; i++){
13723 this.addBinding(config[i]);
13727 var keyCode = config.key,
13728 shift = config.shift,
13729 ctrl = config.ctrl,
13732 scope = config.scope;
13733 if(typeof keyCode == "string"){
13735 var keyString = keyCode.toUpperCase();
13736 for(var j = 0, len = keyString.length; j < len; j++){
13737 ks.push(keyString.charCodeAt(j));
13741 var keyArray = keyCode instanceof Array;
13742 var handler = function(e){
13743 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13744 var k = e.getKey();
13746 for(var i = 0, len = keyCode.length; i < len; i++){
13747 if(keyCode[i] == k){
13748 if(this.stopEvent){
13751 fn.call(scope || window, k, e);
13757 if(this.stopEvent){
13760 fn.call(scope || window, k, e);
13765 this.bindings.push(handler);
13769 * Shorthand for adding a single key listener
13770 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13771 * following options:
13772 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13773 * @param {Function} fn The function to call
13774 * @param {Object} scope (optional) The scope of the function
13776 on : function(key, fn, scope){
13777 var keyCode, shift, ctrl, alt;
13778 if(typeof key == "object" && !(key instanceof Array)){
13797 handleKeyDown : function(e){
13798 if(this.enabled){ //just in case
13799 var b = this.bindings;
13800 for(var i = 0, len = b.length; i < len; i++){
13801 b[i].call(this, e);
13807 * Returns true if this KeyMap is enabled
13808 * @return {Boolean}
13810 isEnabled : function(){
13811 return this.enabled;
13815 * Enables this KeyMap
13817 enable: function(){
13819 this.el.on(this.eventName, this.handleKeyDown, this);
13820 this.enabled = true;
13825 * Disable this KeyMap
13827 disable: function(){
13829 this.el.removeListener(this.eventName, this.handleKeyDown, this);
13830 this.enabled = false;
13835 * Ext JS Library 1.1.1
13836 * Copyright(c) 2006-2007, Ext JS, LLC.
13838 * Originally Released Under LGPL - original licence link has changed is not relivant.
13841 * <script type="text/javascript">
13846 * @class Roo.util.TextMetrics
13847 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
13848 * wide, in pixels, a given block of text will be.
13851 Roo.util.TextMetrics = function(){
13855 * Measures the size of the specified text
13856 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
13857 * that can affect the size of the rendered text
13858 * @param {String} text The text to measure
13859 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13860 * in order to accurately measure the text height
13861 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13863 measure : function(el, text, fixedWidth){
13865 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
13868 shared.setFixedWidth(fixedWidth || 'auto');
13869 return shared.getSize(text);
13873 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
13874 * the overhead of multiple calls to initialize the style properties on each measurement.
13875 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
13876 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13877 * in order to accurately measure the text height
13878 * @return {Roo.util.TextMetrics.Instance} instance The new instance
13880 createInstance : function(el, fixedWidth){
13881 return Roo.util.TextMetrics.Instance(el, fixedWidth);
13888 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
13889 var ml = new Roo.Element(document.createElement('div'));
13890 document.body.appendChild(ml.dom);
13891 ml.position('absolute');
13892 ml.setLeftTop(-1000, -1000);
13896 ml.setWidth(fixedWidth);
13901 * Returns the size of the specified text based on the internal element's style and width properties
13902 * @memberOf Roo.util.TextMetrics.Instance#
13903 * @param {String} text The text to measure
13904 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13906 getSize : function(text){
13908 var s = ml.getSize();
13914 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
13915 * that can affect the size of the rendered text
13916 * @memberOf Roo.util.TextMetrics.Instance#
13917 * @param {String/HTMLElement} el The element, dom node or id
13919 bind : function(el){
13921 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
13926 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
13927 * to set a fixed width in order to accurately measure the text height.
13928 * @memberOf Roo.util.TextMetrics.Instance#
13929 * @param {Number} width The width to set on the element
13931 setFixedWidth : function(width){
13932 ml.setWidth(width);
13936 * Returns the measured width of the specified text
13937 * @memberOf Roo.util.TextMetrics.Instance#
13938 * @param {String} text The text to measure
13939 * @return {Number} width The width in pixels
13941 getWidth : function(text){
13942 ml.dom.style.width = 'auto';
13943 return this.getSize(text).width;
13947 * Returns the measured height of the specified text. For multiline text, be sure to call
13948 * {@link #setFixedWidth} if necessary.
13949 * @memberOf Roo.util.TextMetrics.Instance#
13950 * @param {String} text The text to measure
13951 * @return {Number} height The height in pixels
13953 getHeight : function(text){
13954 return this.getSize(text).height;
13958 instance.bind(bindTo);
13963 // backwards compat
13964 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
13966 * Ext JS Library 1.1.1
13967 * Copyright(c) 2006-2007, Ext JS, LLC.
13969 * Originally Released Under LGPL - original licence link has changed is not relivant.
13972 * <script type="text/javascript">
13976 * @class Roo.state.Provider
13977 * Abstract base class for state provider implementations. This class provides methods
13978 * for encoding and decoding <b>typed</b> variables including dates and defines the
13979 * Provider interface.
13981 Roo.state.Provider = function(){
13983 * @event statechange
13984 * Fires when a state change occurs.
13985 * @param {Provider} this This state provider
13986 * @param {String} key The state key which was changed
13987 * @param {String} value The encoded value for the state
13990 "statechange": true
13993 Roo.state.Provider.superclass.constructor.call(this);
13995 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
13997 * Returns the current value for a key
13998 * @param {String} name The key name
13999 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14000 * @return {Mixed} The state data
14002 get : function(name, defaultValue){
14003 return typeof this.state[name] == "undefined" ?
14004 defaultValue : this.state[name];
14008 * Clears a value from the state
14009 * @param {String} name The key name
14011 clear : function(name){
14012 delete this.state[name];
14013 this.fireEvent("statechange", this, name, null);
14017 * Sets the value for a key
14018 * @param {String} name The key name
14019 * @param {Mixed} value The value to set
14021 set : function(name, value){
14022 this.state[name] = value;
14023 this.fireEvent("statechange", this, name, value);
14027 * Decodes a string previously encoded with {@link #encodeValue}.
14028 * @param {String} value The value to decode
14029 * @return {Mixed} The decoded value
14031 decodeValue : function(cookie){
14032 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14033 var matches = re.exec(unescape(cookie));
14034 if(!matches || !matches[1]) return; // non state cookie
14035 var type = matches[1];
14036 var v = matches[2];
14039 return parseFloat(v);
14041 return new Date(Date.parse(v));
14046 var values = v.split("^");
14047 for(var i = 0, len = values.length; i < len; i++){
14048 all.push(this.decodeValue(values[i]));
14053 var values = v.split("^");
14054 for(var i = 0, len = values.length; i < len; i++){
14055 var kv = values[i].split("=");
14056 all[kv[0]] = this.decodeValue(kv[1]);
14065 * Encodes a value including type information. Decode with {@link #decodeValue}.
14066 * @param {Mixed} value The value to encode
14067 * @return {String} The encoded value
14069 encodeValue : function(v){
14071 if(typeof v == "number"){
14073 }else if(typeof v == "boolean"){
14074 enc = "b:" + (v ? "1" : "0");
14075 }else if(v instanceof Date){
14076 enc = "d:" + v.toGMTString();
14077 }else if(v instanceof Array){
14079 for(var i = 0, len = v.length; i < len; i++){
14080 flat += this.encodeValue(v[i]);
14081 if(i != len-1) flat += "^";
14084 }else if(typeof v == "object"){
14087 if(typeof v[key] != "function"){
14088 flat += key + "=" + this.encodeValue(v[key]) + "^";
14091 enc = "o:" + flat.substring(0, flat.length-1);
14095 return escape(enc);
14101 * Ext JS Library 1.1.1
14102 * Copyright(c) 2006-2007, Ext JS, LLC.
14104 * Originally Released Under LGPL - original licence link has changed is not relivant.
14107 * <script type="text/javascript">
14110 * @class Roo.state.Manager
14111 * This is the global state manager. By default all components that are "state aware" check this class
14112 * for state information if you don't pass them a custom state provider. In order for this class
14113 * to be useful, it must be initialized with a provider when your application initializes.
14115 // in your initialization function
14117 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14119 // supposed you have a {@link Roo.BorderLayout}
14120 var layout = new Roo.BorderLayout(...);
14121 layout.restoreState();
14122 // or a {Roo.BasicDialog}
14123 var dialog = new Roo.BasicDialog(...);
14124 dialog.restoreState();
14128 Roo.state.Manager = function(){
14129 var provider = new Roo.state.Provider();
14133 * Configures the default state provider for your application
14134 * @param {Provider} stateProvider The state provider to set
14136 setProvider : function(stateProvider){
14137 provider = stateProvider;
14141 * Returns the current value for a key
14142 * @param {String} name The key name
14143 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14144 * @return {Mixed} The state data
14146 get : function(key, defaultValue){
14147 return provider.get(key, defaultValue);
14151 * Sets the value for a key
14152 * @param {String} name The key name
14153 * @param {Mixed} value The state data
14155 set : function(key, value){
14156 provider.set(key, value);
14160 * Clears a value from the state
14161 * @param {String} name The key name
14163 clear : function(key){
14164 provider.clear(key);
14168 * Gets the currently configured state provider
14169 * @return {Provider} The state provider
14171 getProvider : function(){
14178 * Ext JS Library 1.1.1
14179 * Copyright(c) 2006-2007, Ext JS, LLC.
14181 * Originally Released Under LGPL - original licence link has changed is not relivant.
14184 * <script type="text/javascript">
14187 * @class Roo.state.CookieProvider
14188 * @extends Roo.state.Provider
14189 * The default Provider implementation which saves state via cookies.
14192 var cp = new Roo.state.CookieProvider({
14194 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14195 domain: "roojs.com"
14197 Roo.state.Manager.setProvider(cp);
14199 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14200 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14201 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14202 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14203 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14204 * domain the page is running on including the 'www' like 'www.roojs.com')
14205 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14207 * Create a new CookieProvider
14208 * @param {Object} config The configuration object
14210 Roo.state.CookieProvider = function(config){
14211 Roo.state.CookieProvider.superclass.constructor.call(this);
14213 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14214 this.domain = null;
14215 this.secure = false;
14216 Roo.apply(this, config);
14217 this.state = this.readCookies();
14220 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14222 set : function(name, value){
14223 if(typeof value == "undefined" || value === null){
14227 this.setCookie(name, value);
14228 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14232 clear : function(name){
14233 this.clearCookie(name);
14234 Roo.state.CookieProvider.superclass.clear.call(this, name);
14238 readCookies : function(){
14240 var c = document.cookie + ";";
14241 var re = /\s?(.*?)=(.*?);/g;
14243 while((matches = re.exec(c)) != null){
14244 var name = matches[1];
14245 var value = matches[2];
14246 if(name && name.substring(0,3) == "ys-"){
14247 cookies[name.substr(3)] = this.decodeValue(value);
14254 setCookie : function(name, value){
14255 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14256 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14257 ((this.path == null) ? "" : ("; path=" + this.path)) +
14258 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14259 ((this.secure == true) ? "; secure" : "");
14263 clearCookie : function(name){
14264 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14265 ((this.path == null) ? "" : ("; path=" + this.path)) +
14266 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14267 ((this.secure == true) ? "; secure" : "");
14271 * Ext JS Library 1.1.1
14272 * Copyright(c) 2006-2007, Ext JS, LLC.
14274 * Originally Released Under LGPL - original licence link has changed is not relivant.
14277 * <script type="text/javascript">
14283 * These classes are derivatives of the similarly named classes in the YUI Library.
14284 * The original license:
14285 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
14286 * Code licensed under the BSD License:
14287 * http://developer.yahoo.net/yui/license.txt
14292 var Event=Roo.EventManager;
14293 var Dom=Roo.lib.Dom;
14296 * @class Roo.dd.DragDrop
14297 * Defines the interface and base operation of items that that can be
14298 * dragged or can be drop targets. It was designed to be extended, overriding
14299 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
14300 * Up to three html elements can be associated with a DragDrop instance:
14302 * <li>linked element: the element that is passed into the constructor.
14303 * This is the element which defines the boundaries for interaction with
14304 * other DragDrop objects.</li>
14305 * <li>handle element(s): The drag operation only occurs if the element that
14306 * was clicked matches a handle element. By default this is the linked
14307 * element, but there are times that you will want only a portion of the
14308 * linked element to initiate the drag operation, and the setHandleElId()
14309 * method provides a way to define this.</li>
14310 * <li>drag element: this represents the element that would be moved along
14311 * with the cursor during a drag operation. By default, this is the linked
14312 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
14313 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
14316 * This class should not be instantiated until the onload event to ensure that
14317 * the associated elements are available.
14318 * The following would define a DragDrop obj that would interact with any
14319 * other DragDrop obj in the "group1" group:
14321 * dd = new Roo.dd.DragDrop("div1", "group1");
14323 * Since none of the event handlers have been implemented, nothing would
14324 * actually happen if you were to run the code above. Normally you would
14325 * override this class or one of the default implementations, but you can
14326 * also override the methods you want on an instance of the class...
14328 * dd.onDragDrop = function(e, id) {
14329 * alert("dd was dropped on " + id);
14333 * @param {String} id of the element that is linked to this instance
14334 * @param {String} sGroup the group of related DragDrop objects
14335 * @param {object} config an object containing configurable attributes
14336 * Valid properties for DragDrop:
14337 * padding, isTarget, maintainOffset, primaryButtonOnly
14339 Roo.dd.DragDrop = function(id, sGroup, config) {
14341 this.init(id, sGroup, config);
14345 Roo.dd.DragDrop.prototype = {
14348 * The id of the element associated with this object. This is what we
14349 * refer to as the "linked element" because the size and position of
14350 * this element is used to determine when the drag and drop objects have
14358 * Configuration attributes passed into the constructor
14365 * The id of the element that will be dragged. By default this is same
14366 * as the linked element , but could be changed to another element. Ex:
14368 * @property dragElId
14375 * the id of the element that initiates the drag operation. By default
14376 * this is the linked element, but could be changed to be a child of this
14377 * element. This lets us do things like only starting the drag when the
14378 * header element within the linked html element is clicked.
14379 * @property handleElId
14386 * An associative array of HTML tags that will be ignored if clicked.
14387 * @property invalidHandleTypes
14388 * @type {string: string}
14390 invalidHandleTypes: null,
14393 * An associative array of ids for elements that will be ignored if clicked
14394 * @property invalidHandleIds
14395 * @type {string: string}
14397 invalidHandleIds: null,
14400 * An indexted array of css class names for elements that will be ignored
14402 * @property invalidHandleClasses
14405 invalidHandleClasses: null,
14408 * The linked element's absolute X position at the time the drag was
14410 * @property startPageX
14417 * The linked element's absolute X position at the time the drag was
14419 * @property startPageY
14426 * The group defines a logical collection of DragDrop objects that are
14427 * related. Instances only get events when interacting with other
14428 * DragDrop object in the same group. This lets us define multiple
14429 * groups using a single DragDrop subclass if we want.
14431 * @type {string: string}
14436 * Individual drag/drop instances can be locked. This will prevent
14437 * onmousedown start drag.
14445 * Lock this instance
14448 lock: function() { this.locked = true; },
14451 * Unlock this instace
14454 unlock: function() { this.locked = false; },
14457 * By default, all insances can be a drop target. This can be disabled by
14458 * setting isTarget to false.
14465 * The padding configured for this drag and drop object for calculating
14466 * the drop zone intersection with this object.
14473 * Cached reference to the linked element
14474 * @property _domRef
14480 * Internal typeof flag
14481 * @property __ygDragDrop
14484 __ygDragDrop: true,
14487 * Set to true when horizontal contraints are applied
14488 * @property constrainX
14495 * Set to true when vertical contraints are applied
14496 * @property constrainY
14503 * The left constraint
14511 * The right constraint
14519 * The up constraint
14528 * The down constraint
14536 * Maintain offsets when we resetconstraints. Set to true when you want
14537 * the position of the element relative to its parent to stay the same
14538 * when the page changes
14540 * @property maintainOffset
14543 maintainOffset: false,
14546 * Array of pixel locations the element will snap to if we specified a
14547 * horizontal graduation/interval. This array is generated automatically
14548 * when you define a tick interval.
14555 * Array of pixel locations the element will snap to if we specified a
14556 * vertical graduation/interval. This array is generated automatically
14557 * when you define a tick interval.
14564 * By default the drag and drop instance will only respond to the primary
14565 * button click (left button for a right-handed mouse). Set to true to
14566 * allow drag and drop to start with any mouse click that is propogated
14568 * @property primaryButtonOnly
14571 primaryButtonOnly: true,
14574 * The availabe property is false until the linked dom element is accessible.
14575 * @property available
14581 * By default, drags can only be initiated if the mousedown occurs in the
14582 * region the linked element is. This is done in part to work around a
14583 * bug in some browsers that mis-report the mousedown if the previous
14584 * mouseup happened outside of the window. This property is set to true
14585 * if outer handles are defined.
14587 * @property hasOuterHandles
14591 hasOuterHandles: false,
14594 * Code that executes immediately before the startDrag event
14595 * @method b4StartDrag
14598 b4StartDrag: function(x, y) { },
14601 * Abstract method called after a drag/drop object is clicked
14602 * and the drag or mousedown time thresholds have beeen met.
14603 * @method startDrag
14604 * @param {int} X click location
14605 * @param {int} Y click location
14607 startDrag: function(x, y) { /* override this */ },
14610 * Code that executes immediately before the onDrag event
14614 b4Drag: function(e) { },
14617 * Abstract method called during the onMouseMove event while dragging an
14620 * @param {Event} e the mousemove event
14622 onDrag: function(e) { /* override this */ },
14625 * Abstract method called when this element fist begins hovering over
14626 * another DragDrop obj
14627 * @method onDragEnter
14628 * @param {Event} e the mousemove event
14629 * @param {String|DragDrop[]} id In POINT mode, the element
14630 * id this is hovering over. In INTERSECT mode, an array of one or more
14631 * dragdrop items being hovered over.
14633 onDragEnter: function(e, id) { /* override this */ },
14636 * Code that executes immediately before the onDragOver event
14637 * @method b4DragOver
14640 b4DragOver: function(e) { },
14643 * Abstract method called when this element is hovering over another
14645 * @method onDragOver
14646 * @param {Event} e the mousemove event
14647 * @param {String|DragDrop[]} id In POINT mode, the element
14648 * id this is hovering over. In INTERSECT mode, an array of dd items
14649 * being hovered over.
14651 onDragOver: function(e, id) { /* override this */ },
14654 * Code that executes immediately before the onDragOut event
14655 * @method b4DragOut
14658 b4DragOut: function(e) { },
14661 * Abstract method called when we are no longer hovering over an element
14662 * @method onDragOut
14663 * @param {Event} e the mousemove event
14664 * @param {String|DragDrop[]} id In POINT mode, the element
14665 * id this was hovering over. In INTERSECT mode, an array of dd items
14666 * that the mouse is no longer over.
14668 onDragOut: function(e, id) { /* override this */ },
14671 * Code that executes immediately before the onDragDrop event
14672 * @method b4DragDrop
14675 b4DragDrop: function(e) { },
14678 * Abstract method called when this item is dropped on another DragDrop
14680 * @method onDragDrop
14681 * @param {Event} e the mouseup event
14682 * @param {String|DragDrop[]} id In POINT mode, the element
14683 * id this was dropped on. In INTERSECT mode, an array of dd items this
14686 onDragDrop: function(e, id) { /* override this */ },
14689 * Abstract method called when this item is dropped on an area with no
14691 * @method onInvalidDrop
14692 * @param {Event} e the mouseup event
14694 onInvalidDrop: function(e) { /* override this */ },
14697 * Code that executes immediately before the endDrag event
14698 * @method b4EndDrag
14701 b4EndDrag: function(e) { },
14704 * Fired when we are done dragging the object
14706 * @param {Event} e the mouseup event
14708 endDrag: function(e) { /* override this */ },
14711 * Code executed immediately before the onMouseDown event
14712 * @method b4MouseDown
14713 * @param {Event} e the mousedown event
14716 b4MouseDown: function(e) { },
14719 * Event handler that fires when a drag/drop obj gets a mousedown
14720 * @method onMouseDown
14721 * @param {Event} e the mousedown event
14723 onMouseDown: function(e) { /* override this */ },
14726 * Event handler that fires when a drag/drop obj gets a mouseup
14727 * @method onMouseUp
14728 * @param {Event} e the mouseup event
14730 onMouseUp: function(e) { /* override this */ },
14733 * Override the onAvailable method to do what is needed after the initial
14734 * position was determined.
14735 * @method onAvailable
14737 onAvailable: function () {
14741 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
14744 defaultPadding : {left:0, right:0, top:0, bottom:0},
14747 * Initializes the drag drop object's constraints to restrict movement to a certain element.
14751 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
14752 { dragElId: "existingProxyDiv" });
14753 dd.startDrag = function(){
14754 this.constrainTo("parent-id");
14757 * Or you can initalize it using the {@link Roo.Element} object:
14759 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
14760 startDrag : function(){
14761 this.constrainTo("parent-id");
14765 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
14766 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
14767 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
14768 * an object containing the sides to pad. For example: {right:10, bottom:10}
14769 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
14771 constrainTo : function(constrainTo, pad, inContent){
14772 if(typeof pad == "number"){
14773 pad = {left: pad, right:pad, top:pad, bottom:pad};
14775 pad = pad || this.defaultPadding;
14776 var b = Roo.get(this.getEl()).getBox();
14777 var ce = Roo.get(constrainTo);
14778 var s = ce.getScroll();
14779 var c, cd = ce.dom;
14780 if(cd == document.body){
14781 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
14784 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
14788 var topSpace = b.y - c.y;
14789 var leftSpace = b.x - c.x;
14791 this.resetConstraints();
14792 this.setXConstraint(leftSpace - (pad.left||0), // left
14793 c.width - leftSpace - b.width - (pad.right||0) //right
14795 this.setYConstraint(topSpace - (pad.top||0), //top
14796 c.height - topSpace - b.height - (pad.bottom||0) //bottom
14801 * Returns a reference to the linked element
14803 * @return {HTMLElement} the html element
14805 getEl: function() {
14806 if (!this._domRef) {
14807 this._domRef = Roo.getDom(this.id);
14810 return this._domRef;
14814 * Returns a reference to the actual element to drag. By default this is
14815 * the same as the html element, but it can be assigned to another
14816 * element. An example of this can be found in Roo.dd.DDProxy
14817 * @method getDragEl
14818 * @return {HTMLElement} the html element
14820 getDragEl: function() {
14821 return Roo.getDom(this.dragElId);
14825 * Sets up the DragDrop object. Must be called in the constructor of any
14826 * Roo.dd.DragDrop subclass
14828 * @param id the id of the linked element
14829 * @param {String} sGroup the group of related items
14830 * @param {object} config configuration attributes
14832 init: function(id, sGroup, config) {
14833 this.initTarget(id, sGroup, config);
14834 Event.on(this.id, "mousedown", this.handleMouseDown, this);
14835 // Event.on(this.id, "selectstart", Event.preventDefault);
14839 * Initializes Targeting functionality only... the object does not
14840 * get a mousedown handler.
14841 * @method initTarget
14842 * @param id the id of the linked element
14843 * @param {String} sGroup the group of related items
14844 * @param {object} config configuration attributes
14846 initTarget: function(id, sGroup, config) {
14848 // configuration attributes
14849 this.config = config || {};
14851 // create a local reference to the drag and drop manager
14852 this.DDM = Roo.dd.DDM;
14853 // initialize the groups array
14856 // assume that we have an element reference instead of an id if the
14857 // parameter is not a string
14858 if (typeof id !== "string") {
14865 // add to an interaction group
14866 this.addToGroup((sGroup) ? sGroup : "default");
14868 // We don't want to register this as the handle with the manager
14869 // so we just set the id rather than calling the setter.
14870 this.handleElId = id;
14872 // the linked element is the element that gets dragged by default
14873 this.setDragElId(id);
14875 // by default, clicked anchors will not start drag operations.
14876 this.invalidHandleTypes = { A: "A" };
14877 this.invalidHandleIds = {};
14878 this.invalidHandleClasses = [];
14880 this.applyConfig();
14882 this.handleOnAvailable();
14886 * Applies the configuration parameters that were passed into the constructor.
14887 * This is supposed to happen at each level through the inheritance chain. So
14888 * a DDProxy implentation will execute apply config on DDProxy, DD, and
14889 * DragDrop in order to get all of the parameters that are available in
14891 * @method applyConfig
14893 applyConfig: function() {
14895 // configurable properties:
14896 // padding, isTarget, maintainOffset, primaryButtonOnly
14897 this.padding = this.config.padding || [0, 0, 0, 0];
14898 this.isTarget = (this.config.isTarget !== false);
14899 this.maintainOffset = (this.config.maintainOffset);
14900 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
14905 * Executed when the linked element is available
14906 * @method handleOnAvailable
14909 handleOnAvailable: function() {
14910 this.available = true;
14911 this.resetConstraints();
14912 this.onAvailable();
14916 * Configures the padding for the target zone in px. Effectively expands
14917 * (or reduces) the virtual object size for targeting calculations.
14918 * Supports css-style shorthand; if only one parameter is passed, all sides
14919 * will have that padding, and if only two are passed, the top and bottom
14920 * will have the first param, the left and right the second.
14921 * @method setPadding
14922 * @param {int} iTop Top pad
14923 * @param {int} iRight Right pad
14924 * @param {int} iBot Bot pad
14925 * @param {int} iLeft Left pad
14927 setPadding: function(iTop, iRight, iBot, iLeft) {
14928 // this.padding = [iLeft, iRight, iTop, iBot];
14929 if (!iRight && 0 !== iRight) {
14930 this.padding = [iTop, iTop, iTop, iTop];
14931 } else if (!iBot && 0 !== iBot) {
14932 this.padding = [iTop, iRight, iTop, iRight];
14934 this.padding = [iTop, iRight, iBot, iLeft];
14939 * Stores the initial placement of the linked element.
14940 * @method setInitialPosition
14941 * @param {int} diffX the X offset, default 0
14942 * @param {int} diffY the Y offset, default 0
14944 setInitPosition: function(diffX, diffY) {
14945 var el = this.getEl();
14947 if (!this.DDM.verifyEl(el)) {
14951 var dx = diffX || 0;
14952 var dy = diffY || 0;
14954 var p = Dom.getXY( el );
14956 this.initPageX = p[0] - dx;
14957 this.initPageY = p[1] - dy;
14959 this.lastPageX = p[0];
14960 this.lastPageY = p[1];
14963 this.setStartPosition(p);
14967 * Sets the start position of the element. This is set when the obj
14968 * is initialized, the reset when a drag is started.
14969 * @method setStartPosition
14970 * @param pos current position (from previous lookup)
14973 setStartPosition: function(pos) {
14974 var p = pos || Dom.getXY( this.getEl() );
14975 this.deltaSetXY = null;
14977 this.startPageX = p[0];
14978 this.startPageY = p[1];
14982 * Add this instance to a group of related drag/drop objects. All
14983 * instances belong to at least one group, and can belong to as many
14984 * groups as needed.
14985 * @method addToGroup
14986 * @param sGroup {string} the name of the group
14988 addToGroup: function(sGroup) {
14989 this.groups[sGroup] = true;
14990 this.DDM.regDragDrop(this, sGroup);
14994 * Remove's this instance from the supplied interaction group
14995 * @method removeFromGroup
14996 * @param {string} sGroup The group to drop
14998 removeFromGroup: function(sGroup) {
14999 if (this.groups[sGroup]) {
15000 delete this.groups[sGroup];
15003 this.DDM.removeDDFromGroup(this, sGroup);
15007 * Allows you to specify that an element other than the linked element
15008 * will be moved with the cursor during a drag
15009 * @method setDragElId
15010 * @param id {string} the id of the element that will be used to initiate the drag
15012 setDragElId: function(id) {
15013 this.dragElId = id;
15017 * Allows you to specify a child of the linked element that should be
15018 * used to initiate the drag operation. An example of this would be if
15019 * you have a content div with text and links. Clicking anywhere in the
15020 * content area would normally start the drag operation. Use this method
15021 * to specify that an element inside of the content div is the element
15022 * that starts the drag operation.
15023 * @method setHandleElId
15024 * @param id {string} the id of the element that will be used to
15025 * initiate the drag.
15027 setHandleElId: function(id) {
15028 if (typeof id !== "string") {
15031 this.handleElId = id;
15032 this.DDM.regHandle(this.id, id);
15036 * Allows you to set an element outside of the linked element as a drag
15038 * @method setOuterHandleElId
15039 * @param id the id of the element that will be used to initiate the drag
15041 setOuterHandleElId: function(id) {
15042 if (typeof id !== "string") {
15045 Event.on(id, "mousedown",
15046 this.handleMouseDown, this);
15047 this.setHandleElId(id);
15049 this.hasOuterHandles = true;
15053 * Remove all drag and drop hooks for this element
15056 unreg: function() {
15057 Event.un(this.id, "mousedown",
15058 this.handleMouseDown);
15059 this._domRef = null;
15060 this.DDM._remove(this);
15063 destroy : function(){
15068 * Returns true if this instance is locked, or the drag drop mgr is locked
15069 * (meaning that all drag/drop is disabled on the page.)
15071 * @return {boolean} true if this obj or all drag/drop is locked, else
15074 isLocked: function() {
15075 return (this.DDM.isLocked() || this.locked);
15079 * Fired when this object is clicked
15080 * @method handleMouseDown
15082 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
15085 handleMouseDown: function(e, oDD){
15086 if (this.primaryButtonOnly && e.button != 0) {
15090 if (this.isLocked()) {
15094 this.DDM.refreshCache(this.groups);
15096 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
15097 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
15099 if (this.clickValidator(e)) {
15101 // set the initial element position
15102 this.setStartPosition();
15105 this.b4MouseDown(e);
15106 this.onMouseDown(e);
15108 this.DDM.handleMouseDown(e, this);
15110 this.DDM.stopEvent(e);
15118 clickValidator: function(e) {
15119 var target = e.getTarget();
15120 return ( this.isValidHandleChild(target) &&
15121 (this.id == this.handleElId ||
15122 this.DDM.handleWasClicked(target, this.id)) );
15126 * Allows you to specify a tag name that should not start a drag operation
15127 * when clicked. This is designed to facilitate embedding links within a
15128 * drag handle that do something other than start the drag.
15129 * @method addInvalidHandleType
15130 * @param {string} tagName the type of element to exclude
15132 addInvalidHandleType: function(tagName) {
15133 var type = tagName.toUpperCase();
15134 this.invalidHandleTypes[type] = type;
15138 * Lets you to specify an element id for a child of a drag handle
15139 * that should not initiate a drag
15140 * @method addInvalidHandleId
15141 * @param {string} id the element id of the element you wish to ignore
15143 addInvalidHandleId: function(id) {
15144 if (typeof id !== "string") {
15147 this.invalidHandleIds[id] = id;
15151 * Lets you specify a css class of elements that will not initiate a drag
15152 * @method addInvalidHandleClass
15153 * @param {string} cssClass the class of the elements you wish to ignore
15155 addInvalidHandleClass: function(cssClass) {
15156 this.invalidHandleClasses.push(cssClass);
15160 * Unsets an excluded tag name set by addInvalidHandleType
15161 * @method removeInvalidHandleType
15162 * @param {string} tagName the type of element to unexclude
15164 removeInvalidHandleType: function(tagName) {
15165 var type = tagName.toUpperCase();
15166 // this.invalidHandleTypes[type] = null;
15167 delete this.invalidHandleTypes[type];
15171 * Unsets an invalid handle id
15172 * @method removeInvalidHandleId
15173 * @param {string} id the id of the element to re-enable
15175 removeInvalidHandleId: function(id) {
15176 if (typeof id !== "string") {
15179 delete this.invalidHandleIds[id];
15183 * Unsets an invalid css class
15184 * @method removeInvalidHandleClass
15185 * @param {string} cssClass the class of the element(s) you wish to
15188 removeInvalidHandleClass: function(cssClass) {
15189 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
15190 if (this.invalidHandleClasses[i] == cssClass) {
15191 delete this.invalidHandleClasses[i];
15197 * Checks the tag exclusion list to see if this click should be ignored
15198 * @method isValidHandleChild
15199 * @param {HTMLElement} node the HTMLElement to evaluate
15200 * @return {boolean} true if this is a valid tag type, false if not
15202 isValidHandleChild: function(node) {
15205 // var n = (node.nodeName == "#text") ? node.parentNode : node;
15208 nodeName = node.nodeName.toUpperCase();
15210 nodeName = node.nodeName;
15212 valid = valid && !this.invalidHandleTypes[nodeName];
15213 valid = valid && !this.invalidHandleIds[node.id];
15215 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
15216 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
15225 * Create the array of horizontal tick marks if an interval was specified
15226 * in setXConstraint().
15227 * @method setXTicks
15230 setXTicks: function(iStartX, iTickSize) {
15232 this.xTickSize = iTickSize;
15236 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
15238 this.xTicks[this.xTicks.length] = i;
15243 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
15245 this.xTicks[this.xTicks.length] = i;
15250 this.xTicks.sort(this.DDM.numericSort) ;
15254 * Create the array of vertical tick marks if an interval was specified in
15255 * setYConstraint().
15256 * @method setYTicks
15259 setYTicks: function(iStartY, iTickSize) {
15261 this.yTickSize = iTickSize;
15265 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
15267 this.yTicks[this.yTicks.length] = i;
15272 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
15274 this.yTicks[this.yTicks.length] = i;
15279 this.yTicks.sort(this.DDM.numericSort) ;
15283 * By default, the element can be dragged any place on the screen. Use
15284 * this method to limit the horizontal travel of the element. Pass in
15285 * 0,0 for the parameters if you want to lock the drag to the y axis.
15286 * @method setXConstraint
15287 * @param {int} iLeft the number of pixels the element can move to the left
15288 * @param {int} iRight the number of pixels the element can move to the
15290 * @param {int} iTickSize optional parameter for specifying that the
15292 * should move iTickSize pixels at a time.
15294 setXConstraint: function(iLeft, iRight, iTickSize) {
15295 this.leftConstraint = iLeft;
15296 this.rightConstraint = iRight;
15298 this.minX = this.initPageX - iLeft;
15299 this.maxX = this.initPageX + iRight;
15300 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
15302 this.constrainX = true;
15306 * Clears any constraints applied to this instance. Also clears ticks
15307 * since they can't exist independent of a constraint at this time.
15308 * @method clearConstraints
15310 clearConstraints: function() {
15311 this.constrainX = false;
15312 this.constrainY = false;
15317 * Clears any tick interval defined for this instance
15318 * @method clearTicks
15320 clearTicks: function() {
15321 this.xTicks = null;
15322 this.yTicks = null;
15323 this.xTickSize = 0;
15324 this.yTickSize = 0;
15328 * By default, the element can be dragged any place on the screen. Set
15329 * this to limit the vertical travel of the element. Pass in 0,0 for the
15330 * parameters if you want to lock the drag to the x axis.
15331 * @method setYConstraint
15332 * @param {int} iUp the number of pixels the element can move up
15333 * @param {int} iDown the number of pixels the element can move down
15334 * @param {int} iTickSize optional parameter for specifying that the
15335 * element should move iTickSize pixels at a time.
15337 setYConstraint: function(iUp, iDown, iTickSize) {
15338 this.topConstraint = iUp;
15339 this.bottomConstraint = iDown;
15341 this.minY = this.initPageY - iUp;
15342 this.maxY = this.initPageY + iDown;
15343 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
15345 this.constrainY = true;
15350 * resetConstraints must be called if you manually reposition a dd element.
15351 * @method resetConstraints
15352 * @param {boolean} maintainOffset
15354 resetConstraints: function() {
15357 // Maintain offsets if necessary
15358 if (this.initPageX || this.initPageX === 0) {
15359 // figure out how much this thing has moved
15360 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
15361 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
15363 this.setInitPosition(dx, dy);
15365 // This is the first time we have detected the element's position
15367 this.setInitPosition();
15370 if (this.constrainX) {
15371 this.setXConstraint( this.leftConstraint,
15372 this.rightConstraint,
15376 if (this.constrainY) {
15377 this.setYConstraint( this.topConstraint,
15378 this.bottomConstraint,
15384 * Normally the drag element is moved pixel by pixel, but we can specify
15385 * that it move a number of pixels at a time. This method resolves the
15386 * location when we have it set up like this.
15388 * @param {int} val where we want to place the object
15389 * @param {int[]} tickArray sorted array of valid points
15390 * @return {int} the closest tick
15393 getTick: function(val, tickArray) {
15396 // If tick interval is not defined, it is effectively 1 pixel,
15397 // so we return the value passed to us.
15399 } else if (tickArray[0] >= val) {
15400 // The value is lower than the first tick, so we return the first
15402 return tickArray[0];
15404 for (var i=0, len=tickArray.length; i<len; ++i) {
15406 if (tickArray[next] && tickArray[next] >= val) {
15407 var diff1 = val - tickArray[i];
15408 var diff2 = tickArray[next] - val;
15409 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
15413 // The value is larger than the last tick, so we return the last
15415 return tickArray[tickArray.length - 1];
15422 * @return {string} string representation of the dd obj
15424 toString: function() {
15425 return ("DragDrop " + this.id);
15433 * Ext JS Library 1.1.1
15434 * Copyright(c) 2006-2007, Ext JS, LLC.
15436 * Originally Released Under LGPL - original licence link has changed is not relivant.
15439 * <script type="text/javascript">
15444 * The drag and drop utility provides a framework for building drag and drop
15445 * applications. In addition to enabling drag and drop for specific elements,
15446 * the drag and drop elements are tracked by the manager class, and the
15447 * interactions between the various elements are tracked during the drag and
15448 * the implementing code is notified about these important moments.
15451 // Only load the library once. Rewriting the manager class would orphan
15452 // existing drag and drop instances.
15453 if (!Roo.dd.DragDropMgr) {
15456 * @class Roo.dd.DragDropMgr
15457 * DragDropMgr is a singleton that tracks the element interaction for
15458 * all DragDrop items in the window. Generally, you will not call
15459 * this class directly, but it does have helper methods that could
15460 * be useful in your DragDrop implementations.
15463 Roo.dd.DragDropMgr = function() {
15465 var Event = Roo.EventManager;
15470 * Two dimensional Array of registered DragDrop objects. The first
15471 * dimension is the DragDrop item group, the second the DragDrop
15474 * @type {string: string}
15481 * Array of element ids defined as drag handles. Used to determine
15482 * if the element that generated the mousedown event is actually the
15483 * handle and not the html element itself.
15484 * @property handleIds
15485 * @type {string: string}
15492 * the DragDrop object that is currently being dragged
15493 * @property dragCurrent
15501 * the DragDrop object(s) that are being hovered over
15502 * @property dragOvers
15510 * the X distance between the cursor and the object being dragged
15519 * the Y distance between the cursor and the object being dragged
15528 * Flag to determine if we should prevent the default behavior of the
15529 * events we define. By default this is true, but this can be set to
15530 * false if you need the default behavior (not recommended)
15531 * @property preventDefault
15535 preventDefault: true,
15538 * Flag to determine if we should stop the propagation of the events
15539 * we generate. This is true by default but you may want to set it to
15540 * false if the html element contains other features that require the
15542 * @property stopPropagation
15546 stopPropagation: true,
15549 * Internal flag that is set to true when drag and drop has been
15551 * @property initialized
15558 * All drag and drop can be disabled.
15566 * Called the first time an element is registered.
15572 this.initialized = true;
15576 * In point mode, drag and drop interaction is defined by the
15577 * location of the cursor during the drag/drop
15585 * In intersect mode, drag and drop interactio nis defined by the
15586 * overlap of two or more drag and drop objects.
15587 * @property INTERSECT
15594 * The current drag and drop mode. Default: POINT
15602 * Runs method on all drag and drop objects
15603 * @method _execOnAll
15607 _execOnAll: function(sMethod, args) {
15608 for (var i in this.ids) {
15609 for (var j in this.ids[i]) {
15610 var oDD = this.ids[i][j];
15611 if (! this.isTypeOfDD(oDD)) {
15614 oDD[sMethod].apply(oDD, args);
15620 * Drag and drop initialization. Sets up the global event handlers
15625 _onLoad: function() {
15630 Event.on(document, "mouseup", this.handleMouseUp, this, true);
15631 Event.on(document, "mousemove", this.handleMouseMove, this, true);
15632 Event.on(window, "unload", this._onUnload, this, true);
15633 Event.on(window, "resize", this._onResize, this, true);
15634 // Event.on(window, "mouseout", this._test);
15639 * Reset constraints on all drag and drop objs
15640 * @method _onResize
15644 _onResize: function(e) {
15645 this._execOnAll("resetConstraints", []);
15649 * Lock all drag and drop functionality
15653 lock: function() { this.locked = true; },
15656 * Unlock all drag and drop functionality
15660 unlock: function() { this.locked = false; },
15663 * Is drag and drop locked?
15665 * @return {boolean} True if drag and drop is locked, false otherwise.
15668 isLocked: function() { return this.locked; },
15671 * Location cache that is set for all drag drop objects when a drag is
15672 * initiated, cleared when the drag is finished.
15673 * @property locationCache
15680 * Set useCache to false if you want to force object the lookup of each
15681 * drag and drop linked element constantly during a drag.
15682 * @property useCache
15689 * The number of pixels that the mouse needs to move after the
15690 * mousedown before the drag is initiated. Default=3;
15691 * @property clickPixelThresh
15695 clickPixelThresh: 3,
15698 * The number of milliseconds after the mousedown event to initiate the
15699 * drag if we don't get a mouseup event. Default=1000
15700 * @property clickTimeThresh
15704 clickTimeThresh: 350,
15707 * Flag that indicates that either the drag pixel threshold or the
15708 * mousdown time threshold has been met
15709 * @property dragThreshMet
15714 dragThreshMet: false,
15717 * Timeout used for the click time threshold
15718 * @property clickTimeout
15723 clickTimeout: null,
15726 * The X position of the mousedown event stored for later use when a
15727 * drag threshold is met.
15736 * The Y position of the mousedown event stored for later use when a
15737 * drag threshold is met.
15746 * Each DragDrop instance must be registered with the DragDropMgr.
15747 * This is executed in DragDrop.init()
15748 * @method regDragDrop
15749 * @param {DragDrop} oDD the DragDrop object to register
15750 * @param {String} sGroup the name of the group this element belongs to
15753 regDragDrop: function(oDD, sGroup) {
15754 if (!this.initialized) { this.init(); }
15756 if (!this.ids[sGroup]) {
15757 this.ids[sGroup] = {};
15759 this.ids[sGroup][oDD.id] = oDD;
15763 * Removes the supplied dd instance from the supplied group. Executed
15764 * by DragDrop.removeFromGroup, so don't call this function directly.
15765 * @method removeDDFromGroup
15769 removeDDFromGroup: function(oDD, sGroup) {
15770 if (!this.ids[sGroup]) {
15771 this.ids[sGroup] = {};
15774 var obj = this.ids[sGroup];
15775 if (obj && obj[oDD.id]) {
15776 delete obj[oDD.id];
15781 * Unregisters a drag and drop item. This is executed in
15782 * DragDrop.unreg, use that method instead of calling this directly.
15787 _remove: function(oDD) {
15788 for (var g in oDD.groups) {
15789 if (g && this.ids[g][oDD.id]) {
15790 delete this.ids[g][oDD.id];
15793 delete this.handleIds[oDD.id];
15797 * Each DragDrop handle element must be registered. This is done
15798 * automatically when executing DragDrop.setHandleElId()
15799 * @method regHandle
15800 * @param {String} sDDId the DragDrop id this element is a handle for
15801 * @param {String} sHandleId the id of the element that is the drag
15805 regHandle: function(sDDId, sHandleId) {
15806 if (!this.handleIds[sDDId]) {
15807 this.handleIds[sDDId] = {};
15809 this.handleIds[sDDId][sHandleId] = sHandleId;
15813 * Utility function to determine if a given element has been
15814 * registered as a drag drop item.
15815 * @method isDragDrop
15816 * @param {String} id the element id to check
15817 * @return {boolean} true if this element is a DragDrop item,
15821 isDragDrop: function(id) {
15822 return ( this.getDDById(id) ) ? true : false;
15826 * Returns the drag and drop instances that are in all groups the
15827 * passed in instance belongs to.
15828 * @method getRelated
15829 * @param {DragDrop} p_oDD the obj to get related data for
15830 * @param {boolean} bTargetsOnly if true, only return targetable objs
15831 * @return {DragDrop[]} the related instances
15834 getRelated: function(p_oDD, bTargetsOnly) {
15836 for (var i in p_oDD.groups) {
15837 for (j in this.ids[i]) {
15838 var dd = this.ids[i][j];
15839 if (! this.isTypeOfDD(dd)) {
15842 if (!bTargetsOnly || dd.isTarget) {
15843 oDDs[oDDs.length] = dd;
15852 * Returns true if the specified dd target is a legal target for
15853 * the specifice drag obj
15854 * @method isLegalTarget
15855 * @param {DragDrop} the drag obj
15856 * @param {DragDrop} the target
15857 * @return {boolean} true if the target is a legal target for the
15861 isLegalTarget: function (oDD, oTargetDD) {
15862 var targets = this.getRelated(oDD, true);
15863 for (var i=0, len=targets.length;i<len;++i) {
15864 if (targets[i].id == oTargetDD.id) {
15873 * My goal is to be able to transparently determine if an object is
15874 * typeof DragDrop, and the exact subclass of DragDrop. typeof
15875 * returns "object", oDD.constructor.toString() always returns
15876 * "DragDrop" and not the name of the subclass. So for now it just
15877 * evaluates a well-known variable in DragDrop.
15878 * @method isTypeOfDD
15879 * @param {Object} the object to evaluate
15880 * @return {boolean} true if typeof oDD = DragDrop
15883 isTypeOfDD: function (oDD) {
15884 return (oDD && oDD.__ygDragDrop);
15888 * Utility function to determine if a given element has been
15889 * registered as a drag drop handle for the given Drag Drop object.
15891 * @param {String} id the element id to check
15892 * @return {boolean} true if this element is a DragDrop handle, false
15896 isHandle: function(sDDId, sHandleId) {
15897 return ( this.handleIds[sDDId] &&
15898 this.handleIds[sDDId][sHandleId] );
15902 * Returns the DragDrop instance for a given id
15903 * @method getDDById
15904 * @param {String} id the id of the DragDrop object
15905 * @return {DragDrop} the drag drop object, null if it is not found
15908 getDDById: function(id) {
15909 for (var i in this.ids) {
15910 if (this.ids[i][id]) {
15911 return this.ids[i][id];
15918 * Fired after a registered DragDrop object gets the mousedown event.
15919 * Sets up the events required to track the object being dragged
15920 * @method handleMouseDown
15921 * @param {Event} e the event
15922 * @param oDD the DragDrop object being dragged
15926 handleMouseDown: function(e, oDD) {
15928 Roo.QuickTips.disable();
15930 this.currentTarget = e.getTarget();
15932 this.dragCurrent = oDD;
15934 var el = oDD.getEl();
15936 // track start position
15937 this.startX = e.getPageX();
15938 this.startY = e.getPageY();
15940 this.deltaX = this.startX - el.offsetLeft;
15941 this.deltaY = this.startY - el.offsetTop;
15943 this.dragThreshMet = false;
15945 this.clickTimeout = setTimeout(
15947 var DDM = Roo.dd.DDM;
15948 DDM.startDrag(DDM.startX, DDM.startY);
15950 this.clickTimeThresh );
15954 * Fired when either the drag pixel threshol or the mousedown hold
15955 * time threshold has been met.
15956 * @method startDrag
15957 * @param x {int} the X position of the original mousedown
15958 * @param y {int} the Y position of the original mousedown
15961 startDrag: function(x, y) {
15962 clearTimeout(this.clickTimeout);
15963 if (this.dragCurrent) {
15964 this.dragCurrent.b4StartDrag(x, y);
15965 this.dragCurrent.startDrag(x, y);
15967 this.dragThreshMet = true;
15971 * Internal function to handle the mouseup event. Will be invoked
15972 * from the context of the document.
15973 * @method handleMouseUp
15974 * @param {Event} e the event
15978 handleMouseUp: function(e) {
15981 Roo.QuickTips.enable();
15983 if (! this.dragCurrent) {
15987 clearTimeout(this.clickTimeout);
15989 if (this.dragThreshMet) {
15990 this.fireEvents(e, true);
16000 * Utility to stop event propagation and event default, if these
16001 * features are turned on.
16002 * @method stopEvent
16003 * @param {Event} e the event as returned by this.getEvent()
16006 stopEvent: function(e){
16007 if(this.stopPropagation) {
16008 e.stopPropagation();
16011 if (this.preventDefault) {
16012 e.preventDefault();
16017 * Internal function to clean up event handlers after the drag
16018 * operation is complete
16020 * @param {Event} e the event
16024 stopDrag: function(e) {
16025 // Fire the drag end event for the item that was dragged
16026 if (this.dragCurrent) {
16027 if (this.dragThreshMet) {
16028 this.dragCurrent.b4EndDrag(e);
16029 this.dragCurrent.endDrag(e);
16032 this.dragCurrent.onMouseUp(e);
16035 this.dragCurrent = null;
16036 this.dragOvers = {};
16040 * Internal function to handle the mousemove event. Will be invoked
16041 * from the context of the html element.
16043 * @TODO figure out what we can do about mouse events lost when the
16044 * user drags objects beyond the window boundary. Currently we can
16045 * detect this in internet explorer by verifying that the mouse is
16046 * down during the mousemove event. Firefox doesn't give us the
16047 * button state on the mousemove event.
16048 * @method handleMouseMove
16049 * @param {Event} e the event
16053 handleMouseMove: function(e) {
16054 if (! this.dragCurrent) {
16058 // var button = e.which || e.button;
16060 // check for IE mouseup outside of page boundary
16061 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
16063 return this.handleMouseUp(e);
16066 if (!this.dragThreshMet) {
16067 var diffX = Math.abs(this.startX - e.getPageX());
16068 var diffY = Math.abs(this.startY - e.getPageY());
16069 if (diffX > this.clickPixelThresh ||
16070 diffY > this.clickPixelThresh) {
16071 this.startDrag(this.startX, this.startY);
16075 if (this.dragThreshMet) {
16076 this.dragCurrent.b4Drag(e);
16077 this.dragCurrent.onDrag(e);
16078 if(!this.dragCurrent.moveOnly){
16079 this.fireEvents(e, false);
16089 * Iterates over all of the DragDrop elements to find ones we are
16090 * hovering over or dropping on
16091 * @method fireEvents
16092 * @param {Event} e the event
16093 * @param {boolean} isDrop is this a drop op or a mouseover op?
16097 fireEvents: function(e, isDrop) {
16098 var dc = this.dragCurrent;
16100 // If the user did the mouse up outside of the window, we could
16101 // get here even though we have ended the drag.
16102 if (!dc || dc.isLocked()) {
16106 var pt = e.getPoint();
16108 // cache the previous dragOver array
16114 var enterEvts = [];
16116 // Check to see if the object(s) we were hovering over is no longer
16117 // being hovered over so we can fire the onDragOut event
16118 for (var i in this.dragOvers) {
16120 var ddo = this.dragOvers[i];
16122 if (! this.isTypeOfDD(ddo)) {
16126 if (! this.isOverTarget(pt, ddo, this.mode)) {
16127 outEvts.push( ddo );
16130 oldOvers[i] = true;
16131 delete this.dragOvers[i];
16134 for (var sGroup in dc.groups) {
16136 if ("string" != typeof sGroup) {
16140 for (i in this.ids[sGroup]) {
16141 var oDD = this.ids[sGroup][i];
16142 if (! this.isTypeOfDD(oDD)) {
16146 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
16147 if (this.isOverTarget(pt, oDD, this.mode)) {
16148 // look for drop interactions
16150 dropEvts.push( oDD );
16151 // look for drag enter and drag over interactions
16154 // initial drag over: dragEnter fires
16155 if (!oldOvers[oDD.id]) {
16156 enterEvts.push( oDD );
16157 // subsequent drag overs: dragOver fires
16159 overEvts.push( oDD );
16162 this.dragOvers[oDD.id] = oDD;
16170 if (outEvts.length) {
16171 dc.b4DragOut(e, outEvts);
16172 dc.onDragOut(e, outEvts);
16175 if (enterEvts.length) {
16176 dc.onDragEnter(e, enterEvts);
16179 if (overEvts.length) {
16180 dc.b4DragOver(e, overEvts);
16181 dc.onDragOver(e, overEvts);
16184 if (dropEvts.length) {
16185 dc.b4DragDrop(e, dropEvts);
16186 dc.onDragDrop(e, dropEvts);
16190 // fire dragout events
16192 for (i=0, len=outEvts.length; i<len; ++i) {
16193 dc.b4DragOut(e, outEvts[i].id);
16194 dc.onDragOut(e, outEvts[i].id);
16197 // fire enter events
16198 for (i=0,len=enterEvts.length; i<len; ++i) {
16199 // dc.b4DragEnter(e, oDD.id);
16200 dc.onDragEnter(e, enterEvts[i].id);
16203 // fire over events
16204 for (i=0,len=overEvts.length; i<len; ++i) {
16205 dc.b4DragOver(e, overEvts[i].id);
16206 dc.onDragOver(e, overEvts[i].id);
16209 // fire drop events
16210 for (i=0, len=dropEvts.length; i<len; ++i) {
16211 dc.b4DragDrop(e, dropEvts[i].id);
16212 dc.onDragDrop(e, dropEvts[i].id);
16217 // notify about a drop that did not find a target
16218 if (isDrop && !dropEvts.length) {
16219 dc.onInvalidDrop(e);
16225 * Helper function for getting the best match from the list of drag
16226 * and drop objects returned by the drag and drop events when we are
16227 * in INTERSECT mode. It returns either the first object that the
16228 * cursor is over, or the object that has the greatest overlap with
16229 * the dragged element.
16230 * @method getBestMatch
16231 * @param {DragDrop[]} dds The array of drag and drop objects
16233 * @return {DragDrop} The best single match
16236 getBestMatch: function(dds) {
16238 // Return null if the input is not what we expect
16239 //if (!dds || !dds.length || dds.length == 0) {
16241 // If there is only one item, it wins
16242 //} else if (dds.length == 1) {
16244 var len = dds.length;
16249 // Loop through the targeted items
16250 for (var i=0; i<len; ++i) {
16252 // If the cursor is over the object, it wins. If the
16253 // cursor is over multiple matches, the first one we come
16255 if (dd.cursorIsOver) {
16258 // Otherwise the object with the most overlap wins
16261 winner.overlap.getArea() < dd.overlap.getArea()) {
16272 * Refreshes the cache of the top-left and bottom-right points of the
16273 * drag and drop objects in the specified group(s). This is in the
16274 * format that is stored in the drag and drop instance, so typical
16277 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
16281 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
16283 * @TODO this really should be an indexed array. Alternatively this
16284 * method could accept both.
16285 * @method refreshCache
16286 * @param {Object} groups an associative array of groups to refresh
16289 refreshCache: function(groups) {
16290 for (var sGroup in groups) {
16291 if ("string" != typeof sGroup) {
16294 for (var i in this.ids[sGroup]) {
16295 var oDD = this.ids[sGroup][i];
16297 if (this.isTypeOfDD(oDD)) {
16298 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
16299 var loc = this.getLocation(oDD);
16301 this.locationCache[oDD.id] = loc;
16303 delete this.locationCache[oDD.id];
16304 // this will unregister the drag and drop object if
16305 // the element is not in a usable state
16314 * This checks to make sure an element exists and is in the DOM. The
16315 * main purpose is to handle cases where innerHTML is used to remove
16316 * drag and drop objects from the DOM. IE provides an 'unspecified
16317 * error' when trying to access the offsetParent of such an element
16319 * @param {HTMLElement} el the element to check
16320 * @return {boolean} true if the element looks usable
16323 verifyEl: function(el) {
16328 parent = el.offsetParent;
16331 parent = el.offsetParent;
16342 * Returns a Region object containing the drag and drop element's position
16343 * and size, including the padding configured for it
16344 * @method getLocation
16345 * @param {DragDrop} oDD the drag and drop object to get the
16347 * @return {Roo.lib.Region} a Region object representing the total area
16348 * the element occupies, including any padding
16349 * the instance is configured for.
16352 getLocation: function(oDD) {
16353 if (! this.isTypeOfDD(oDD)) {
16357 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
16360 pos= Roo.lib.Dom.getXY(el);
16368 x2 = x1 + el.offsetWidth;
16370 y2 = y1 + el.offsetHeight;
16372 t = y1 - oDD.padding[0];
16373 r = x2 + oDD.padding[1];
16374 b = y2 + oDD.padding[2];
16375 l = x1 - oDD.padding[3];
16377 return new Roo.lib.Region( t, r, b, l );
16381 * Checks the cursor location to see if it over the target
16382 * @method isOverTarget
16383 * @param {Roo.lib.Point} pt The point to evaluate
16384 * @param {DragDrop} oTarget the DragDrop object we are inspecting
16385 * @return {boolean} true if the mouse is over the target
16389 isOverTarget: function(pt, oTarget, intersect) {
16390 // use cache if available
16391 var loc = this.locationCache[oTarget.id];
16392 if (!loc || !this.useCache) {
16393 loc = this.getLocation(oTarget);
16394 this.locationCache[oTarget.id] = loc;
16402 oTarget.cursorIsOver = loc.contains( pt );
16404 // DragDrop is using this as a sanity check for the initial mousedown
16405 // in this case we are done. In POINT mode, if the drag obj has no
16406 // contraints, we are also done. Otherwise we need to evaluate the
16407 // location of the target as related to the actual location of the
16408 // dragged element.
16409 var dc = this.dragCurrent;
16410 if (!dc || !dc.getTargetCoord ||
16411 (!intersect && !dc.constrainX && !dc.constrainY)) {
16412 return oTarget.cursorIsOver;
16415 oTarget.overlap = null;
16417 // Get the current location of the drag element, this is the
16418 // location of the mouse event less the delta that represents
16419 // where the original mousedown happened on the element. We
16420 // need to consider constraints and ticks as well.
16421 var pos = dc.getTargetCoord(pt.x, pt.y);
16423 var el = dc.getDragEl();
16424 var curRegion = new Roo.lib.Region( pos.y,
16425 pos.x + el.offsetWidth,
16426 pos.y + el.offsetHeight,
16429 var overlap = curRegion.intersect(loc);
16432 oTarget.overlap = overlap;
16433 return (intersect) ? true : oTarget.cursorIsOver;
16440 * unload event handler
16441 * @method _onUnload
16445 _onUnload: function(e, me) {
16446 Roo.dd.DragDropMgr.unregAll();
16450 * Cleans up the drag and drop events and objects.
16455 unregAll: function() {
16457 if (this.dragCurrent) {
16459 this.dragCurrent = null;
16462 this._execOnAll("unreg", []);
16464 for (i in this.elementCache) {
16465 delete this.elementCache[i];
16468 this.elementCache = {};
16473 * A cache of DOM elements
16474 * @property elementCache
16481 * Get the wrapper for the DOM element specified
16482 * @method getElWrapper
16483 * @param {String} id the id of the element to get
16484 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
16486 * @deprecated This wrapper isn't that useful
16489 getElWrapper: function(id) {
16490 var oWrapper = this.elementCache[id];
16491 if (!oWrapper || !oWrapper.el) {
16492 oWrapper = this.elementCache[id] =
16493 new this.ElementWrapper(Roo.getDom(id));
16499 * Returns the actual DOM element
16500 * @method getElement
16501 * @param {String} id the id of the elment to get
16502 * @return {Object} The element
16503 * @deprecated use Roo.getDom instead
16506 getElement: function(id) {
16507 return Roo.getDom(id);
16511 * Returns the style property for the DOM element (i.e.,
16512 * document.getElById(id).style)
16514 * @param {String} id the id of the elment to get
16515 * @return {Object} The style property of the element
16516 * @deprecated use Roo.getDom instead
16519 getCss: function(id) {
16520 var el = Roo.getDom(id);
16521 return (el) ? el.style : null;
16525 * Inner class for cached elements
16526 * @class DragDropMgr.ElementWrapper
16531 ElementWrapper: function(el) {
16536 this.el = el || null;
16541 this.id = this.el && el.id;
16543 * A reference to the style property
16546 this.css = this.el && el.style;
16550 * Returns the X position of an html element
16552 * @param el the element for which to get the position
16553 * @return {int} the X coordinate
16555 * @deprecated use Roo.lib.Dom.getX instead
16558 getPosX: function(el) {
16559 return Roo.lib.Dom.getX(el);
16563 * Returns the Y position of an html element
16565 * @param el the element for which to get the position
16566 * @return {int} the Y coordinate
16567 * @deprecated use Roo.lib.Dom.getY instead
16570 getPosY: function(el) {
16571 return Roo.lib.Dom.getY(el);
16575 * Swap two nodes. In IE, we use the native method, for others we
16576 * emulate the IE behavior
16578 * @param n1 the first node to swap
16579 * @param n2 the other node to swap
16582 swapNode: function(n1, n2) {
16586 var p = n2.parentNode;
16587 var s = n2.nextSibling;
16590 p.insertBefore(n1, n2);
16591 } else if (n2 == n1.nextSibling) {
16592 p.insertBefore(n2, n1);
16594 n1.parentNode.replaceChild(n2, n1);
16595 p.insertBefore(n1, s);
16601 * Returns the current scroll position
16602 * @method getScroll
16606 getScroll: function () {
16607 var t, l, dde=document.documentElement, db=document.body;
16608 if (dde && (dde.scrollTop || dde.scrollLeft)) {
16610 l = dde.scrollLeft;
16617 return { top: t, left: l };
16621 * Returns the specified element style property
16623 * @param {HTMLElement} el the element
16624 * @param {string} styleProp the style property
16625 * @return {string} The value of the style property
16626 * @deprecated use Roo.lib.Dom.getStyle
16629 getStyle: function(el, styleProp) {
16630 return Roo.fly(el).getStyle(styleProp);
16634 * Gets the scrollTop
16635 * @method getScrollTop
16636 * @return {int} the document's scrollTop
16639 getScrollTop: function () { return this.getScroll().top; },
16642 * Gets the scrollLeft
16643 * @method getScrollLeft
16644 * @return {int} the document's scrollTop
16647 getScrollLeft: function () { return this.getScroll().left; },
16650 * Sets the x/y position of an element to the location of the
16653 * @param {HTMLElement} moveEl The element to move
16654 * @param {HTMLElement} targetEl The position reference element
16657 moveToEl: function (moveEl, targetEl) {
16658 var aCoord = Roo.lib.Dom.getXY(targetEl);
16659 Roo.lib.Dom.setXY(moveEl, aCoord);
16663 * Numeric array sort function
16664 * @method numericSort
16667 numericSort: function(a, b) { return (a - b); },
16671 * @property _timeoutCount
16678 * Trying to make the load order less important. Without this we get
16679 * an error if this file is loaded before the Event Utility.
16680 * @method _addListeners
16684 _addListeners: function() {
16685 var DDM = Roo.dd.DDM;
16686 if ( Roo.lib.Event && document ) {
16689 if (DDM._timeoutCount > 2000) {
16691 setTimeout(DDM._addListeners, 10);
16692 if (document && document.body) {
16693 DDM._timeoutCount += 1;
16700 * Recursively searches the immediate parent and all child nodes for
16701 * the handle element in order to determine wheter or not it was
16703 * @method handleWasClicked
16704 * @param node the html element to inspect
16707 handleWasClicked: function(node, id) {
16708 if (this.isHandle(id, node.id)) {
16711 // check to see if this is a text node child of the one we want
16712 var p = node.parentNode;
16715 if (this.isHandle(id, p.id)) {
16730 // shorter alias, save a few bytes
16731 Roo.dd.DDM = Roo.dd.DragDropMgr;
16732 Roo.dd.DDM._addListeners();
16736 * Ext JS Library 1.1.1
16737 * Copyright(c) 2006-2007, Ext JS, LLC.
16739 * Originally Released Under LGPL - original licence link has changed is not relivant.
16742 * <script type="text/javascript">
16747 * A DragDrop implementation where the linked element follows the
16748 * mouse cursor during a drag.
16749 * @extends Roo.dd.DragDrop
16751 * @param {String} id the id of the linked element
16752 * @param {String} sGroup the group of related DragDrop items
16753 * @param {object} config an object containing configurable attributes
16754 * Valid properties for DD:
16757 Roo.dd.DD = function(id, sGroup, config) {
16759 this.init(id, sGroup, config);
16763 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
16766 * When set to true, the utility automatically tries to scroll the browser
16767 * window wehn a drag and drop element is dragged near the viewport boundary.
16768 * Defaults to true.
16775 * Sets the pointer offset to the distance between the linked element's top
16776 * left corner and the location the element was clicked
16777 * @method autoOffset
16778 * @param {int} iPageX the X coordinate of the click
16779 * @param {int} iPageY the Y coordinate of the click
16781 autoOffset: function(iPageX, iPageY) {
16782 var x = iPageX - this.startPageX;
16783 var y = iPageY - this.startPageY;
16784 this.setDelta(x, y);
16788 * Sets the pointer offset. You can call this directly to force the
16789 * offset to be in a particular location (e.g., pass in 0,0 to set it
16790 * to the center of the object)
16792 * @param {int} iDeltaX the distance from the left
16793 * @param {int} iDeltaY the distance from the top
16795 setDelta: function(iDeltaX, iDeltaY) {
16796 this.deltaX = iDeltaX;
16797 this.deltaY = iDeltaY;
16801 * Sets the drag element to the location of the mousedown or click event,
16802 * maintaining the cursor location relative to the location on the element
16803 * that was clicked. Override this if you want to place the element in a
16804 * location other than where the cursor is.
16805 * @method setDragElPos
16806 * @param {int} iPageX the X coordinate of the mousedown or drag event
16807 * @param {int} iPageY the Y coordinate of the mousedown or drag event
16809 setDragElPos: function(iPageX, iPageY) {
16810 // the first time we do this, we are going to check to make sure
16811 // the element has css positioning
16813 var el = this.getDragEl();
16814 this.alignElWithMouse(el, iPageX, iPageY);
16818 * Sets the element to the location of the mousedown or click event,
16819 * maintaining the cursor location relative to the location on the element
16820 * that was clicked. Override this if you want to place the element in a
16821 * location other than where the cursor is.
16822 * @method alignElWithMouse
16823 * @param {HTMLElement} el the element to move
16824 * @param {int} iPageX the X coordinate of the mousedown or drag event
16825 * @param {int} iPageY the Y coordinate of the mousedown or drag event
16827 alignElWithMouse: function(el, iPageX, iPageY) {
16828 var oCoord = this.getTargetCoord(iPageX, iPageY);
16829 var fly = el.dom ? el : Roo.fly(el);
16830 if (!this.deltaSetXY) {
16831 var aCoord = [oCoord.x, oCoord.y];
16833 var newLeft = fly.getLeft(true);
16834 var newTop = fly.getTop(true);
16835 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
16837 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
16840 this.cachePosition(oCoord.x, oCoord.y);
16841 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
16846 * Saves the most recent position so that we can reset the constraints and
16847 * tick marks on-demand. We need to know this so that we can calculate the
16848 * number of pixels the element is offset from its original position.
16849 * @method cachePosition
16850 * @param iPageX the current x position (optional, this just makes it so we
16851 * don't have to look it up again)
16852 * @param iPageY the current y position (optional, this just makes it so we
16853 * don't have to look it up again)
16855 cachePosition: function(iPageX, iPageY) {
16857 this.lastPageX = iPageX;
16858 this.lastPageY = iPageY;
16860 var aCoord = Roo.lib.Dom.getXY(this.getEl());
16861 this.lastPageX = aCoord[0];
16862 this.lastPageY = aCoord[1];
16867 * Auto-scroll the window if the dragged object has been moved beyond the
16868 * visible window boundary.
16869 * @method autoScroll
16870 * @param {int} x the drag element's x position
16871 * @param {int} y the drag element's y position
16872 * @param {int} h the height of the drag element
16873 * @param {int} w the width of the drag element
16876 autoScroll: function(x, y, h, w) {
16879 // The client height
16880 var clientH = Roo.lib.Dom.getViewWidth();
16882 // The client width
16883 var clientW = Roo.lib.Dom.getViewHeight();
16885 // The amt scrolled down
16886 var st = this.DDM.getScrollTop();
16888 // The amt scrolled right
16889 var sl = this.DDM.getScrollLeft();
16891 // Location of the bottom of the element
16894 // Location of the right of the element
16897 // The distance from the cursor to the bottom of the visible area,
16898 // adjusted so that we don't scroll if the cursor is beyond the
16899 // element drag constraints
16900 var toBot = (clientH + st - y - this.deltaY);
16902 // The distance from the cursor to the right of the visible area
16903 var toRight = (clientW + sl - x - this.deltaX);
16906 // How close to the edge the cursor must be before we scroll
16907 // var thresh = (document.all) ? 100 : 40;
16910 // How many pixels to scroll per autoscroll op. This helps to reduce
16911 // clunky scrolling. IE is more sensitive about this ... it needs this
16912 // value to be higher.
16913 var scrAmt = (document.all) ? 80 : 30;
16915 // Scroll down if we are near the bottom of the visible page and the
16916 // obj extends below the crease
16917 if ( bot > clientH && toBot < thresh ) {
16918 window.scrollTo(sl, st + scrAmt);
16921 // Scroll up if the window is scrolled down and the top of the object
16922 // goes above the top border
16923 if ( y < st && st > 0 && y - st < thresh ) {
16924 window.scrollTo(sl, st - scrAmt);
16927 // Scroll right if the obj is beyond the right border and the cursor is
16928 // near the border.
16929 if ( right > clientW && toRight < thresh ) {
16930 window.scrollTo(sl + scrAmt, st);
16933 // Scroll left if the window has been scrolled to the right and the obj
16934 // extends past the left border
16935 if ( x < sl && sl > 0 && x - sl < thresh ) {
16936 window.scrollTo(sl - scrAmt, st);
16942 * Finds the location the element should be placed if we want to move
16943 * it to where the mouse location less the click offset would place us.
16944 * @method getTargetCoord
16945 * @param {int} iPageX the X coordinate of the click
16946 * @param {int} iPageY the Y coordinate of the click
16947 * @return an object that contains the coordinates (Object.x and Object.y)
16950 getTargetCoord: function(iPageX, iPageY) {
16953 var x = iPageX - this.deltaX;
16954 var y = iPageY - this.deltaY;
16956 if (this.constrainX) {
16957 if (x < this.minX) { x = this.minX; }
16958 if (x > this.maxX) { x = this.maxX; }
16961 if (this.constrainY) {
16962 if (y < this.minY) { y = this.minY; }
16963 if (y > this.maxY) { y = this.maxY; }
16966 x = this.getTick(x, this.xTicks);
16967 y = this.getTick(y, this.yTicks);
16974 * Sets up config options specific to this class. Overrides
16975 * Roo.dd.DragDrop, but all versions of this method through the
16976 * inheritance chain are called
16978 applyConfig: function() {
16979 Roo.dd.DD.superclass.applyConfig.call(this);
16980 this.scroll = (this.config.scroll !== false);
16984 * Event that fires prior to the onMouseDown event. Overrides
16987 b4MouseDown: function(e) {
16988 // this.resetConstraints();
16989 this.autoOffset(e.getPageX(),
16994 * Event that fires prior to the onDrag event. Overrides
16997 b4Drag: function(e) {
16998 this.setDragElPos(e.getPageX(),
17002 toString: function() {
17003 return ("DD " + this.id);
17006 //////////////////////////////////////////////////////////////////////////
17007 // Debugging ygDragDrop events that can be overridden
17008 //////////////////////////////////////////////////////////////////////////
17010 startDrag: function(x, y) {
17013 onDrag: function(e) {
17016 onDragEnter: function(e, id) {
17019 onDragOver: function(e, id) {
17022 onDragOut: function(e, id) {
17025 onDragDrop: function(e, id) {
17028 endDrag: function(e) {
17035 * Ext JS Library 1.1.1
17036 * Copyright(c) 2006-2007, Ext JS, LLC.
17038 * Originally Released Under LGPL - original licence link has changed is not relivant.
17041 * <script type="text/javascript">
17045 * @class Roo.dd.DDProxy
17046 * A DragDrop implementation that inserts an empty, bordered div into
17047 * the document that follows the cursor during drag operations. At the time of
17048 * the click, the frame div is resized to the dimensions of the linked html
17049 * element, and moved to the exact location of the linked element.
17051 * References to the "frame" element refer to the single proxy element that
17052 * was created to be dragged in place of all DDProxy elements on the
17055 * @extends Roo.dd.DD
17057 * @param {String} id the id of the linked html element
17058 * @param {String} sGroup the group of related DragDrop objects
17059 * @param {object} config an object containing configurable attributes
17060 * Valid properties for DDProxy in addition to those in DragDrop:
17061 * resizeFrame, centerFrame, dragElId
17063 Roo.dd.DDProxy = function(id, sGroup, config) {
17065 this.init(id, sGroup, config);
17071 * The default drag frame div id
17072 * @property Roo.dd.DDProxy.dragElId
17076 Roo.dd.DDProxy.dragElId = "ygddfdiv";
17078 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
17081 * By default we resize the drag frame to be the same size as the element
17082 * we want to drag (this is to get the frame effect). We can turn it off
17083 * if we want a different behavior.
17084 * @property resizeFrame
17090 * By default the frame is positioned exactly where the drag element is, so
17091 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
17092 * you do not have constraints on the obj is to have the drag frame centered
17093 * around the cursor. Set centerFrame to true for this effect.
17094 * @property centerFrame
17097 centerFrame: false,
17100 * Creates the proxy element if it does not yet exist
17101 * @method createFrame
17103 createFrame: function() {
17105 var body = document.body;
17107 if (!body || !body.firstChild) {
17108 setTimeout( function() { self.createFrame(); }, 50 );
17112 var div = this.getDragEl();
17115 div = document.createElement("div");
17116 div.id = this.dragElId;
17119 s.position = "absolute";
17120 s.visibility = "hidden";
17122 s.border = "2px solid #aaa";
17125 // appendChild can blow up IE if invoked prior to the window load event
17126 // while rendering a table. It is possible there are other scenarios
17127 // that would cause this to happen as well.
17128 body.insertBefore(div, body.firstChild);
17133 * Initialization for the drag frame element. Must be called in the
17134 * constructor of all subclasses
17135 * @method initFrame
17137 initFrame: function() {
17138 this.createFrame();
17141 applyConfig: function() {
17142 Roo.dd.DDProxy.superclass.applyConfig.call(this);
17144 this.resizeFrame = (this.config.resizeFrame !== false);
17145 this.centerFrame = (this.config.centerFrame);
17146 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
17150 * Resizes the drag frame to the dimensions of the clicked object, positions
17151 * it over the object, and finally displays it
17152 * @method showFrame
17153 * @param {int} iPageX X click position
17154 * @param {int} iPageY Y click position
17157 showFrame: function(iPageX, iPageY) {
17158 var el = this.getEl();
17159 var dragEl = this.getDragEl();
17160 var s = dragEl.style;
17162 this._resizeProxy();
17164 if (this.centerFrame) {
17165 this.setDelta( Math.round(parseInt(s.width, 10)/2),
17166 Math.round(parseInt(s.height, 10)/2) );
17169 this.setDragElPos(iPageX, iPageY);
17171 Roo.fly(dragEl).show();
17175 * The proxy is automatically resized to the dimensions of the linked
17176 * element when a drag is initiated, unless resizeFrame is set to false
17177 * @method _resizeProxy
17180 _resizeProxy: function() {
17181 if (this.resizeFrame) {
17182 var el = this.getEl();
17183 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
17187 // overrides Roo.dd.DragDrop
17188 b4MouseDown: function(e) {
17189 var x = e.getPageX();
17190 var y = e.getPageY();
17191 this.autoOffset(x, y);
17192 this.setDragElPos(x, y);
17195 // overrides Roo.dd.DragDrop
17196 b4StartDrag: function(x, y) {
17197 // show the drag frame
17198 this.showFrame(x, y);
17201 // overrides Roo.dd.DragDrop
17202 b4EndDrag: function(e) {
17203 Roo.fly(this.getDragEl()).hide();
17206 // overrides Roo.dd.DragDrop
17207 // By default we try to move the element to the last location of the frame.
17208 // This is so that the default behavior mirrors that of Roo.dd.DD.
17209 endDrag: function(e) {
17211 var lel = this.getEl();
17212 var del = this.getDragEl();
17214 // Show the drag frame briefly so we can get its position
17215 del.style.visibility = "";
17218 // Hide the linked element before the move to get around a Safari
17220 lel.style.visibility = "hidden";
17221 Roo.dd.DDM.moveToEl(lel, del);
17222 del.style.visibility = "hidden";
17223 lel.style.visibility = "";
17228 beforeMove : function(){
17232 afterDrag : function(){
17236 toString: function() {
17237 return ("DDProxy " + this.id);
17243 * Ext JS Library 1.1.1
17244 * Copyright(c) 2006-2007, Ext JS, LLC.
17246 * Originally Released Under LGPL - original licence link has changed is not relivant.
17249 * <script type="text/javascript">
17253 * @class Roo.dd.DDTarget
17254 * A DragDrop implementation that does not move, but can be a drop
17255 * target. You would get the same result by simply omitting implementation
17256 * for the event callbacks, but this way we reduce the processing cost of the
17257 * event listener and the callbacks.
17258 * @extends Roo.dd.DragDrop
17260 * @param {String} id the id of the element that is a drop target
17261 * @param {String} sGroup the group of related DragDrop objects
17262 * @param {object} config an object containing configurable attributes
17263 * Valid properties for DDTarget in addition to those in
17267 Roo.dd.DDTarget = function(id, sGroup, config) {
17269 this.initTarget(id, sGroup, config);
17273 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
17274 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
17275 toString: function() {
17276 return ("DDTarget " + this.id);
17281 * Ext JS Library 1.1.1
17282 * Copyright(c) 2006-2007, Ext JS, LLC.
17284 * Originally Released Under LGPL - original licence link has changed is not relivant.
17287 * <script type="text/javascript">
17292 * @class Roo.dd.ScrollManager
17293 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
17294 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
17297 Roo.dd.ScrollManager = function(){
17298 var ddm = Roo.dd.DragDropMgr;
17303 var onStop = function(e){
17308 var triggerRefresh = function(){
17309 if(ddm.dragCurrent){
17310 ddm.refreshCache(ddm.dragCurrent.groups);
17314 var doScroll = function(){
17315 if(ddm.dragCurrent){
17316 var dds = Roo.dd.ScrollManager;
17318 if(proc.el.scroll(proc.dir, dds.increment)){
17322 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
17327 var clearProc = function(){
17329 clearInterval(proc.id);
17336 var startProc = function(el, dir){
17340 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
17343 var onFire = function(e, isDrop){
17344 if(isDrop || !ddm.dragCurrent){ return; }
17345 var dds = Roo.dd.ScrollManager;
17346 if(!dragEl || dragEl != ddm.dragCurrent){
17347 dragEl = ddm.dragCurrent;
17348 // refresh regions on drag start
17349 dds.refreshCache();
17352 var xy = Roo.lib.Event.getXY(e);
17353 var pt = new Roo.lib.Point(xy[0], xy[1]);
17354 for(var id in els){
17355 var el = els[id], r = el._region;
17356 if(r && r.contains(pt) && el.isScrollable()){
17357 if(r.bottom - pt.y <= dds.thresh){
17359 startProc(el, "down");
17362 }else if(r.right - pt.x <= dds.thresh){
17364 startProc(el, "left");
17367 }else if(pt.y - r.top <= dds.thresh){
17369 startProc(el, "up");
17372 }else if(pt.x - r.left <= dds.thresh){
17374 startProc(el, "right");
17383 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
17384 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
17388 * Registers new overflow element(s) to auto scroll
17389 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
17391 register : function(el){
17392 if(el instanceof Array){
17393 for(var i = 0, len = el.length; i < len; i++) {
17394 this.register(el[i]);
17403 * Unregisters overflow element(s) so they are no longer scrolled
17404 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
17406 unregister : function(el){
17407 if(el instanceof Array){
17408 for(var i = 0, len = el.length; i < len; i++) {
17409 this.unregister(el[i]);
17418 * The number of pixels from the edge of a container the pointer needs to be to
17419 * trigger scrolling (defaults to 25)
17425 * The number of pixels to scroll in each scroll increment (defaults to 50)
17431 * The frequency of scrolls in milliseconds (defaults to 500)
17437 * True to animate the scroll (defaults to true)
17443 * The animation duration in seconds -
17444 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
17450 * Manually trigger a cache refresh.
17452 refreshCache : function(){
17453 for(var id in els){
17454 if(typeof els[id] == 'object'){ // for people extending the object prototype
17455 els[id]._region = els[id].getRegion();
17462 * Ext JS Library 1.1.1
17463 * Copyright(c) 2006-2007, Ext JS, LLC.
17465 * Originally Released Under LGPL - original licence link has changed is not relivant.
17468 * <script type="text/javascript">
17473 * @class Roo.dd.Registry
17474 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
17475 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
17478 Roo.dd.Registry = function(){
17481 var autoIdSeed = 0;
17483 var getId = function(el, autogen){
17484 if(typeof el == "string"){
17488 if(!id && autogen !== false){
17489 id = "roodd-" + (++autoIdSeed);
17497 * Register a drag drop element
17498 * @param {String|HTMLElement} element The id or DOM node to register
17499 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
17500 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
17501 * knows how to interpret, plus there are some specific properties known to the Registry that should be
17502 * populated in the data object (if applicable):
17504 Value Description<br />
17505 --------- ------------------------------------------<br />
17506 handles Array of DOM nodes that trigger dragging<br />
17507 for the element being registered<br />
17508 isHandle True if the element passed in triggers<br />
17509 dragging itself, else false
17512 register : function(el, data){
17514 if(typeof el == "string"){
17515 el = document.getElementById(el);
17518 elements[getId(el)] = data;
17519 if(data.isHandle !== false){
17520 handles[data.ddel.id] = data;
17523 var hs = data.handles;
17524 for(var i = 0, len = hs.length; i < len; i++){
17525 handles[getId(hs[i])] = data;
17531 * Unregister a drag drop element
17532 * @param {String|HTMLElement} element The id or DOM node to unregister
17534 unregister : function(el){
17535 var id = getId(el, false);
17536 var data = elements[id];
17538 delete elements[id];
17540 var hs = data.handles;
17541 for(var i = 0, len = hs.length; i < len; i++){
17542 delete handles[getId(hs[i], false)];
17549 * Returns the handle registered for a DOM Node by id
17550 * @param {String|HTMLElement} id The DOM node or id to look up
17551 * @return {Object} handle The custom handle data
17553 getHandle : function(id){
17554 if(typeof id != "string"){ // must be element?
17557 return handles[id];
17561 * Returns the handle that is registered for the DOM node that is the target of the event
17562 * @param {Event} e The event
17563 * @return {Object} handle The custom handle data
17565 getHandleFromEvent : function(e){
17566 var t = Roo.lib.Event.getTarget(e);
17567 return t ? handles[t.id] : null;
17571 * Returns a custom data object that is registered for a DOM node by id
17572 * @param {String|HTMLElement} id The DOM node or id to look up
17573 * @return {Object} data The custom data
17575 getTarget : function(id){
17576 if(typeof id != "string"){ // must be element?
17579 return elements[id];
17583 * Returns a custom data object that is registered for the DOM node that is the target of the event
17584 * @param {Event} e The event
17585 * @return {Object} data The custom data
17587 getTargetFromEvent : function(e){
17588 var t = Roo.lib.Event.getTarget(e);
17589 return t ? elements[t.id] || handles[t.id] : null;
17594 * Ext JS Library 1.1.1
17595 * Copyright(c) 2006-2007, Ext JS, LLC.
17597 * Originally Released Under LGPL - original licence link has changed is not relivant.
17600 * <script type="text/javascript">
17605 * @class Roo.dd.StatusProxy
17606 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
17607 * default drag proxy used by all Roo.dd components.
17609 * @param {Object} config
17611 Roo.dd.StatusProxy = function(config){
17612 Roo.apply(this, config);
17613 this.id = this.id || Roo.id();
17614 this.el = new Roo.Layer({
17616 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
17617 {tag: "div", cls: "x-dd-drop-icon"},
17618 {tag: "div", cls: "x-dd-drag-ghost"}
17621 shadow: !config || config.shadow !== false
17623 this.ghost = Roo.get(this.el.dom.childNodes[1]);
17624 this.dropStatus = this.dropNotAllowed;
17627 Roo.dd.StatusProxy.prototype = {
17629 * @cfg {String} dropAllowed
17630 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
17632 dropAllowed : "x-dd-drop-ok",
17634 * @cfg {String} dropNotAllowed
17635 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
17637 dropNotAllowed : "x-dd-drop-nodrop",
17640 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
17641 * over the current target element.
17642 * @param {String} cssClass The css class for the new drop status indicator image
17644 setStatus : function(cssClass){
17645 cssClass = cssClass || this.dropNotAllowed;
17646 if(this.dropStatus != cssClass){
17647 this.el.replaceClass(this.dropStatus, cssClass);
17648 this.dropStatus = cssClass;
17653 * Resets the status indicator to the default dropNotAllowed value
17654 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
17656 reset : function(clearGhost){
17657 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
17658 this.dropStatus = this.dropNotAllowed;
17660 this.ghost.update("");
17665 * Updates the contents of the ghost element
17666 * @param {String} html The html that will replace the current innerHTML of the ghost element
17668 update : function(html){
17669 if(typeof html == "string"){
17670 this.ghost.update(html);
17672 this.ghost.update("");
17673 html.style.margin = "0";
17674 this.ghost.dom.appendChild(html);
17676 // ensure float = none set?? cant remember why though.
17677 var el = this.ghost.dom.firstChild;
17679 Roo.fly(el).setStyle('float', 'none');
17684 * Returns the underlying proxy {@link Roo.Layer}
17685 * @return {Roo.Layer} el
17687 getEl : function(){
17692 * Returns the ghost element
17693 * @return {Roo.Element} el
17695 getGhost : function(){
17701 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
17703 hide : function(clear){
17711 * Stops the repair animation if it's currently running
17714 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
17720 * Displays this proxy
17727 * Force the Layer to sync its shadow and shim positions to the element
17734 * Causes the proxy to return to its position of origin via an animation. Should be called after an
17735 * invalid drop operation by the item being dragged.
17736 * @param {Array} xy The XY position of the element ([x, y])
17737 * @param {Function} callback The function to call after the repair is complete
17738 * @param {Object} scope The scope in which to execute the callback
17740 repair : function(xy, callback, scope){
17741 this.callback = callback;
17742 this.scope = scope;
17743 if(xy && this.animRepair !== false){
17744 this.el.addClass("x-dd-drag-repair");
17745 this.el.hideUnders(true);
17746 this.anim = this.el.shift({
17747 duration: this.repairDuration || .5,
17751 callback: this.afterRepair,
17755 this.afterRepair();
17760 afterRepair : function(){
17762 if(typeof this.callback == "function"){
17763 this.callback.call(this.scope || this);
17765 this.callback = null;
17770 * Ext JS Library 1.1.1
17771 * Copyright(c) 2006-2007, Ext JS, LLC.
17773 * Originally Released Under LGPL - original licence link has changed is not relivant.
17776 * <script type="text/javascript">
17780 * @class Roo.dd.DragSource
17781 * @extends Roo.dd.DDProxy
17782 * A simple class that provides the basic implementation needed to make any element draggable.
17784 * @param {String/HTMLElement/Element} el The container element
17785 * @param {Object} config
17787 Roo.dd.DragSource = function(el, config){
17788 this.el = Roo.get(el);
17789 this.dragData = {};
17791 Roo.apply(this, config);
17794 this.proxy = new Roo.dd.StatusProxy();
17797 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
17798 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
17800 this.dragging = false;
17803 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
17805 * @cfg {String} dropAllowed
17806 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
17808 dropAllowed : "x-dd-drop-ok",
17810 * @cfg {String} dropNotAllowed
17811 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
17813 dropNotAllowed : "x-dd-drop-nodrop",
17816 * Returns the data object associated with this drag source
17817 * @return {Object} data An object containing arbitrary data
17819 getDragData : function(e){
17820 return this.dragData;
17824 onDragEnter : function(e, id){
17825 var target = Roo.dd.DragDropMgr.getDDById(id);
17826 this.cachedTarget = target;
17827 if(this.beforeDragEnter(target, e, id) !== false){
17828 if(target.isNotifyTarget){
17829 var status = target.notifyEnter(this, e, this.dragData);
17830 this.proxy.setStatus(status);
17832 this.proxy.setStatus(this.dropAllowed);
17835 if(this.afterDragEnter){
17837 * An empty function by default, but provided so that you can perform a custom action
17838 * when the dragged item enters the drop target by providing an implementation.
17839 * @param {Roo.dd.DragDrop} target The drop target
17840 * @param {Event} e The event object
17841 * @param {String} id The id of the dragged element
17842 * @method afterDragEnter
17844 this.afterDragEnter(target, e, id);
17850 * An empty function by default, but provided so that you can perform a custom action
17851 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
17852 * @param {Roo.dd.DragDrop} target The drop target
17853 * @param {Event} e The event object
17854 * @param {String} id The id of the dragged element
17855 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
17857 beforeDragEnter : function(target, e, id){
17862 alignElWithMouse: function() {
17863 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
17868 onDragOver : function(e, id){
17869 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
17870 if(this.beforeDragOver(target, e, id) !== false){
17871 if(target.isNotifyTarget){
17872 var status = target.notifyOver(this, e, this.dragData);
17873 this.proxy.setStatus(status);
17876 if(this.afterDragOver){
17878 * An empty function by default, but provided so that you can perform a custom action
17879 * while the dragged item is over the drop target by providing an implementation.
17880 * @param {Roo.dd.DragDrop} target The drop target
17881 * @param {Event} e The event object
17882 * @param {String} id The id of the dragged element
17883 * @method afterDragOver
17885 this.afterDragOver(target, e, id);
17891 * An empty function by default, but provided so that you can perform a custom action
17892 * while the dragged item is over the drop target and optionally cancel the onDragOver.
17893 * @param {Roo.dd.DragDrop} target The drop target
17894 * @param {Event} e The event object
17895 * @param {String} id The id of the dragged element
17896 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
17898 beforeDragOver : function(target, e, id){
17903 onDragOut : function(e, id){
17904 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
17905 if(this.beforeDragOut(target, e, id) !== false){
17906 if(target.isNotifyTarget){
17907 target.notifyOut(this, e, this.dragData);
17909 this.proxy.reset();
17910 if(this.afterDragOut){
17912 * An empty function by default, but provided so that you can perform a custom action
17913 * after the dragged item is dragged out of the target without dropping.
17914 * @param {Roo.dd.DragDrop} target The drop target
17915 * @param {Event} e The event object
17916 * @param {String} id The id of the dragged element
17917 * @method afterDragOut
17919 this.afterDragOut(target, e, id);
17922 this.cachedTarget = null;
17926 * An empty function by default, but provided so that you can perform a custom action before the dragged
17927 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
17928 * @param {Roo.dd.DragDrop} target The drop target
17929 * @param {Event} e The event object
17930 * @param {String} id The id of the dragged element
17931 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
17933 beforeDragOut : function(target, e, id){
17938 onDragDrop : function(e, id){
17939 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
17940 if(this.beforeDragDrop(target, e, id) !== false){
17941 if(target.isNotifyTarget){
17942 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
17943 this.onValidDrop(target, e, id);
17945 this.onInvalidDrop(target, e, id);
17948 this.onValidDrop(target, e, id);
17951 if(this.afterDragDrop){
17953 * An empty function by default, but provided so that you can perform a custom action
17954 * after a valid drag drop has occurred by providing an implementation.
17955 * @param {Roo.dd.DragDrop} target The drop target
17956 * @param {Event} e The event object
17957 * @param {String} id The id of the dropped element
17958 * @method afterDragDrop
17960 this.afterDragDrop(target, e, id);
17963 delete this.cachedTarget;
17967 * An empty function by default, but provided so that you can perform a custom action before the dragged
17968 * item is dropped onto the target and optionally cancel the onDragDrop.
17969 * @param {Roo.dd.DragDrop} target The drop target
17970 * @param {Event} e The event object
17971 * @param {String} id The id of the dragged element
17972 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
17974 beforeDragDrop : function(target, e, id){
17979 onValidDrop : function(target, e, id){
17981 if(this.afterValidDrop){
17983 * An empty function by default, but provided so that you can perform a custom action
17984 * after a valid drop has occurred by providing an implementation.
17985 * @param {Object} target The target DD
17986 * @param {Event} e The event object
17987 * @param {String} id The id of the dropped element
17988 * @method afterInvalidDrop
17990 this.afterValidDrop(target, e, id);
17995 getRepairXY : function(e, data){
17996 return this.el.getXY();
18000 onInvalidDrop : function(target, e, id){
18001 this.beforeInvalidDrop(target, e, id);
18002 if(this.cachedTarget){
18003 if(this.cachedTarget.isNotifyTarget){
18004 this.cachedTarget.notifyOut(this, e, this.dragData);
18006 this.cacheTarget = null;
18008 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
18010 if(this.afterInvalidDrop){
18012 * An empty function by default, but provided so that you can perform a custom action
18013 * after an invalid drop has occurred by providing an implementation.
18014 * @param {Event} e The event object
18015 * @param {String} id The id of the dropped element
18016 * @method afterInvalidDrop
18018 this.afterInvalidDrop(e, id);
18023 afterRepair : function(){
18025 this.el.highlight(this.hlColor || "c3daf9");
18027 this.dragging = false;
18031 * An empty function by default, but provided so that you can perform a custom action after an invalid
18032 * drop has occurred.
18033 * @param {Roo.dd.DragDrop} target The drop target
18034 * @param {Event} e The event object
18035 * @param {String} id The id of the dragged element
18036 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
18038 beforeInvalidDrop : function(target, e, id){
18043 handleMouseDown : function(e){
18044 if(this.dragging) {
18047 var data = this.getDragData(e);
18048 if(data && this.onBeforeDrag(data, e) !== false){
18049 this.dragData = data;
18051 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
18056 * An empty function by default, but provided so that you can perform a custom action before the initial
18057 * drag event begins and optionally cancel it.
18058 * @param {Object} data An object containing arbitrary data to be shared with drop targets
18059 * @param {Event} e The event object
18060 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
18062 onBeforeDrag : function(data, e){
18067 * An empty function by default, but provided so that you can perform a custom action once the initial
18068 * drag event has begun. The drag cannot be canceled from this function.
18069 * @param {Number} x The x position of the click on the dragged object
18070 * @param {Number} y The y position of the click on the dragged object
18072 onStartDrag : Roo.emptyFn,
18074 // private - YUI override
18075 startDrag : function(x, y){
18076 this.proxy.reset();
18077 this.dragging = true;
18078 this.proxy.update("");
18079 this.onInitDrag(x, y);
18084 onInitDrag : function(x, y){
18085 var clone = this.el.dom.cloneNode(true);
18086 clone.id = Roo.id(); // prevent duplicate ids
18087 this.proxy.update(clone);
18088 this.onStartDrag(x, y);
18093 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
18094 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
18096 getProxy : function(){
18101 * Hides the drag source's {@link Roo.dd.StatusProxy}
18103 hideProxy : function(){
18105 this.proxy.reset(true);
18106 this.dragging = false;
18110 triggerCacheRefresh : function(){
18111 Roo.dd.DDM.refreshCache(this.groups);
18114 // private - override to prevent hiding
18115 b4EndDrag: function(e) {
18118 // private - override to prevent moving
18119 endDrag : function(e){
18120 this.onEndDrag(this.dragData, e);
18124 onEndDrag : function(data, e){
18127 // private - pin to cursor
18128 autoOffset : function(x, y) {
18129 this.setDelta(-12, -20);
18133 * Ext JS Library 1.1.1
18134 * Copyright(c) 2006-2007, Ext JS, LLC.
18136 * Originally Released Under LGPL - original licence link has changed is not relivant.
18139 * <script type="text/javascript">
18144 * @class Roo.dd.DropTarget
18145 * @extends Roo.dd.DDTarget
18146 * A simple class that provides the basic implementation needed to make any element a drop target that can have
18147 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
18149 * @param {String/HTMLElement/Element} el The container element
18150 * @param {Object} config
18152 Roo.dd.DropTarget = function(el, config){
18153 this.el = Roo.get(el);
18155 Roo.apply(this, config);
18157 if(this.containerScroll){
18158 Roo.dd.ScrollManager.register(this.el);
18161 Roo.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
18166 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
18168 * @cfg {String} overClass
18169 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
18172 * @cfg {String} dropAllowed
18173 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
18175 dropAllowed : "x-dd-drop-ok",
18177 * @cfg {String} dropNotAllowed
18178 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
18180 dropNotAllowed : "x-dd-drop-nodrop",
18186 isNotifyTarget : true,
18189 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
18190 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
18191 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
18192 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18193 * @param {Event} e The event
18194 * @param {Object} data An object containing arbitrary data supplied by the drag source
18195 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18196 * underlying {@link Roo.dd.StatusProxy} can be updated
18198 notifyEnter : function(dd, e, data){
18199 if(this.overClass){
18200 this.el.addClass(this.overClass);
18202 return this.dropAllowed;
18206 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
18207 * This method will be called on every mouse movement while the drag source is over the drop target.
18208 * This default implementation simply returns the dropAllowed config value.
18209 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18210 * @param {Event} e The event
18211 * @param {Object} data An object containing arbitrary data supplied by the drag source
18212 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18213 * underlying {@link Roo.dd.StatusProxy} can be updated
18215 notifyOver : function(dd, e, data){
18216 return this.dropAllowed;
18220 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
18221 * out of the target without dropping. This default implementation simply removes the CSS class specified by
18222 * overClass (if any) from the drop element.
18223 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18224 * @param {Event} e The event
18225 * @param {Object} data An object containing arbitrary data supplied by the drag source
18227 notifyOut : function(dd, e, data){
18228 if(this.overClass){
18229 this.el.removeClass(this.overClass);
18234 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
18235 * been dropped on it. This method has no default implementation and returns false, so you must provide an
18236 * implementation that does something to process the drop event and returns true so that the drag source's
18237 * repair action does not run.
18238 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18239 * @param {Event} e The event
18240 * @param {Object} data An object containing arbitrary data supplied by the drag source
18241 * @return {Boolean} True if the drop was valid, else false
18243 notifyDrop : function(dd, e, data){
18248 * Ext JS Library 1.1.1
18249 * Copyright(c) 2006-2007, Ext JS, LLC.
18251 * Originally Released Under LGPL - original licence link has changed is not relivant.
18254 * <script type="text/javascript">
18259 * @class Roo.dd.DragZone
18260 * @extends Roo.dd.DragSource
18261 * This class provides a container DD instance that proxies for multiple child node sources.<br />
18262 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
18264 * @param {String/HTMLElement/Element} el The container element
18265 * @param {Object} config
18267 Roo.dd.DragZone = function(el, config){
18268 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
18269 if(this.containerScroll){
18270 Roo.dd.ScrollManager.register(this.el);
18274 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
18276 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
18277 * for auto scrolling during drag operations.
18280 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
18281 * method after a failed drop (defaults to "c3daf9" - light blue)
18285 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
18286 * for a valid target to drag based on the mouse down. Override this method
18287 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
18288 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
18289 * @param {EventObject} e The mouse down event
18290 * @return {Object} The dragData
18292 getDragData : function(e){
18293 return Roo.dd.Registry.getHandleFromEvent(e);
18297 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
18298 * this.dragData.ddel
18299 * @param {Number} x The x position of the click on the dragged object
18300 * @param {Number} y The y position of the click on the dragged object
18301 * @return {Boolean} true to continue the drag, false to cancel
18303 onInitDrag : function(x, y){
18304 this.proxy.update(this.dragData.ddel.cloneNode(true));
18305 this.onStartDrag(x, y);
18310 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
18312 afterRepair : function(){
18314 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
18316 this.dragging = false;
18320 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
18321 * the XY of this.dragData.ddel
18322 * @param {EventObject} e The mouse up event
18323 * @return {Array} The xy location (e.g. [100, 200])
18325 getRepairXY : function(e){
18326 return Roo.Element.fly(this.dragData.ddel).getXY();
18330 * Ext JS Library 1.1.1
18331 * Copyright(c) 2006-2007, Ext JS, LLC.
18333 * Originally Released Under LGPL - original licence link has changed is not relivant.
18336 * <script type="text/javascript">
18339 * @class Roo.dd.DropZone
18340 * @extends Roo.dd.DropTarget
18341 * This class provides a container DD instance that proxies for multiple child node targets.<br />
18342 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
18344 * @param {String/HTMLElement/Element} el The container element
18345 * @param {Object} config
18347 Roo.dd.DropZone = function(el, config){
18348 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
18351 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
18353 * Returns a custom data object associated with the DOM node that is the target of the event. By default
18354 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
18355 * provide your own custom lookup.
18356 * @param {Event} e The event
18357 * @return {Object} data The custom data
18359 getTargetFromEvent : function(e){
18360 return Roo.dd.Registry.getTargetFromEvent(e);
18364 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
18365 * that it has registered. This method has no default implementation and should be overridden to provide
18366 * node-specific processing if necessary.
18367 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18368 * {@link #getTargetFromEvent} for this node)
18369 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18370 * @param {Event} e The event
18371 * @param {Object} data An object containing arbitrary data supplied by the drag source
18373 onNodeEnter : function(n, dd, e, data){
18378 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
18379 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
18380 * overridden to provide the proper feedback.
18381 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18382 * {@link #getTargetFromEvent} for this node)
18383 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18384 * @param {Event} e The event
18385 * @param {Object} data An object containing arbitrary data supplied by the drag source
18386 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18387 * underlying {@link Roo.dd.StatusProxy} can be updated
18389 onNodeOver : function(n, dd, e, data){
18390 return this.dropAllowed;
18394 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
18395 * the drop node without dropping. This method has no default implementation and should be overridden to provide
18396 * node-specific processing if necessary.
18397 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18398 * {@link #getTargetFromEvent} for this node)
18399 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18400 * @param {Event} e The event
18401 * @param {Object} data An object containing arbitrary data supplied by the drag source
18403 onNodeOut : function(n, dd, e, data){
18408 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
18409 * the drop node. The default implementation returns false, so it should be overridden to provide the
18410 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
18411 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18412 * {@link #getTargetFromEvent} for this node)
18413 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18414 * @param {Event} e The event
18415 * @param {Object} data An object containing arbitrary data supplied by the drag source
18416 * @return {Boolean} True if the drop was valid, else false
18418 onNodeDrop : function(n, dd, e, data){
18423 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
18424 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
18425 * it should be overridden to provide the proper feedback if necessary.
18426 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18427 * @param {Event} e The event
18428 * @param {Object} data An object containing arbitrary data supplied by the drag source
18429 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18430 * underlying {@link Roo.dd.StatusProxy} can be updated
18432 onContainerOver : function(dd, e, data){
18433 return this.dropNotAllowed;
18437 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
18438 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
18439 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
18440 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
18441 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18442 * @param {Event} e The event
18443 * @param {Object} data An object containing arbitrary data supplied by the drag source
18444 * @return {Boolean} True if the drop was valid, else false
18446 onContainerDrop : function(dd, e, data){
18451 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
18452 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
18453 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
18454 * you should override this method and provide a custom implementation.
18455 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18456 * @param {Event} e The event
18457 * @param {Object} data An object containing arbitrary data supplied by the drag source
18458 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18459 * underlying {@link Roo.dd.StatusProxy} can be updated
18461 notifyEnter : function(dd, e, data){
18462 return this.dropNotAllowed;
18466 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
18467 * This method will be called on every mouse movement while the drag source is over the drop zone.
18468 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
18469 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
18470 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
18471 * registered node, it will call {@link #onContainerOver}.
18472 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18473 * @param {Event} e The event
18474 * @param {Object} data An object containing arbitrary data supplied by the drag source
18475 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18476 * underlying {@link Roo.dd.StatusProxy} can be updated
18478 notifyOver : function(dd, e, data){
18479 var n = this.getTargetFromEvent(e);
18480 if(!n){ // not over valid drop target
18481 if(this.lastOverNode){
18482 this.onNodeOut(this.lastOverNode, dd, e, data);
18483 this.lastOverNode = null;
18485 return this.onContainerOver(dd, e, data);
18487 if(this.lastOverNode != n){
18488 if(this.lastOverNode){
18489 this.onNodeOut(this.lastOverNode, dd, e, data);
18491 this.onNodeEnter(n, dd, e, data);
18492 this.lastOverNode = n;
18494 return this.onNodeOver(n, dd, e, data);
18498 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
18499 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
18500 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
18501 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18502 * @param {Event} e The event
18503 * @param {Object} data An object containing arbitrary data supplied by the drag zone
18505 notifyOut : function(dd, e, data){
18506 if(this.lastOverNode){
18507 this.onNodeOut(this.lastOverNode, dd, e, data);
18508 this.lastOverNode = null;
18513 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
18514 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
18515 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
18516 * otherwise it will call {@link #onContainerDrop}.
18517 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18518 * @param {Event} e The event
18519 * @param {Object} data An object containing arbitrary data supplied by the drag source
18520 * @return {Boolean} True if the drop was valid, else false
18522 notifyDrop : function(dd, e, data){
18523 if(this.lastOverNode){
18524 this.onNodeOut(this.lastOverNode, dd, e, data);
18525 this.lastOverNode = null;
18527 var n = this.getTargetFromEvent(e);
18529 this.onNodeDrop(n, dd, e, data) :
18530 this.onContainerDrop(dd, e, data);
18534 triggerCacheRefresh : function(){
18535 Roo.dd.DDM.refreshCache(this.groups);
18539 * Ext JS Library 1.1.1
18540 * Copyright(c) 2006-2007, Ext JS, LLC.
18542 * Originally Released Under LGPL - original licence link has changed is not relivant.
18545 * <script type="text/javascript">
18550 * @class Roo.data.SortTypes
18552 * Defines the default sorting (casting?) comparison functions used when sorting data.
18554 Roo.data.SortTypes = {
18556 * Default sort that does nothing
18557 * @param {Mixed} s The value being converted
18558 * @return {Mixed} The comparison value
18560 none : function(s){
18565 * The regular expression used to strip tags
18569 stripTagsRE : /<\/?[^>]+>/gi,
18572 * Strips all HTML tags to sort on text only
18573 * @param {Mixed} s The value being converted
18574 * @return {String} The comparison value
18576 asText : function(s){
18577 return String(s).replace(this.stripTagsRE, "");
18581 * Strips all HTML tags to sort on text only - Case insensitive
18582 * @param {Mixed} s The value being converted
18583 * @return {String} The comparison value
18585 asUCText : function(s){
18586 return String(s).toUpperCase().replace(this.stripTagsRE, "");
18590 * Case insensitive string
18591 * @param {Mixed} s The value being converted
18592 * @return {String} The comparison value
18594 asUCString : function(s) {
18595 return String(s).toUpperCase();
18600 * @param {Mixed} s The value being converted
18601 * @return {Number} The comparison value
18603 asDate : function(s) {
18607 if(s instanceof Date){
18608 return s.getTime();
18610 return Date.parse(String(s));
18615 * @param {Mixed} s The value being converted
18616 * @return {Float} The comparison value
18618 asFloat : function(s) {
18619 var val = parseFloat(String(s).replace(/,/g, ""));
18620 if(isNaN(val)) val = 0;
18626 * @param {Mixed} s The value being converted
18627 * @return {Number} The comparison value
18629 asInt : function(s) {
18630 var val = parseInt(String(s).replace(/,/g, ""));
18631 if(isNaN(val)) val = 0;
18636 * Ext JS Library 1.1.1
18637 * Copyright(c) 2006-2007, Ext JS, LLC.
18639 * Originally Released Under LGPL - original licence link has changed is not relivant.
18642 * <script type="text/javascript">
18646 * @class Roo.data.Record
18647 * Instances of this class encapsulate both record <em>definition</em> information, and record
18648 * <em>value</em> information for use in {@link Roo.data.Store} objects, or any code which needs
18649 * to access Records cached in an {@link Roo.data.Store} object.<br>
18651 * Constructors for this class are generated by passing an Array of field definition objects to {@link #create}.
18652 * Instances are usually only created by {@link Roo.data.Reader} implementations when processing unformatted data
18655 * Record objects generated by this constructor inherit all the methods of Roo.data.Record listed below.
18657 * This constructor should not be used to create Record objects. Instead, use the constructor generated by
18658 * {@link #create}. The parameters are the same.
18659 * @param {Array} data An associative Array of data values keyed by the field name.
18660 * @param {Object} id (Optional) The id of the record. This id should be unique, and is used by the
18661 * {@link Roo.data.Store} object which owns the Record to index its collection of Records. If
18662 * not specified an integer id is generated.
18664 Roo.data.Record = function(data, id){
18665 this.id = (id || id === 0) ? id : ++Roo.data.Record.AUTO_ID;
18670 * Generate a constructor for a specific record layout.
18671 * @param {Array} o An Array of field definition objects which specify field names, and optionally,
18672 * data types, and a mapping for an {@link Roo.data.Reader} to extract the field's value from a data object.
18673 * Each field definition object may contain the following properties: <ul>
18674 * <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,
18675 * for example the <em>dataIndex</em> property in column definition objects passed to {@link Roo.grid.ColumnModel}</p></li>
18676 * <li><b>mapping</b> : String<p style="margin-left:1em">(Optional) A path specification for use by the {@link Roo.data.Reader} implementation
18677 * that is creating the Record to access the data value from the data object. If an {@link Roo.data.JsonReader}
18678 * is being used, then this is a string containing the javascript expression to reference the data relative to
18679 * the record item's root. If an {@link Roo.data.XmlReader} is being used, this is an {@link Roo.DomQuery} path
18680 * to the data item relative to the record element. If the mapping expression is the same as the field name,
18681 * this may be omitted.</p></li>
18682 * <li><b>type</b> : String<p style="margin-left:1em">(Optional) The data type for conversion to displayable value. Possible values are
18683 * <ul><li>auto (Default, implies no conversion)</li>
18688 * <li>date</li></ul></p></li>
18689 * <li><b>sortType</b> : Mixed<p style="margin-left:1em">(Optional) A member of {@link Roo.data.SortTypes}.</p></li>
18690 * <li><b>sortDir</b> : String<p style="margin-left:1em">(Optional) Initial direction to sort. "ASC" or "DESC"</p></li>
18691 * <li><b>convert</b> : Function<p style="margin-left:1em">(Optional) A function which converts the value provided
18692 * by the Reader into an object that will be stored in the Record. It is passed the
18693 * following parameters:<ul>
18694 * <li><b>v</b> : Mixed<p style="margin-left:1em">The data value as read by the Reader.</p></li>
18696 * <li><b>dateFormat</b> : String<p style="margin-left:1em">(Optional) A format String for the Date.parseDate function.</p></li>
18698 * <br>usage:<br><pre><code>
18699 var TopicRecord = Roo.data.Record.create(
18700 {name: 'title', mapping: 'topic_title'},
18701 {name: 'author', mapping: 'username'},
18702 {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
18703 {name: 'lastPost', mapping: 'post_time', type: 'date'},
18704 {name: 'lastPoster', mapping: 'user2'},
18705 {name: 'excerpt', mapping: 'post_text'}
18708 var myNewRecord = new TopicRecord({
18709 title: 'Do my job please',
18712 lastPost: new Date(),
18713 lastPoster: 'Animal',
18714 excerpt: 'No way dude!'
18716 myStore.add(myNewRecord);
18721 Roo.data.Record.create = function(o){
18722 var f = function(){
18723 f.superclass.constructor.apply(this, arguments);
18725 Roo.extend(f, Roo.data.Record);
18726 var p = f.prototype;
18727 p.fields = new Roo.util.MixedCollection(false, function(field){
18730 for(var i = 0, len = o.length; i < len; i++){
18731 p.fields.add(new Roo.data.Field(o[i]));
18733 f.getField = function(name){
18734 return p.fields.get(name);
18739 Roo.data.Record.AUTO_ID = 1000;
18740 Roo.data.Record.EDIT = 'edit';
18741 Roo.data.Record.REJECT = 'reject';
18742 Roo.data.Record.COMMIT = 'commit';
18744 Roo.data.Record.prototype = {
18746 * Readonly flag - true if this record has been modified.
18755 join : function(store){
18756 this.store = store;
18760 * Set the named field to the specified value.
18761 * @param {String} name The name of the field to set.
18762 * @param {Object} value The value to set the field to.
18764 set : function(name, value){
18765 if(this.data[name] == value){
18769 if(!this.modified){
18770 this.modified = {};
18772 if(typeof this.modified[name] == 'undefined'){
18773 this.modified[name] = this.data[name];
18775 this.data[name] = value;
18777 this.store.afterEdit(this);
18782 * Get the value of the named field.
18783 * @param {String} name The name of the field to get the value of.
18784 * @return {Object} The value of the field.
18786 get : function(name){
18787 return this.data[name];
18791 beginEdit : function(){
18792 this.editing = true;
18793 this.modified = {};
18797 cancelEdit : function(){
18798 this.editing = false;
18799 delete this.modified;
18803 endEdit : function(){
18804 this.editing = false;
18805 if(this.dirty && this.store){
18806 this.store.afterEdit(this);
18811 * Usually called by the {@link Roo.data.Store} which owns the Record.
18812 * Rejects all changes made to the Record since either creation, or the last commit operation.
18813 * Modified fields are reverted to their original values.
18815 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
18816 * of reject operations.
18818 reject : function(){
18819 var m = this.modified;
18821 if(typeof m[n] != "function"){
18822 this.data[n] = m[n];
18825 this.dirty = false;
18826 delete this.modified;
18827 this.editing = false;
18829 this.store.afterReject(this);
18834 * Usually called by the {@link Roo.data.Store} which owns the Record.
18835 * Commits all changes made to the Record since either creation, or the last commit operation.
18837 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
18838 * of commit operations.
18840 commit : function(){
18841 this.dirty = false;
18842 delete this.modified;
18843 this.editing = false;
18845 this.store.afterCommit(this);
18850 hasError : function(){
18851 return this.error != null;
18855 clearError : function(){
18860 * Creates a copy of this record.
18861 * @param {String} id (optional) A new record id if you don't want to use this record's id
18864 copy : function(newId) {
18865 return new this.constructor(Roo.apply({}, this.data), newId || this.id);
18869 * Ext JS Library 1.1.1
18870 * Copyright(c) 2006-2007, Ext JS, LLC.
18872 * Originally Released Under LGPL - original licence link has changed is not relivant.
18875 * <script type="text/javascript">
18881 * @class Roo.data.Store
18882 * @extends Roo.util.Observable
18883 * The Store class encapsulates a client side cache of {@link Roo.data.Record} objects which provide input data
18884 * for widgets such as the Roo.grid.Grid, or the Roo.form.ComboBox.<br>
18886 * 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
18887 * has no knowledge of the format of the data returned by the Proxy.<br>
18889 * A Store object uses its configured implementation of {@link Roo.data.DataReader} to create {@link Roo.data.Record}
18890 * instances from the data object. These records are cached and made available through accessor functions.
18892 * Creates a new Store.
18893 * @param {Object} config A config object containing the objects needed for the Store to access data,
18894 * and read the data into Records.
18896 Roo.data.Store = function(config){
18897 this.data = new Roo.util.MixedCollection(false);
18898 this.data.getKey = function(o){
18901 this.baseParams = {};
18903 this.paramNames = {
18910 if(config && config.data){
18911 this.inlineData = config.data;
18912 delete config.data;
18915 Roo.apply(this, config);
18917 if(this.reader){ // reader passed
18918 this.reader = Roo.factory(this.reader, Roo.data);
18919 this.reader.xmodule = this.xmodule || false;
18920 if(!this.recordType){
18921 this.recordType = this.reader.recordType;
18923 if(this.reader.onMetaChange){
18924 this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
18928 if(this.recordType){
18929 this.fields = this.recordType.prototype.fields;
18931 this.modified = [];
18935 * @event datachanged
18936 * Fires when the data cache has changed, and a widget which is using this Store
18937 * as a Record cache should refresh its view.
18938 * @param {Store} this
18940 datachanged : true,
18942 * @event metachange
18943 * Fires when this store's reader provides new metadata (fields). This is currently only support for JsonReaders.
18944 * @param {Store} this
18945 * @param {Object} meta The JSON metadata
18950 * Fires when Records have been added to the Store
18951 * @param {Store} this
18952 * @param {Roo.data.Record[]} records The array of Records added
18953 * @param {Number} index The index at which the record(s) were added
18958 * Fires when a Record has been removed from the Store
18959 * @param {Store} this
18960 * @param {Roo.data.Record} record The Record that was removed
18961 * @param {Number} index The index at which the record was removed
18966 * Fires when a Record has been updated
18967 * @param {Store} this
18968 * @param {Roo.data.Record} record The Record that was updated
18969 * @param {String} operation The update operation being performed. Value may be one of:
18971 Roo.data.Record.EDIT
18972 Roo.data.Record.REJECT
18973 Roo.data.Record.COMMIT
18979 * Fires when the data cache has been cleared.
18980 * @param {Store} this
18984 * @event beforeload
18985 * Fires before a request is made for a new data object. If the beforeload handler returns false
18986 * the load action will be canceled.
18987 * @param {Store} this
18988 * @param {Object} options The loading options that were specified (see {@link #load} for details)
18993 * Fires after a new set of Records has been loaded.
18994 * @param {Store} this
18995 * @param {Roo.data.Record[]} records The Records that were loaded
18996 * @param {Object} options The loading options that were specified (see {@link #load} for details)
19000 * @event loadexception
19001 * Fires if an exception occurs in the Proxy during loading.
19002 * Called with the signature of the Proxy's "loadexception" event.
19003 * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
19006 * @param {Object} return from JsonData.reader() - success, totalRecords, records
19007 * @param {Object} load options
19008 * @param {Object} jsonData from your request (normally this contains the Exception)
19010 loadexception : true
19014 this.proxy = Roo.factory(this.proxy, Roo.data);
19015 this.proxy.xmodule = this.xmodule || false;
19016 this.relayEvents(this.proxy, ["loadexception"]);
19018 this.sortToggle = {};
19020 Roo.data.Store.superclass.constructor.call(this);
19022 if(this.inlineData){
19023 this.loadData(this.inlineData);
19024 delete this.inlineData;
19027 Roo.extend(Roo.data.Store, Roo.util.Observable, {
19029 * @cfg {boolean} isLocal flag if data is locally available (and can be always looked up
19030 * without a remote query - used by combo/forms at present.
19034 * @cfg {Roo.data.DataProxy} proxy The Proxy object which provides access to a data object.
19037 * @cfg {Array} data Inline data to be loaded when the store is initialized.
19040 * @cfg {Roo.data.Reader} reader The Reader object which processes the data object and returns
19041 * an Array of Roo.data.record objects which are cached keyed by their <em>id</em> property.
19044 * @cfg {Object} baseParams An object containing properties which are to be sent as parameters
19045 * on any HTTP request
19048 * @cfg {Object} sortInfo A config object in the format: {field: "fieldName", direction: "ASC|DESC"}
19051 * @cfg {boolean} remoteSort True if sorting is to be handled by requesting the Proxy to provide a refreshed
19052 * version of the data object in sorted order, as opposed to sorting the Record cache in place (defaults to false).
19054 remoteSort : false,
19057 * @cfg {boolean} pruneModifiedRecords True to clear all modified record information each time the store is
19058 * loaded or when a record is removed. (defaults to false).
19060 pruneModifiedRecords : false,
19063 lastOptions : null,
19066 * Add Records to the Store and fires the add event.
19067 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
19069 add : function(records){
19070 records = [].concat(records);
19071 for(var i = 0, len = records.length; i < len; i++){
19072 records[i].join(this);
19074 var index = this.data.length;
19075 this.data.addAll(records);
19076 this.fireEvent("add", this, records, index);
19080 * Remove a Record from the Store and fires the remove event.
19081 * @param {Ext.data.Record} record The Roo.data.Record object to remove from the cache.
19083 remove : function(record){
19084 var index = this.data.indexOf(record);
19085 this.data.removeAt(index);
19086 if(this.pruneModifiedRecords){
19087 this.modified.remove(record);
19089 this.fireEvent("remove", this, record, index);
19093 * Remove all Records from the Store and fires the clear event.
19095 removeAll : function(){
19097 if(this.pruneModifiedRecords){
19098 this.modified = [];
19100 this.fireEvent("clear", this);
19104 * Inserts Records to the Store at the given index and fires the add event.
19105 * @param {Number} index The start index at which to insert the passed Records.
19106 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
19108 insert : function(index, records){
19109 records = [].concat(records);
19110 for(var i = 0, len = records.length; i < len; i++){
19111 this.data.insert(index, records[i]);
19112 records[i].join(this);
19114 this.fireEvent("add", this, records, index);
19118 * Get the index within the cache of the passed Record.
19119 * @param {Roo.data.Record} record The Roo.data.Record object to to find.
19120 * @return {Number} The index of the passed Record. Returns -1 if not found.
19122 indexOf : function(record){
19123 return this.data.indexOf(record);
19127 * Get the index within the cache of the Record with the passed id.
19128 * @param {String} id The id of the Record to find.
19129 * @return {Number} The index of the Record. Returns -1 if not found.
19131 indexOfId : function(id){
19132 return this.data.indexOfKey(id);
19136 * Get the Record with the specified id.
19137 * @param {String} id The id of the Record to find.
19138 * @return {Roo.data.Record} The Record with the passed id. Returns undefined if not found.
19140 getById : function(id){
19141 return this.data.key(id);
19145 * Get the Record at the specified index.
19146 * @param {Number} index The index of the Record to find.
19147 * @return {Roo.data.Record} The Record at the passed index. Returns undefined if not found.
19149 getAt : function(index){
19150 return this.data.itemAt(index);
19154 * Returns a range of Records between specified indices.
19155 * @param {Number} startIndex (optional) The starting index (defaults to 0)
19156 * @param {Number} endIndex (optional) The ending index (defaults to the last Record in the Store)
19157 * @return {Roo.data.Record[]} An array of Records
19159 getRange : function(start, end){
19160 return this.data.getRange(start, end);
19164 storeOptions : function(o){
19165 o = Roo.apply({}, o);
19168 this.lastOptions = o;
19172 * Loads the Record cache from the configured Proxy using the configured Reader.
19174 * If using remote paging, then the first load call must specify the <em>start</em>
19175 * and <em>limit</em> properties in the options.params property to establish the initial
19176 * position within the dataset, and the number of Records to cache on each read from the Proxy.
19178 * <strong>It is important to note that for remote data sources, loading is asynchronous,
19179 * and this call will return before the new data has been loaded. Perform any post-processing
19180 * in a callback function, or in a "load" event handler.</strong>
19182 * @param {Object} options An object containing properties which control loading options:<ul>
19183 * <li>params {Object} An object containing properties to pass as HTTP parameters to a remote data source.</li>
19184 * <li>callback {Function} A function to be called after the Records have been loaded. The callback is
19185 * passed the following arguments:<ul>
19186 * <li>r : Roo.data.Record[]</li>
19187 * <li>options: Options object from the load call</li>
19188 * <li>success: Boolean success indicator</li></ul></li>
19189 * <li>scope {Object} Scope with which to call the callback (defaults to the Store object)</li>
19190 * <li>add {Boolean} indicator to append loaded records rather than replace the current cache.</li>
19193 load : function(options){
19194 options = options || {};
19195 if(this.fireEvent("beforeload", this, options) !== false){
19196 this.storeOptions(options);
19197 var p = Roo.apply(options.params || {}, this.baseParams);
19198 if(this.sortInfo && this.remoteSort){
19199 var pn = this.paramNames;
19200 p[pn["sort"]] = this.sortInfo.field;
19201 p[pn["dir"]] = this.sortInfo.direction;
19203 this.proxy.load(p, this.reader, this.loadRecords, this, options);
19208 * Reloads the Record cache from the configured Proxy using the configured Reader and
19209 * the options from the last load operation performed.
19210 * @param {Object} options (optional) An object containing properties which may override the options
19211 * used in the last load operation. See {@link #load} for details (defaults to null, in which case
19212 * the most recently used options are reused).
19214 reload : function(options){
19215 this.load(Roo.applyIf(options||{}, this.lastOptions));
19219 // Called as a callback by the Reader during a load operation.
19220 loadRecords : function(o, options, success){
19221 if(!o || success === false){
19222 if(success !== false){
19223 this.fireEvent("load", this, [], options);
19225 if(options.callback){
19226 options.callback.call(options.scope || this, [], options, false);
19230 // if data returned failure - throw an exception.
19231 if (o.success === false) {
19232 this.fireEvent("loadexception", this, o, options, this.reader.jsonData);
19235 var r = o.records, t = o.totalRecords || r.length;
19236 if(!options || options.add !== true){
19237 if(this.pruneModifiedRecords){
19238 this.modified = [];
19240 for(var i = 0, len = r.length; i < len; i++){
19244 this.data = this.snapshot;
19245 delete this.snapshot;
19248 this.data.addAll(r);
19249 this.totalLength = t;
19251 this.fireEvent("datachanged", this);
19253 this.totalLength = Math.max(t, this.data.length+r.length);
19256 this.fireEvent("load", this, r, options);
19257 if(options.callback){
19258 options.callback.call(options.scope || this, r, options, true);
19263 * Loads data from a passed data block. A Reader which understands the format of the data
19264 * must have been configured in the constructor.
19265 * @param {Object} data The data block from which to read the Records. The format of the data expected
19266 * is dependent on the type of Reader that is configured and should correspond to that Reader's readRecords parameter.
19267 * @param {Boolean} append (Optional) True to append the new Records rather than replace the existing cache.
19269 loadData : function(o, append){
19270 var r = this.reader.readRecords(o);
19271 this.loadRecords(r, {add: append}, true);
19275 * Gets the number of cached records.
19277 * <em>If using paging, this may not be the total size of the dataset. If the data object
19278 * used by the Reader contains the dataset size, then the getTotalCount() function returns
19279 * the data set size</em>
19281 getCount : function(){
19282 return this.data.length || 0;
19286 * Gets the total number of records in the dataset as returned by the server.
19288 * <em>If using paging, for this to be accurate, the data object used by the Reader must contain
19289 * the dataset size</em>
19291 getTotalCount : function(){
19292 return this.totalLength || 0;
19296 * Returns the sort state of the Store as an object with two properties:
19298 field {String} The name of the field by which the Records are sorted
19299 direction {String} The sort order, "ASC" or "DESC"
19302 getSortState : function(){
19303 return this.sortInfo;
19307 applySort : function(){
19308 if(this.sortInfo && !this.remoteSort){
19309 var s = this.sortInfo, f = s.field;
19310 var st = this.fields.get(f).sortType;
19311 var fn = function(r1, r2){
19312 var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
19313 return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
19315 this.data.sort(s.direction, fn);
19316 if(this.snapshot && this.snapshot != this.data){
19317 this.snapshot.sort(s.direction, fn);
19323 * Sets the default sort column and order to be used by the next load operation.
19324 * @param {String} fieldName The name of the field to sort by.
19325 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
19327 setDefaultSort : function(field, dir){
19328 this.sortInfo = {field: field, direction: dir ? dir.toUpperCase() : "ASC"};
19332 * Sort the Records.
19333 * If remote sorting is used, the sort is performed on the server, and the cache is
19334 * reloaded. If local sorting is used, the cache is sorted internally.
19335 * @param {String} fieldName The name of the field to sort by.
19336 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
19338 sort : function(fieldName, dir){
19339 var f = this.fields.get(fieldName);
19341 if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir
19342 dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
19347 this.sortToggle[f.name] = dir;
19348 this.sortInfo = {field: f.name, direction: dir};
19349 if(!this.remoteSort){
19351 this.fireEvent("datachanged", this);
19353 this.load(this.lastOptions);
19358 * Calls the specified function for each of the Records in the cache.
19359 * @param {Function} fn The function to call. The Record is passed as the first parameter.
19360 * Returning <em>false</em> aborts and exits the iteration.
19361 * @param {Object} scope (optional) The scope in which to call the function (defaults to the Record).
19363 each : function(fn, scope){
19364 this.data.each(fn, scope);
19368 * Gets all records modified since the last commit. Modified records are persisted across load operations
19369 * (e.g., during paging).
19370 * @return {Roo.data.Record[]} An array of Records containing outstanding modifications.
19372 getModifiedRecords : function(){
19373 return this.modified;
19377 createFilterFn : function(property, value, anyMatch){
19378 if(!value.exec){ // not a regex
19379 value = String(value);
19380 if(value.length == 0){
19383 value = new RegExp((anyMatch === true ? '' : '^') + Roo.escapeRe(value), "i");
19385 return function(r){
19386 return value.test(r.data[property]);
19391 * Sums the value of <i>property</i> for each record between start and end and returns the result.
19392 * @param {String} property A field on your records
19393 * @param {Number} start The record index to start at (defaults to 0)
19394 * @param {Number} end The last record index to include (defaults to length - 1)
19395 * @return {Number} The sum
19397 sum : function(property, start, end){
19398 var rs = this.data.items, v = 0;
19399 start = start || 0;
19400 end = (end || end === 0) ? end : rs.length-1;
19402 for(var i = start; i <= end; i++){
19403 v += (rs[i].data[property] || 0);
19409 * Filter the records by a specified property.
19410 * @param {String} field A field on your records
19411 * @param {String/RegExp} value Either a string that the field
19412 * should start with or a RegExp to test against the field
19413 * @param {Boolean} anyMatch True to match any part not just the beginning
19415 filter : function(property, value, anyMatch){
19416 var fn = this.createFilterFn(property, value, anyMatch);
19417 return fn ? this.filterBy(fn) : this.clearFilter();
19421 * Filter by a function. The specified function will be called with each
19422 * record in this data source. If the function returns true the record is included,
19423 * otherwise it is filtered.
19424 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
19425 * @param {Object} scope (optional) The scope of the function (defaults to this)
19427 filterBy : function(fn, scope){
19428 this.snapshot = this.snapshot || this.data;
19429 this.data = this.queryBy(fn, scope||this);
19430 this.fireEvent("datachanged", this);
19434 * Query the records by a specified property.
19435 * @param {String} field A field on your records
19436 * @param {String/RegExp} value Either a string that the field
19437 * should start with or a RegExp to test against the field
19438 * @param {Boolean} anyMatch True to match any part not just the beginning
19439 * @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
19441 query : function(property, value, anyMatch){
19442 var fn = this.createFilterFn(property, value, anyMatch);
19443 return fn ? this.queryBy(fn) : this.data.clone();
19447 * Query by a function. The specified function will be called with each
19448 * record in this data source. If the function returns true the record is included
19450 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
19451 * @param {Object} scope (optional) The scope of the function (defaults to this)
19452 @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
19454 queryBy : function(fn, scope){
19455 var data = this.snapshot || this.data;
19456 return data.filterBy(fn, scope||this);
19460 * Collects unique values for a particular dataIndex from this store.
19461 * @param {String} dataIndex The property to collect
19462 * @param {Boolean} allowNull (optional) Pass true to allow null, undefined or empty string values
19463 * @param {Boolean} bypassFilter (optional) Pass true to collect from all records, even ones which are filtered
19464 * @return {Array} An array of the unique values
19466 collect : function(dataIndex, allowNull, bypassFilter){
19467 var d = (bypassFilter === true && this.snapshot) ?
19468 this.snapshot.items : this.data.items;
19469 var v, sv, r = [], l = {};
19470 for(var i = 0, len = d.length; i < len; i++){
19471 v = d[i].data[dataIndex];
19473 if((allowNull || !Roo.isEmpty(v)) && !l[sv]){
19482 * Revert to a view of the Record cache with no filtering applied.
19483 * @param {Boolean} suppressEvent If true the filter is cleared silently without notifying listeners
19485 clearFilter : function(suppressEvent){
19486 if(this.snapshot && this.snapshot != this.data){
19487 this.data = this.snapshot;
19488 delete this.snapshot;
19489 if(suppressEvent !== true){
19490 this.fireEvent("datachanged", this);
19496 afterEdit : function(record){
19497 if(this.modified.indexOf(record) == -1){
19498 this.modified.push(record);
19500 this.fireEvent("update", this, record, Roo.data.Record.EDIT);
19504 afterReject : function(record){
19505 this.modified.remove(record);
19506 this.fireEvent("update", this, record, Roo.data.Record.REJECT);
19510 afterCommit : function(record){
19511 this.modified.remove(record);
19512 this.fireEvent("update", this, record, Roo.data.Record.COMMIT);
19516 * Commit all Records with outstanding changes. To handle updates for changes, subscribe to the
19517 * Store's "update" event, and perform updating when the third parameter is Roo.data.Record.COMMIT.
19519 commitChanges : function(){
19520 var m = this.modified.slice(0);
19521 this.modified = [];
19522 for(var i = 0, len = m.length; i < len; i++){
19528 * Cancel outstanding changes on all changed records.
19530 rejectChanges : function(){
19531 var m = this.modified.slice(0);
19532 this.modified = [];
19533 for(var i = 0, len = m.length; i < len; i++){
19538 onMetaChange : function(meta, rtype, o){
19539 this.recordType = rtype;
19540 this.fields = rtype.prototype.fields;
19541 delete this.snapshot;
19542 this.sortInfo = meta.sortInfo;
19543 this.modified = [];
19544 this.fireEvent('metachange', this, this.reader.meta);
19548 * Ext JS Library 1.1.1
19549 * Copyright(c) 2006-2007, Ext JS, LLC.
19551 * Originally Released Under LGPL - original licence link has changed is not relivant.
19554 * <script type="text/javascript">
19558 * @class Roo.data.SimpleStore
19559 * @extends Roo.data.Store
19560 * Small helper class to make creating Stores from Array data easier.
19561 * @cfg {Number} id The array index of the record id. Leave blank to auto generate ids.
19562 * @cfg {Array} fields An array of field definition objects, or field name strings.
19563 * @cfg {Array} data The multi-dimensional array of data
19565 * @param {Object} config
19567 Roo.data.SimpleStore = function(config){
19568 Roo.data.SimpleStore.superclass.constructor.call(this, {
19570 reader: new Roo.data.ArrayReader({
19573 Roo.data.Record.create(config.fields)
19575 proxy : new Roo.data.MemoryProxy(config.data)
19579 Roo.extend(Roo.data.SimpleStore, Roo.data.Store);/*
19581 * Ext JS Library 1.1.1
19582 * Copyright(c) 2006-2007, Ext JS, LLC.
19584 * Originally Released Under LGPL - original licence link has changed is not relivant.
19587 * <script type="text/javascript">
19592 * @extends Roo.data.Store
19593 * @class Roo.data.JsonStore
19594 * Small helper class to make creating Stores for JSON data easier. <br/>
19596 var store = new Roo.data.JsonStore({
19597 url: 'get-images.php',
19599 fields: ['name', 'url', {name:'size', type: 'float'}, {name:'lastmod', type:'date'}]
19602 * <b>Note: Although they are not listed, this class inherits all of the config options of Store,
19603 * JsonReader and HttpProxy (unless inline data is provided).</b>
19604 * @cfg {Array} fields An array of field definition objects, or field name strings.
19606 * @param {Object} config
19608 Roo.data.JsonStore = function(c){
19609 Roo.data.JsonStore.superclass.constructor.call(this, Roo.apply(c, {
19610 proxy: !c.data ? new Roo.data.HttpProxy({url: c.url}) : undefined,
19611 reader: new Roo.data.JsonReader(c, c.fields)
19614 Roo.extend(Roo.data.JsonStore, Roo.data.Store);/*
19616 * Ext JS Library 1.1.1
19617 * Copyright(c) 2006-2007, Ext JS, LLC.
19619 * Originally Released Under LGPL - original licence link has changed is not relivant.
19622 * <script type="text/javascript">
19626 Roo.data.Field = function(config){
19627 if(typeof config == "string"){
19628 config = {name: config};
19630 Roo.apply(this, config);
19633 this.type = "auto";
19636 var st = Roo.data.SortTypes;
19637 // named sortTypes are supported, here we look them up
19638 if(typeof this.sortType == "string"){
19639 this.sortType = st[this.sortType];
19642 // set default sortType for strings and dates
19643 if(!this.sortType){
19646 this.sortType = st.asUCString;
19649 this.sortType = st.asDate;
19652 this.sortType = st.none;
19657 var stripRe = /[\$,%]/g;
19659 // prebuilt conversion function for this field, instead of
19660 // switching every time we're reading a value
19662 var cv, dateFormat = this.dateFormat;
19667 cv = function(v){ return v; };
19670 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
19674 return v !== undefined && v !== null && v !== '' ?
19675 parseInt(String(v).replace(stripRe, ""), 10) : '';
19680 return v !== undefined && v !== null && v !== '' ?
19681 parseFloat(String(v).replace(stripRe, ""), 10) : '';
19686 cv = function(v){ return v === true || v === "true" || v == 1; };
19693 if(v instanceof Date){
19697 if(dateFormat == "timestamp"){
19698 return new Date(v*1000);
19700 return Date.parseDate(v, dateFormat);
19702 var parsed = Date.parse(v);
19703 return parsed ? new Date(parsed) : null;
19712 Roo.data.Field.prototype = {
19720 * Ext JS Library 1.1.1
19721 * Copyright(c) 2006-2007, Ext JS, LLC.
19723 * Originally Released Under LGPL - original licence link has changed is not relivant.
19726 * <script type="text/javascript">
19729 // Base class for reading structured data from a data source. This class is intended to be
19730 // extended (see ArrayReader, JsonReader and XmlReader) and should not be created directly.
19733 * @class Roo.data.DataReader
19734 * Base class for reading structured data from a data source. This class is intended to be
19735 * extended (see {Roo.data.ArrayReader}, {Roo.data.JsonReader} and {Roo.data.XmlReader}) and should not be created directly.
19738 Roo.data.DataReader = function(meta, recordType){
19742 this.recordType = recordType instanceof Array ?
19743 Roo.data.Record.create(recordType) : recordType;
19746 Roo.data.DataReader.prototype = {
19748 * Create an empty record
19749 * @param {Object} data (optional) - overlay some values
19750 * @return {Roo.data.Record} record created.
19752 newRow : function(d) {
19754 this.recordType.prototype.fields.each(function(c) {
19756 case 'int' : da[c.name] = 0; break;
19757 case 'date' : da[c.name] = new Date(); break;
19758 case 'float' : da[c.name] = 0.0; break;
19759 case 'boolean' : da[c.name] = false; break;
19760 default : da[c.name] = ""; break;
19764 return new this.recordType(Roo.apply(da, d));
19769 * Ext JS Library 1.1.1
19770 * Copyright(c) 2006-2007, Ext JS, LLC.
19772 * Originally Released Under LGPL - original licence link has changed is not relivant.
19775 * <script type="text/javascript">
19779 * @class Roo.data.DataProxy
19780 * @extends Roo.data.Observable
19781 * This class is an abstract base class for implementations which provide retrieval of
19782 * unformatted data objects.<br>
19784 * DataProxy implementations are usually used in conjunction with an implementation of Roo.data.DataReader
19785 * (of the appropriate type which knows how to parse the data object) to provide a block of
19786 * {@link Roo.data.Records} to an {@link Roo.data.Store}.<br>
19788 * Custom implementations must implement the load method as described in
19789 * {@link Roo.data.HttpProxy#load}.
19791 Roo.data.DataProxy = function(){
19794 * @event beforeload
19795 * Fires before a network request is made to retrieve a data object.
19796 * @param {Object} This DataProxy object.
19797 * @param {Object} params The params parameter to the load function.
19802 * Fires before the load method's callback is called.
19803 * @param {Object} This DataProxy object.
19804 * @param {Object} o The data object.
19805 * @param {Object} arg The callback argument object passed to the load function.
19809 * @event loadexception
19810 * Fires if an Exception occurs during data retrieval.
19811 * @param {Object} This DataProxy object.
19812 * @param {Object} o The data object.
19813 * @param {Object} arg The callback argument object passed to the load function.
19814 * @param {Object} e The Exception.
19816 loadexception : true
19818 Roo.data.DataProxy.superclass.constructor.call(this);
19821 Roo.extend(Roo.data.DataProxy, Roo.util.Observable);
19824 * @cfg {void} listeners (Not available) Constructor blocks listeners from being set
19828 * Ext JS Library 1.1.1
19829 * Copyright(c) 2006-2007, Ext JS, LLC.
19831 * Originally Released Under LGPL - original licence link has changed is not relivant.
19834 * <script type="text/javascript">
19837 * @class Roo.data.MemoryProxy
19838 * An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
19839 * to the Reader when its load method is called.
19841 * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
19843 Roo.data.MemoryProxy = function(data){
19847 Roo.data.MemoryProxy.superclass.constructor.call(this);
19851 Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
19853 * Load data from the requested source (in this case an in-memory
19854 * data object passed to the constructor), read the data object into
19855 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
19856 * process that block using the passed callback.
19857 * @param {Object} params This parameter is not used by the MemoryProxy class.
19858 * @param {Roo.data.DataReader} reader The Reader object which converts the data
19859 * object into a block of Roo.data.Records.
19860 * @param {Function} callback The function into which to pass the block of Roo.data.records.
19861 * The function must be passed <ul>
19862 * <li>The Record block object</li>
19863 * <li>The "arg" argument from the load function</li>
19864 * <li>A boolean success indicator</li>
19866 * @param {Object} scope The scope in which to call the callback
19867 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
19869 load : function(params, reader, callback, scope, arg){
19870 params = params || {};
19873 result = reader.readRecords(this.data);
19875 this.fireEvent("loadexception", this, arg, null, e);
19876 callback.call(scope, null, arg, false);
19879 callback.call(scope, result, arg, true);
19883 update : function(params, records){
19888 * Ext JS Library 1.1.1
19889 * Copyright(c) 2006-2007, Ext JS, LLC.
19891 * Originally Released Under LGPL - original licence link has changed is not relivant.
19894 * <script type="text/javascript">
19897 * @class Roo.data.HttpProxy
19898 * @extends Roo.data.DataProxy
19899 * An implementation of {@link Roo.data.DataProxy} that reads a data object from an {@link Roo.data.Connection} object
19900 * configured to reference a certain URL.<br><br>
19902 * <em>Note that this class cannot be used to retrieve data from a domain other than the domain
19903 * from which the running page was served.<br><br>
19905 * For cross-domain access to remote data, use an {@link Roo.data.ScriptTagProxy}.</em><br><br>
19907 * Be aware that to enable the browser to parse an XML document, the server must set
19908 * the Content-Type header in the HTTP response to "text/xml".
19910 * @param {Object} conn Connection config options to add to each request (e.g. {url: 'foo.php'} or
19911 * an {@link Roo.data.Connection} object. If a Connection config is passed, the singleton {@link Roo.Ajax} object
19912 * will be used to make the request.
19914 Roo.data.HttpProxy = function(conn){
19915 Roo.data.HttpProxy.superclass.constructor.call(this);
19916 // is conn a conn config or a real conn?
19918 this.useAjax = !conn || !conn.events;
19922 Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
19923 // thse are take from connection...
19926 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
19929 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
19930 * extra parameters to each request made by this object. (defaults to undefined)
19933 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
19934 * to each request made by this object. (defaults to undefined)
19937 * @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)
19940 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
19943 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
19949 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
19953 * Return the {@link Roo.data.Connection} object being used by this Proxy.
19954 * @return {Connection} The Connection object. This object may be used to subscribe to events on
19955 * a finer-grained basis than the DataProxy events.
19957 getConnection : function(){
19958 return this.useAjax ? Roo.Ajax : this.conn;
19962 * Load data from the configured {@link Roo.data.Connection}, read the data object into
19963 * a block of Roo.data.Records using the passed {@link Roo.data.DataReader} implementation, and
19964 * process that block using the passed callback.
19965 * @param {Object} params An object containing properties which are to be used as HTTP parameters
19966 * for the request to the remote server.
19967 * @param {Roo.data.DataReader} reader The Reader object which converts the data
19968 * object into a block of Roo.data.Records.
19969 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
19970 * The function must be passed <ul>
19971 * <li>The Record block object</li>
19972 * <li>The "arg" argument from the load function</li>
19973 * <li>A boolean success indicator</li>
19975 * @param {Object} scope The scope in which to call the callback
19976 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
19978 load : function(params, reader, callback, scope, arg){
19979 if(this.fireEvent("beforeload", this, params) !== false){
19981 params : params || {},
19983 callback : callback,
19988 callback : this.loadResponse,
19992 Roo.applyIf(o, this.conn);
19993 if(this.activeRequest){
19994 Roo.Ajax.abort(this.activeRequest);
19996 this.activeRequest = Roo.Ajax.request(o);
19998 this.conn.request(o);
20001 callback.call(scope||this, null, arg, false);
20006 loadResponse : function(o, success, response){
20007 delete this.activeRequest;
20009 this.fireEvent("loadexception", this, o, response);
20010 o.request.callback.call(o.request.scope, null, o.request.arg, false);
20015 result = o.reader.read(response);
20017 this.fireEvent("loadexception", this, o, response, e);
20018 o.request.callback.call(o.request.scope, null, o.request.arg, false);
20022 this.fireEvent("load", this, o, o.request.arg);
20023 o.request.callback.call(o.request.scope, result, o.request.arg, true);
20027 update : function(dataSet){
20032 updateResponse : function(dataSet){
20037 * Ext JS Library 1.1.1
20038 * Copyright(c) 2006-2007, Ext JS, LLC.
20040 * Originally Released Under LGPL - original licence link has changed is not relivant.
20043 * <script type="text/javascript">
20047 * @class Roo.data.ScriptTagProxy
20048 * An implementation of Roo.data.DataProxy that reads a data object from a URL which may be in a domain
20049 * other than the originating domain of the running page.<br><br>
20051 * <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
20052 * of the running page, you must use this class, rather than DataProxy.</em><br><br>
20054 * The content passed back from a server resource requested by a ScriptTagProxy is executable JavaScript
20055 * source code that is used as the source inside a <script> tag.<br><br>
20057 * In order for the browser to process the returned data, the server must wrap the data object
20058 * with a call to a callback function, the name of which is passed as a parameter by the ScriptTagProxy.
20059 * Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy
20060 * depending on whether the callback name was passed:
20063 boolean scriptTag = false;
20064 String cb = request.getParameter("callback");
20067 response.setContentType("text/javascript");
20069 response.setContentType("application/x-json");
20071 Writer out = response.getWriter();
20073 out.write(cb + "(");
20075 out.print(dataBlock.toJsonString());
20082 * @param {Object} config A configuration object.
20084 Roo.data.ScriptTagProxy = function(config){
20085 Roo.data.ScriptTagProxy.superclass.constructor.call(this);
20086 Roo.apply(this, config);
20087 this.head = document.getElementsByTagName("head")[0];
20090 Roo.data.ScriptTagProxy.TRANS_ID = 1000;
20092 Roo.extend(Roo.data.ScriptTagProxy, Roo.data.DataProxy, {
20094 * @cfg {String} url The URL from which to request the data object.
20097 * @cfg {Number} timeout (Optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
20101 * @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells
20102 * the server the name of the callback function set up by the load call to process the returned data object.
20103 * Defaults to "callback".<p>The server-side processing must read this parameter value, and generate
20104 * javascript output which calls this named function passing the data object as its only parameter.
20106 callbackParam : "callback",
20108 * @cfg {Boolean} nocache (Optional) Defaults to true. Disable cacheing by adding a unique parameter
20109 * name to the request.
20114 * Load data from the configured URL, read the data object into
20115 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
20116 * process that block using the passed callback.
20117 * @param {Object} params An object containing properties which are to be used as HTTP parameters
20118 * for the request to the remote server.
20119 * @param {Roo.data.DataReader} reader The Reader object which converts the data
20120 * object into a block of Roo.data.Records.
20121 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
20122 * The function must be passed <ul>
20123 * <li>The Record block object</li>
20124 * <li>The "arg" argument from the load function</li>
20125 * <li>A boolean success indicator</li>
20127 * @param {Object} scope The scope in which to call the callback
20128 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
20130 load : function(params, reader, callback, scope, arg){
20131 if(this.fireEvent("beforeload", this, params) !== false){
20133 var p = Roo.urlEncode(Roo.apply(params, this.extraParams));
20135 var url = this.url;
20136 url += (url.indexOf("?") != -1 ? "&" : "?") + p;
20138 url += "&_dc=" + (new Date().getTime());
20140 var transId = ++Roo.data.ScriptTagProxy.TRANS_ID;
20143 cb : "stcCallback"+transId,
20144 scriptId : "stcScript"+transId,
20148 callback : callback,
20154 window[trans.cb] = function(o){
20155 conn.handleResponse(o, trans);
20158 url += String.format("&{0}={1}", this.callbackParam, trans.cb);
20160 if(this.autoAbort !== false){
20164 trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
20166 var script = document.createElement("script");
20167 script.setAttribute("src", url);
20168 script.setAttribute("type", "text/javascript");
20169 script.setAttribute("id", trans.scriptId);
20170 this.head.appendChild(script);
20172 this.trans = trans;
20174 callback.call(scope||this, null, arg, false);
20179 isLoading : function(){
20180 return this.trans ? true : false;
20184 * Abort the current server request.
20186 abort : function(){
20187 if(this.isLoading()){
20188 this.destroyTrans(this.trans);
20193 destroyTrans : function(trans, isLoaded){
20194 this.head.removeChild(document.getElementById(trans.scriptId));
20195 clearTimeout(trans.timeoutId);
20197 window[trans.cb] = undefined;
20199 delete window[trans.cb];
20202 // if hasn't been loaded, wait for load to remove it to prevent script error
20203 window[trans.cb] = function(){
20204 window[trans.cb] = undefined;
20206 delete window[trans.cb];
20213 handleResponse : function(o, trans){
20214 this.trans = false;
20215 this.destroyTrans(trans, true);
20218 result = trans.reader.readRecords(o);
20220 this.fireEvent("loadexception", this, o, trans.arg, e);
20221 trans.callback.call(trans.scope||window, null, trans.arg, false);
20224 this.fireEvent("load", this, o, trans.arg);
20225 trans.callback.call(trans.scope||window, result, trans.arg, true);
20229 handleFailure : function(trans){
20230 this.trans = false;
20231 this.destroyTrans(trans, false);
20232 this.fireEvent("loadexception", this, null, trans.arg);
20233 trans.callback.call(trans.scope||window, null, trans.arg, false);
20237 * Ext JS Library 1.1.1
20238 * Copyright(c) 2006-2007, Ext JS, LLC.
20240 * Originally Released Under LGPL - original licence link has changed is not relivant.
20243 * <script type="text/javascript">
20247 * @class Roo.data.JsonReader
20248 * @extends Roo.data.DataReader
20249 * Data reader class to create an Array of Roo.data.Record objects from a JSON response
20250 * based on mappings in a provided Roo.data.Record constructor.
20254 var RecordDef = Roo.data.Record.create([
20255 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
20256 {name: 'occupation'} // This field will use "occupation" as the mapping.
20258 var myReader = new Roo.data.JsonReader({
20259 totalProperty: "results", // The property which contains the total dataset size (optional)
20260 root: "rows", // The property which contains an Array of row objects
20261 id: "id" // The property within each row object that provides an ID for the record (optional)
20265 * This would consume a JSON file like this:
20267 { 'results': 2, 'rows': [
20268 { 'id': 1, 'name': 'Bill', occupation: 'Gardener' },
20269 { 'id': 2, 'name': 'Ben', occupation: 'Horticulturalist' } ]
20272 * @cfg {String} totalProperty Name of the property from which to retrieve the total number of records
20273 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
20274 * paged from the remote server.
20275 * @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
20276 * @cfg {String} root name of the property which contains the Array of row objects.
20277 * @cfg {String} id Name of the property within a row object that contains a record identifier value.
20279 * Create a new JsonReader
20280 * @param {Object} meta Metadata configuration options
20281 * @param {Object} recordType Either an Array of field definition objects,
20282 * or an {@link Roo.data.Record} object created using {@link Roo.data.Record#create}.
20284 Roo.data.JsonReader = function(meta, recordType){
20287 // set some defaults:
20288 Roo.applyIf(meta, {
20289 totalProperty: 'total',
20290 successProperty : 'success',
20295 Roo.data.JsonReader.superclass.constructor.call(this, meta, recordType||meta.fields);
20297 Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
20299 * This method is only used by a DataProxy which has retrieved data from a remote server.
20300 * @param {Object} response The XHR object which contains the JSON data in its responseText.
20301 * @return {Object} data A data block which is used by an Roo.data.Store object as
20302 * a cache of Roo.data.Records.
20304 read : function(response){
20305 var json = response.responseText;
20307 var o = eval("("+json+")");
20309 throw {message: "JsonReader.read: Json object not found"};
20314 this.meta = o.metaData;
20315 this.recordType = Roo.data.Record.create(o.metaData.fields);
20316 this.onMetaChange(this.meta, this.recordType, o);
20318 return this.readRecords(o);
20321 // private function a store will implement
20322 onMetaChange : function(meta, recordType, o){
20329 simpleAccess: function(obj, subsc) {
20336 getJsonAccessor: function(){
20338 return function(expr) {
20340 return(re.test(expr))
20341 ? new Function("obj", "return obj." + expr)
20346 return Roo.emptyFn;
20351 * Create a data block containing Roo.data.Records from an XML document.
20352 * @param {Object} o An object which contains an Array of row objects in the property specified
20353 * in the config as 'root, and optionally a property, specified in the config as 'totalProperty'
20354 * which contains the total size of the dataset.
20355 * @return {Object} data A data block which is used by an Roo.data.Store object as
20356 * a cache of Roo.data.Records.
20358 readRecords : function(o){
20360 * After any data loads, the raw JSON data is available for further custom processing.
20364 var s = this.meta, Record = this.recordType,
20365 f = Record.prototype.fields, fi = f.items, fl = f.length;
20367 // Generate extraction functions for the totalProperty, the root, the id, and for each field
20369 if(s.totalProperty) {
20370 this.getTotal = this.getJsonAccessor(s.totalProperty);
20372 if(s.successProperty) {
20373 this.getSuccess = this.getJsonAccessor(s.successProperty);
20375 this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
20377 var g = this.getJsonAccessor(s.id);
20378 this.getId = function(rec) {
20380 return (r === undefined || r === "") ? null : r;
20383 this.getId = function(){return null;};
20386 for(var i = 0; i < fl; i++){
20388 var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
20389 this.ef[i] = this.getJsonAccessor(map);
20393 var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
20394 if(s.totalProperty){
20395 var v = parseInt(this.getTotal(o), 10);
20400 if(s.successProperty){
20401 var v = this.getSuccess(o);
20402 if(v === false || v === 'false'){
20407 for(var i = 0; i < c; i++){
20410 var id = this.getId(n);
20411 for(var j = 0; j < fl; j++){
20413 var v = this.ef[j](n);
20414 values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
20416 var record = new Record(values, id);
20418 records[i] = record;
20423 totalRecords : totalRecords
20428 * Ext JS Library 1.1.1
20429 * Copyright(c) 2006-2007, Ext JS, LLC.
20431 * Originally Released Under LGPL - original licence link has changed is not relivant.
20434 * <script type="text/javascript">
20438 * @class Roo.data.XmlReader
20439 * @extends Roo.data.DataReader
20440 * Data reader class to create an Array of {@link Roo.data.Record} objects from an XML document
20441 * based on mappings in a provided Roo.data.Record constructor.<br><br>
20443 * <em>Note that in order for the browser to parse a returned XML document, the Content-Type
20444 * header in the HTTP response must be set to "text/xml".</em>
20448 var RecordDef = Roo.data.Record.create([
20449 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
20450 {name: 'occupation'} // This field will use "occupation" as the mapping.
20452 var myReader = new Roo.data.XmlReader({
20453 totalRecords: "results", // The element which contains the total dataset size (optional)
20454 record: "row", // The repeated element which contains row information
20455 id: "id" // The element within the row that provides an ID for the record (optional)
20459 * This would consume an XML file like this:
20463 <results>2</results>
20466 <name>Bill</name>
20467 <occupation>Gardener</occupation>
20471 <name>Ben</name>
20472 <occupation>Horticulturalist</occupation>
20476 * @cfg {String} totalRecords The DomQuery path from which to retrieve the total number of records
20477 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
20478 * paged from the remote server.
20479 * @cfg {String} record The DomQuery path to the repeated element which contains record information.
20480 * @cfg {String} success The DomQuery path to the success attribute used by forms.
20481 * @cfg {String} id The DomQuery path relative from the record element to the element that contains
20482 * a record identifier value.
20484 * Create a new XmlReader
20485 * @param {Object} meta Metadata configuration options
20486 * @param {Mixed} recordType The definition of the data record type to produce. This can be either a valid
20487 * Record subclass created with {@link Roo.data.Record#create}, or an array of objects with which to call
20488 * Roo.data.Record.create. See the {@link Roo.data.Record} class for more details.
20490 Roo.data.XmlReader = function(meta, recordType){
20492 Roo.data.XmlReader.superclass.constructor.call(this, meta, recordType||meta.fields);
20494 Roo.extend(Roo.data.XmlReader, Roo.data.DataReader, {
20496 * This method is only used by a DataProxy which has retrieved data from a remote server.
20497 * @param {Object} response The XHR object which contains the parsed XML document. The response is expected
20498 * to contain a method called 'responseXML' that returns an XML document object.
20499 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
20500 * a cache of Roo.data.Records.
20502 read : function(response){
20503 var doc = response.responseXML;
20505 throw {message: "XmlReader.read: XML Document not available"};
20507 return this.readRecords(doc);
20511 * Create a data block containing Roo.data.Records from an XML document.
20512 * @param {Object} doc A parsed XML document.
20513 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
20514 * a cache of Roo.data.Records.
20516 readRecords : function(doc){
20518 * After any data loads/reads, the raw XML Document is available for further custom processing.
20519 * @type XMLDocument
20521 this.xmlData = doc;
20522 var root = doc.documentElement || doc;
20523 var q = Roo.DomQuery;
20524 var recordType = this.recordType, fields = recordType.prototype.fields;
20525 var sid = this.meta.id;
20526 var totalRecords = 0, success = true;
20527 if(this.meta.totalRecords){
20528 totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
20531 if(this.meta.success){
20532 var sv = q.selectValue(this.meta.success, root, true);
20533 success = sv !== false && sv !== 'false';
20536 var ns = q.select(this.meta.record, root);
20537 for(var i = 0, len = ns.length; i < len; i++) {
20540 var id = sid ? q.selectValue(sid, n) : undefined;
20541 for(var j = 0, jlen = fields.length; j < jlen; j++){
20542 var f = fields.items[j];
20543 var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
20545 values[f.name] = v;
20547 var record = new recordType(values, id);
20549 records[records.length] = record;
20555 totalRecords : totalRecords || records.length
20560 * Ext JS Library 1.1.1
20561 * Copyright(c) 2006-2007, Ext JS, LLC.
20563 * Originally Released Under LGPL - original licence link has changed is not relivant.
20566 * <script type="text/javascript">
20570 * @class Roo.data.ArrayReader
20571 * @extends Roo.data.DataReader
20572 * Data reader class to create an Array of Roo.data.Record objects from an Array.
20573 * Each element of that Array represents a row of data fields. The
20574 * fields are pulled into a Record object using as a subscript, the <em>mapping</em> property
20575 * of the field definition if it exists, or the field's ordinal position in the definition.<br>
20579 var RecordDef = Roo.data.Record.create([
20580 {name: 'name', mapping: 1}, // "mapping" only needed if an "id" field is present which
20581 {name: 'occupation', mapping: 2} // precludes using the ordinal position as the index.
20583 var myReader = new Roo.data.ArrayReader({
20584 id: 0 // The subscript within row Array that provides an ID for the Record (optional)
20588 * This would consume an Array like this:
20590 [ [1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist'] ]
20592 * @cfg {String} id (optional) The subscript within row Array that provides an ID for the Record
20594 * Create a new JsonReader
20595 * @param {Object} meta Metadata configuration options.
20596 * @param {Object} recordType Either an Array of field definition objects
20597 * as specified to {@link Roo.data.Record#create},
20598 * or an {@link Roo.data.Record} object
20599 * created using {@link Roo.data.Record#create}.
20601 Roo.data.ArrayReader = function(meta, recordType){
20602 Roo.data.ArrayReader.superclass.constructor.call(this, meta, recordType);
20605 Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
20607 * Create a data block containing Roo.data.Records from an XML document.
20608 * @param {Object} o An Array of row objects which represents the dataset.
20609 * @return {Object} data A data block which is used by an Roo.data.Store object as
20610 * a cache of Roo.data.Records.
20612 readRecords : function(o){
20613 var sid = this.meta ? this.meta.id : null;
20614 var recordType = this.recordType, fields = recordType.prototype.fields;
20617 for(var i = 0; i < root.length; i++){
20620 var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
20621 for(var j = 0, jlen = fields.length; j < jlen; j++){
20622 var f = fields.items[j];
20623 var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
20624 var v = n[k] !== undefined ? n[k] : f.defaultValue;
20626 values[f.name] = v;
20628 var record = new recordType(values, id);
20630 records[records.length] = record;
20634 totalRecords : records.length
20639 * Ext JS Library 1.1.1
20640 * Copyright(c) 2006-2007, Ext JS, LLC.
20642 * Originally Released Under LGPL - original licence link has changed is not relivant.
20645 * <script type="text/javascript">
20650 * @class Roo.data.Tree
20651 * @extends Roo.util.Observable
20652 * Represents a tree data structure and bubbles all the events for its nodes. The nodes
20653 * in the tree have most standard DOM functionality.
20655 * @param {Node} root (optional) The root node
20657 Roo.data.Tree = function(root){
20658 this.nodeHash = {};
20660 * The root node for this tree
20665 this.setRootNode(root);
20670 * Fires when a new child node is appended to a node in this tree.
20671 * @param {Tree} tree The owner tree
20672 * @param {Node} parent The parent node
20673 * @param {Node} node The newly appended node
20674 * @param {Number} index The index of the newly appended node
20679 * Fires when a child node is removed from a node in this tree.
20680 * @param {Tree} tree The owner tree
20681 * @param {Node} parent The parent node
20682 * @param {Node} node The child node removed
20687 * Fires when a node is moved to a new location in the tree
20688 * @param {Tree} tree The owner tree
20689 * @param {Node} node The node moved
20690 * @param {Node} oldParent The old parent of this node
20691 * @param {Node} newParent The new parent of this node
20692 * @param {Number} index The index it was moved to
20697 * Fires when a new child node is inserted in a node in this tree.
20698 * @param {Tree} tree The owner tree
20699 * @param {Node} parent The parent node
20700 * @param {Node} node The child node inserted
20701 * @param {Node} refNode The child node the node was inserted before
20705 * @event beforeappend
20706 * Fires before a new child is appended to a node in this tree, return false to cancel the append.
20707 * @param {Tree} tree The owner tree
20708 * @param {Node} parent The parent node
20709 * @param {Node} node The child node to be appended
20711 "beforeappend" : true,
20713 * @event beforeremove
20714 * Fires before a child is removed from a node in this tree, return false to cancel the remove.
20715 * @param {Tree} tree The owner tree
20716 * @param {Node} parent The parent node
20717 * @param {Node} node The child node to be removed
20719 "beforeremove" : true,
20721 * @event beforemove
20722 * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
20723 * @param {Tree} tree The owner tree
20724 * @param {Node} node The node being moved
20725 * @param {Node} oldParent The parent of the node
20726 * @param {Node} newParent The new parent the node is moving to
20727 * @param {Number} index The index it is being moved to
20729 "beforemove" : true,
20731 * @event beforeinsert
20732 * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
20733 * @param {Tree} tree The owner tree
20734 * @param {Node} parent The parent node
20735 * @param {Node} node The child node to be inserted
20736 * @param {Node} refNode The child node the node is being inserted before
20738 "beforeinsert" : true
20741 Roo.data.Tree.superclass.constructor.call(this);
20744 Roo.extend(Roo.data.Tree, Roo.util.Observable, {
20745 pathSeparator: "/",
20747 proxyNodeEvent : function(){
20748 return this.fireEvent.apply(this, arguments);
20752 * Returns the root node for this tree.
20755 getRootNode : function(){
20760 * Sets the root node for this tree.
20761 * @param {Node} node
20764 setRootNode : function(node){
20766 node.ownerTree = this;
20767 node.isRoot = true;
20768 this.registerNode(node);
20773 * Gets a node in this tree by its id.
20774 * @param {String} id
20777 getNodeById : function(id){
20778 return this.nodeHash[id];
20781 registerNode : function(node){
20782 this.nodeHash[node.id] = node;
20785 unregisterNode : function(node){
20786 delete this.nodeHash[node.id];
20789 toString : function(){
20790 return "[Tree"+(this.id?" "+this.id:"")+"]";
20795 * @class Roo.data.Node
20796 * @extends Roo.util.Observable
20797 * @cfg {Boolean} leaf true if this node is a leaf and does not have children
20798 * @cfg {String} id The id for this node. If one is not specified, one is generated.
20800 * @param {Object} attributes The attributes/config for the node
20802 Roo.data.Node = function(attributes){
20804 * The attributes supplied for the node. You can use this property to access any custom attributes you supplied.
20807 this.attributes = attributes || {};
20808 this.leaf = this.attributes.leaf;
20810 * The node id. @type String
20812 this.id = this.attributes.id;
20814 this.id = Roo.id(null, "ynode-");
20815 this.attributes.id = this.id;
20818 * All child nodes of this node. @type Array
20820 this.childNodes = [];
20821 if(!this.childNodes.indexOf){ // indexOf is a must
20822 this.childNodes.indexOf = function(o){
20823 for(var i = 0, len = this.length; i < len; i++){
20824 if(this[i] == o) return i;
20830 * The parent node for this node. @type Node
20832 this.parentNode = null;
20834 * The first direct child node of this node, or null if this node has no child nodes. @type Node
20836 this.firstChild = null;
20838 * The last direct child node of this node, or null if this node has no child nodes. @type Node
20840 this.lastChild = null;
20842 * The node immediately preceding this node in the tree, or null if there is no sibling node. @type Node
20844 this.previousSibling = null;
20846 * The node immediately following this node in the tree, or null if there is no sibling node. @type Node
20848 this.nextSibling = null;
20853 * Fires when a new child node is appended
20854 * @param {Tree} tree The owner tree
20855 * @param {Node} this This node
20856 * @param {Node} node The newly appended node
20857 * @param {Number} index The index of the newly appended node
20862 * Fires when a child node is removed
20863 * @param {Tree} tree The owner tree
20864 * @param {Node} this This node
20865 * @param {Node} node The removed node
20870 * Fires when this node is moved to a new location in the tree
20871 * @param {Tree} tree The owner tree
20872 * @param {Node} this This node
20873 * @param {Node} oldParent The old parent of this node
20874 * @param {Node} newParent The new parent of this node
20875 * @param {Number} index The index it was moved to
20880 * Fires when a new child node is inserted.
20881 * @param {Tree} tree The owner tree
20882 * @param {Node} this This node
20883 * @param {Node} node The child node inserted
20884 * @param {Node} refNode The child node the node was inserted before
20888 * @event beforeappend
20889 * Fires before a new child is appended, return false to cancel the append.
20890 * @param {Tree} tree The owner tree
20891 * @param {Node} this This node
20892 * @param {Node} node The child node to be appended
20894 "beforeappend" : true,
20896 * @event beforeremove
20897 * Fires before a child is removed, return false to cancel the remove.
20898 * @param {Tree} tree The owner tree
20899 * @param {Node} this This node
20900 * @param {Node} node The child node to be removed
20902 "beforeremove" : true,
20904 * @event beforemove
20905 * Fires before this node is moved to a new location in the tree. Return false to cancel the move.
20906 * @param {Tree} tree The owner tree
20907 * @param {Node} this This node
20908 * @param {Node} oldParent The parent of this node
20909 * @param {Node} newParent The new parent this node is moving to
20910 * @param {Number} index The index it is being moved to
20912 "beforemove" : true,
20914 * @event beforeinsert
20915 * Fires before a new child is inserted, return false to cancel the insert.
20916 * @param {Tree} tree The owner tree
20917 * @param {Node} this This node
20918 * @param {Node} node The child node to be inserted
20919 * @param {Node} refNode The child node the node is being inserted before
20921 "beforeinsert" : true
20923 this.listeners = this.attributes.listeners;
20924 Roo.data.Node.superclass.constructor.call(this);
20927 Roo.extend(Roo.data.Node, Roo.util.Observable, {
20928 fireEvent : function(evtName){
20929 // first do standard event for this node
20930 if(Roo.data.Node.superclass.fireEvent.apply(this, arguments) === false){
20933 // then bubble it up to the tree if the event wasn't cancelled
20934 var ot = this.getOwnerTree();
20936 if(ot.proxyNodeEvent.apply(ot, arguments) === false){
20944 * Returns true if this node is a leaf
20945 * @return {Boolean}
20947 isLeaf : function(){
20948 return this.leaf === true;
20952 setFirstChild : function(node){
20953 this.firstChild = node;
20957 setLastChild : function(node){
20958 this.lastChild = node;
20963 * Returns true if this node is the last child of its parent
20964 * @return {Boolean}
20966 isLast : function(){
20967 return (!this.parentNode ? true : this.parentNode.lastChild == this);
20971 * Returns true if this node is the first child of its parent
20972 * @return {Boolean}
20974 isFirst : function(){
20975 return (!this.parentNode ? true : this.parentNode.firstChild == this);
20978 hasChildNodes : function(){
20979 return !this.isLeaf() && this.childNodes.length > 0;
20983 * Insert node(s) as the last child node of this node.
20984 * @param {Node/Array} node The node or Array of nodes to append
20985 * @return {Node} The appended node if single append, or null if an array was passed
20987 appendChild : function(node){
20989 if(node instanceof Array){
20991 }else if(arguments.length > 1){
20994 // if passed an array or multiple args do them one by one
20996 for(var i = 0, len = multi.length; i < len; i++) {
20997 this.appendChild(multi[i]);
21000 if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
21003 var index = this.childNodes.length;
21004 var oldParent = node.parentNode;
21005 // it's a move, make sure we move it cleanly
21007 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
21010 oldParent.removeChild(node);
21012 index = this.childNodes.length;
21014 this.setFirstChild(node);
21016 this.childNodes.push(node);
21017 node.parentNode = this;
21018 var ps = this.childNodes[index-1];
21020 node.previousSibling = ps;
21021 ps.nextSibling = node;
21023 node.previousSibling = null;
21025 node.nextSibling = null;
21026 this.setLastChild(node);
21027 node.setOwnerTree(this.getOwnerTree());
21028 this.fireEvent("append", this.ownerTree, this, node, index);
21030 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
21037 * Removes a child node from this node.
21038 * @param {Node} node The node to remove
21039 * @return {Node} The removed node
21041 removeChild : function(node){
21042 var index = this.childNodes.indexOf(node);
21046 if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
21050 // remove it from childNodes collection
21051 this.childNodes.splice(index, 1);
21054 if(node.previousSibling){
21055 node.previousSibling.nextSibling = node.nextSibling;
21057 if(node.nextSibling){
21058 node.nextSibling.previousSibling = node.previousSibling;
21061 // update child refs
21062 if(this.firstChild == node){
21063 this.setFirstChild(node.nextSibling);
21065 if(this.lastChild == node){
21066 this.setLastChild(node.previousSibling);
21069 node.setOwnerTree(null);
21070 // clear any references from the node
21071 node.parentNode = null;
21072 node.previousSibling = null;
21073 node.nextSibling = null;
21074 this.fireEvent("remove", this.ownerTree, this, node);
21079 * Inserts the first node before the second node in this nodes childNodes collection.
21080 * @param {Node} node The node to insert
21081 * @param {Node} refNode The node to insert before (if null the node is appended)
21082 * @return {Node} The inserted node
21084 insertBefore : function(node, refNode){
21085 if(!refNode){ // like standard Dom, refNode can be null for append
21086 return this.appendChild(node);
21089 if(node == refNode){
21093 if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
21096 var index = this.childNodes.indexOf(refNode);
21097 var oldParent = node.parentNode;
21098 var refIndex = index;
21100 // when moving internally, indexes will change after remove
21101 if(oldParent == this && this.childNodes.indexOf(node) < index){
21105 // it's a move, make sure we move it cleanly
21107 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
21110 oldParent.removeChild(node);
21113 this.setFirstChild(node);
21115 this.childNodes.splice(refIndex, 0, node);
21116 node.parentNode = this;
21117 var ps = this.childNodes[refIndex-1];
21119 node.previousSibling = ps;
21120 ps.nextSibling = node;
21122 node.previousSibling = null;
21124 node.nextSibling = refNode;
21125 refNode.previousSibling = node;
21126 node.setOwnerTree(this.getOwnerTree());
21127 this.fireEvent("insert", this.ownerTree, this, node, refNode);
21129 node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
21135 * Returns the child node at the specified index.
21136 * @param {Number} index
21139 item : function(index){
21140 return this.childNodes[index];
21144 * Replaces one child node in this node with another.
21145 * @param {Node} newChild The replacement node
21146 * @param {Node} oldChild The node to replace
21147 * @return {Node} The replaced node
21149 replaceChild : function(newChild, oldChild){
21150 this.insertBefore(newChild, oldChild);
21151 this.removeChild(oldChild);
21156 * Returns the index of a child node
21157 * @param {Node} node
21158 * @return {Number} The index of the node or -1 if it was not found
21160 indexOf : function(child){
21161 return this.childNodes.indexOf(child);
21165 * Returns the tree this node is in.
21168 getOwnerTree : function(){
21169 // if it doesn't have one, look for one
21170 if(!this.ownerTree){
21174 this.ownerTree = p.ownerTree;
21180 return this.ownerTree;
21184 * Returns depth of this node (the root node has a depth of 0)
21187 getDepth : function(){
21190 while(p.parentNode){
21198 setOwnerTree : function(tree){
21199 // if it's move, we need to update everyone
21200 if(tree != this.ownerTree){
21201 if(this.ownerTree){
21202 this.ownerTree.unregisterNode(this);
21204 this.ownerTree = tree;
21205 var cs = this.childNodes;
21206 for(var i = 0, len = cs.length; i < len; i++) {
21207 cs[i].setOwnerTree(tree);
21210 tree.registerNode(this);
21216 * Returns the path for this node. The path can be used to expand or select this node programmatically.
21217 * @param {String} attr (optional) The attr to use for the path (defaults to the node's id)
21218 * @return {String} The path
21220 getPath : function(attr){
21221 attr = attr || "id";
21222 var p = this.parentNode;
21223 var b = [this.attributes[attr]];
21225 b.unshift(p.attributes[attr]);
21228 var sep = this.getOwnerTree().pathSeparator;
21229 return sep + b.join(sep);
21233 * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
21234 * function call will be the scope provided or the current node. The arguments to the function
21235 * will be the args provided or the current node. If the function returns false at any point,
21236 * the bubble is stopped.
21237 * @param {Function} fn The function to call
21238 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21239 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21241 bubble : function(fn, scope, args){
21244 if(fn.call(scope || p, args || p) === false){
21252 * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
21253 * function call will be the scope provided or the current node. The arguments to the function
21254 * will be the args provided or the current node. If the function returns false at any point,
21255 * the cascade is stopped on that branch.
21256 * @param {Function} fn The function to call
21257 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21258 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21260 cascade : function(fn, scope, args){
21261 if(fn.call(scope || this, args || this) !== false){
21262 var cs = this.childNodes;
21263 for(var i = 0, len = cs.length; i < len; i++) {
21264 cs[i].cascade(fn, scope, args);
21270 * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of
21271 * function call will be the scope provided or the current node. The arguments to the function
21272 * will be the args provided or the current node. If the function returns false at any point,
21273 * the iteration stops.
21274 * @param {Function} fn The function to call
21275 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21276 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21278 eachChild : function(fn, scope, args){
21279 var cs = this.childNodes;
21280 for(var i = 0, len = cs.length; i < len; i++) {
21281 if(fn.call(scope || this, args || cs[i]) === false){
21288 * Finds the first child that has the attribute with the specified value.
21289 * @param {String} attribute The attribute name
21290 * @param {Mixed} value The value to search for
21291 * @return {Node} The found child or null if none was found
21293 findChild : function(attribute, value){
21294 var cs = this.childNodes;
21295 for(var i = 0, len = cs.length; i < len; i++) {
21296 if(cs[i].attributes[attribute] == value){
21304 * Finds the first child by a custom function. The child matches if the function passed
21306 * @param {Function} fn
21307 * @param {Object} scope (optional)
21308 * @return {Node} The found child or null if none was found
21310 findChildBy : function(fn, scope){
21311 var cs = this.childNodes;
21312 for(var i = 0, len = cs.length; i < len; i++) {
21313 if(fn.call(scope||cs[i], cs[i]) === true){
21321 * Sorts this nodes children using the supplied sort function
21322 * @param {Function} fn
21323 * @param {Object} scope (optional)
21325 sort : function(fn, scope){
21326 var cs = this.childNodes;
21327 var len = cs.length;
21329 var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
21331 for(var i = 0; i < len; i++){
21333 n.previousSibling = cs[i-1];
21334 n.nextSibling = cs[i+1];
21336 this.setFirstChild(n);
21339 this.setLastChild(n);
21346 * Returns true if this node is an ancestor (at any point) of the passed node.
21347 * @param {Node} node
21348 * @return {Boolean}
21350 contains : function(node){
21351 return node.isAncestor(this);
21355 * Returns true if the passed node is an ancestor (at any point) of this node.
21356 * @param {Node} node
21357 * @return {Boolean}
21359 isAncestor : function(node){
21360 var p = this.parentNode;
21370 toString : function(){
21371 return "[Node"+(this.id?" "+this.id:"")+"]";