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, A){
37 // no "this" reference for friendly out of scope calls
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var C = document.compatMode == "CSS1Compat",
54 D = ua.indexOf("opera") > -1,
55 E = (/webkit|khtml/).test(ua),
56 F = ua.indexOf("msie") > -1,
57 G = ua.indexOf("msie 7") > -1,
58 H = !E && ua.indexOf("gecko") > -1,
60 J = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 K = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 L = (ua.indexOf("linux") != -1),
63 M = window.location.href.toLowerCase().indexOf("https") === 0;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
75 * True if the browser is in strict mode
80 * True if the page is running over SSL
85 * True when the document is fully initialized and ready for action
91 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
94 enableGarbageCollector : true,
97 * True to automatically purge event listeners after uncaching an element (defaults to false).
98 * Note: this only happens if enableGarbageCollector is true.
101 enableListenerCollection:false,
104 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
105 * the IE insecure content warning (defaults to javascript:false).
108 SSL_SECURE_URL : "javascript:false",
111 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
112 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
115 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
117 emptyFn : function(){},
120 * Copies all the properties of config to obj if they don't already exist.
121 * @param {Object} obj The receiver of the properties
122 * @param {Object} config The source of the properties
123 * @return {Object} returns obj
125 applyIf : function(o, c){
128 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
135 * Applies event listeners to elements by selectors when the document is ready.
136 * The event name is specified with an @ suffix.
139 // add a listener for click on all anchors in element with id foo
140 '#foo a@click' : function(e, t){
144 // add the same listener to multiple selectors (separated by comma BEFORE the @)
145 '#foo a, #bar span.some-class@mouseover' : function(){
150 * @param {Object} obj The list of behaviors to apply
152 addBehaviors : function(o){
154 Roo.onReady(function(){
159 var N = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
161 var parts = b.split('@');
162 if(parts[1]){ // for Object prototype breakers
165 N[s] = Roo.select(s);
168 N[s].on(parts[1], o[b]);
176 * Generates unique ids. If the element already has an id, it is unchanged
177 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
178 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
179 * @return {String} The generated Id.
181 id : function(el, O){
185 return el ? (el.id ? el.id : (el.id = id)) : id;
190 * Extends one class with another class and optionally overrides members with the passed literal. This class
191 * also adds the function "override()" to the class that can be used to override
192 * members on an instance.
193 * @param {Object} subclass The class inheriting the functionality
194 * @param {Object} superclass The class being extended
195 * @param {Object} overrides (optional) A literal with members
200 var io = function(o){
205 return function(sb, sp, P){
206 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
209 sb = function(){sp.apply(this, arguments);};
211 var F = function(){}, sbp, spp = sp.prototype;
213 sbp = sb.prototype = new F();
217 if(spp.constructor == Object.prototype.constructor){
223 sb.override = function(o){
233 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
235 Roo.override(MyClass, {
236 newMethod1: function(){
239 newMethod2: function(foo){
244 * @param {Object} origclass The class to override
245 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
246 * containing one or more methods.
249 override : function(P, Q){
252 for(var method in Q){
253 p[method] = Q[method];
258 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
260 Roo.namespace('Company', 'Company.data');
261 Company.Widget = function() { ... }
262 Company.data.CustomStore = function(config) { ... }
264 * @param {String} namespace1
265 * @param {String} namespace2
266 * @param {String} etc
269 namespace : function(){
270 var a=arguments, o=null, i, j, d, rt;
271 for (i=0; i<a.length; ++i) {
275 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
276 for (j=1; j<d.length; ++j) {
277 o[d[j]]=o[d[j]] || {};
283 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
285 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
286 Roo.factory(conf, Roo.data);
288 * @param {String} classname
289 * @param {String} namespace (optional)
293 factory : function(c, ns)
295 // no xtype, no ns or c.xns - or forced off by c.xns
296 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
300 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
301 if (c.constructor == ns[c.xtype]) {// already created...
305 console.log("Roo.Factory(" + c.xtype + ")");
306 var ret = new ns[c.xtype](c);
311 c.xns = false; // prevent recursion..
316 * 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.
320 urlEncode : function(o){
326 var ov = o[key], k = encodeURIComponent(key);
327 var type = typeof ov;
328 if(type == 'undefined'){
330 }else if(type != "function" && type != "object"){
331 R.push(k, "=", encodeURIComponent(ov), "&");
332 }else if(ov instanceof Array){
334 for(var i = 0, len = ov.length; i < len; i++) {
335 R.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
348 * 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]}.
349 * @param {String} string
350 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
351 * @return {Object} A literal with members
353 urlDecode : function(S, T){
358 var V = S.split('&');
360 for(var i = 0, len = V.length; i < len; i++){
362 X = decodeURIComponent(W[0]);
363 Y = decodeURIComponent(W[1]);
365 if(typeof U[X] == "undefined"){
367 }else if(typeof U[X] == "string"){
381 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
382 * passed array is not really an array, your function is called once with it.
383 * The supplied function is called with (Object item, Number index, Array allItems).
384 * @param {Array/NodeList/Mixed} array
385 * @param {Function} fn
386 * @param {Object} scope
388 each : function(Z, fn, f){
389 if(typeof Z.length == "undefined" || typeof Z == "string"){
392 for(var i = 0, len = Z.length; i < len; i++){
393 if(fn.call(f || Z[i], Z[i], i, Z) === false){ return i; };
398 combine : function(){
399 var as = arguments, l = as.length, r = [];
400 for(var i = 0; i < l; i++){
402 if(a instanceof Array){
404 }else if(a.length !== undefined && !a.substr){
405 r = r.concat(Array.prototype.slice.call(a, 0));
414 * Escapes the passed string for use in a regular expression
415 * @param {String} str
418 escapeRe : function(s) {
419 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
423 callback : function(cb, g, h, n){
424 if(typeof cb == "function"){
426 cb.defer(n, g, h || []);
428 cb.apply(g, h || []);
434 * Return the dom node for the passed string (id), dom node, or Roo.Element
435 * @param {String/HTMLElement/Roo.Element} el
436 * @return HTMLElement
438 getDom : function(el){
442 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
446 * Shorthand for {@link Roo.ComponentMgr#get}
448 * @return Roo.Component
450 getCmp : function(id){
451 return Roo.ComponentMgr.get(id);
454 num : function(v, q){
455 if(typeof v != 'number'){
461 destroy : function(){
462 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
466 as.removeAllListeners();
470 if(typeof as.purgeListeners == 'function'){
473 if(typeof as.destroy == 'function'){
480 // inpired by a similar function in mootools library
482 * Returns the type of object that is passed in. If the object passed in is null or undefined it
483 * return false otherwise it returns one of the following values:<ul>
484 * <li><b>string</b>: If the object passed is a string</li>
485 * <li><b>number</b>: If the object passed is a number</li>
486 * <li><b>boolean</b>: If the object passed is a boolean value</li>
487 * <li><b>function</b>: If the object passed is a function reference</li>
488 * <li><b>object</b>: If the object passed is an object</li>
489 * <li><b>array</b>: If the object passed is an array</li>
490 * <li><b>regexp</b>: If the object passed is a regular expression</li>
491 * <li><b>element</b>: If the object passed is a DOM Element</li>
492 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
493 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
494 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
495 * @param {Mixed} object
499 if(o === undefined || o === null){
506 if(t == 'object' && o.nodeName) {
508 case 1: return 'element';
509 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
512 if(t == 'object' || t == 'function') {
513 switch(o.constructor) {
514 case Array: return 'array';
515 case RegExp: return 'regexp';
517 if(typeof o.length == 'number' && typeof o.item == 'function') {
525 * Returns true if the passed value is null, undefined or an empty string (optional).
526 * @param {Mixed} value The value to test
527 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
530 isEmpty : function(v, u){
531 return v === null || v === undefined || (!u ? v === '' : false);
554 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
555 * you may want to set this to true.
558 useShims : ((F && !G) || (H && K))
564 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
565 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
569 * Ext JS Library 1.1.1
570 * Copyright(c) 2006-2007, Ext JS, LLC.
572 * Originally Released Under LGPL - original licence link has changed is not relivant.
575 * <script type="text/javascript">
579 // wrappedn so fnCleanup is not in global scope...
582 var p = Function.prototype;
583 delete p.createSequence;
585 delete p.createDelegate;
586 delete p.createCallback;
587 delete p.createInterceptor;
589 window.detachEvent("onunload", A);
592 window.attachEvent("onunload", A);
599 * These functions are available on every Function object (any JavaScript function).
601 Roo.apply(Function.prototype, {
603 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
604 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
605 * Will create a function that is bound to those 2 args.
606 * @return {Function} The new function
608 createCallback : function(/*args...*/){
609 // make args available, in function below
613 return C.apply(window, B);
618 * Creates a delegate (callback) that sets the scope to obj.
619 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
620 * Will create a function that is automatically scoped to this.
621 * @param {Object} obj (optional) The object for which the scope is set
622 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
623 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
624 * if a number the args are inserted at the specified position
625 * @return {Function} The new function
627 createDelegate : function(D, E, F){
630 var H = E || arguments;
632 H = Array.prototype.slice.call(arguments, 0);
634 }else if(typeof F == "number"){
635 H = Array.prototype.slice.call(arguments, 0); // copy arguments first
636 var applyArgs = [F, 0].concat(E); // create method call params
637 Array.prototype.splice.apply(H, applyArgs); // splice them in
639 return G.apply(D || window, H);
644 * Calls this function after the number of millseconds specified.
645 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
646 * @param {Object} obj (optional) The object for which the scope is set
647 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
648 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
649 * if a number the args are inserted at the specified position
650 * @return {Number} The timeout id that can be used with clearTimeout
652 defer : function(H, I, J, K){
653 var fn = this.createDelegate(I, J, K);
655 return setTimeout(fn, H);
662 * Create a combined function call sequence of the original function + the passed function.
663 * The resulting function returns the results of the original function.
664 * The passed fcn is called with the parameters of the original function
665 * @param {Function} fcn The function to sequence
666 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
667 * @return {Function} The new function
669 createSequence : function(L, M){
670 if(typeof L != "function"){
675 var O = N.apply(this || window, arguments);
676 L.apply(M || this || window, arguments);
682 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
683 * The resulting function returns the results of the original function.
684 * The passed fcn is called with the parameters of the original function.
686 * @param {Function} fcn The function to call before the original
687 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
688 * @return {Function} The new function
690 createInterceptor : function(O, P){
691 if(typeof O != "function"){
698 if(O.apply(P || this || window, arguments) === false){
701 return Q.apply(this || window, arguments);
708 * Ext JS Library 1.1.1
709 * Copyright(c) 2006-2007, Ext JS, LLC.
711 * Originally Released Under LGPL - original licence link has changed is not relivant.
714 * <script type="text/javascript">
717 Roo.applyIf(String, {
722 * Escapes the passed string for ' and \
723 * @param {String} string The string to escape
724 * @return {String} The escaped string
727 escape : function(A) {
728 return A.replace(/('|\\)/g, "\\$1");
732 * Pads the left side of a string with a specified character. This is especially useful
733 * for normalizing number and date strings. Example usage:
735 var s = String.leftPad('123', 5, '0');
736 // s now contains the string: '00123'
738 * @param {String} string The original string
739 * @param {Number} size The total length of the output string
740 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
741 * @return {String} The padded string
744 leftPad : function (B, C, ch) {
745 var D = new String(B);
746 if(ch === null || ch === undefined || ch === '') {
749 while (D.length < C) {
756 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
757 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
759 var cls = 'my-class', text = 'Some text';
760 var s = String.format('<div class="{0}">{1}</div>', cls, text);
761 // s now contains the string: '<div class="my-class">Some text</div>'
763 * @param {String} string The tokenized string to be formatted
764 * @param {String} value1 The value to replace token {0}
765 * @param {String} value2 Etc...
766 * @return {String} The formatted string
769 format : function(E){
770 var F = Array.prototype.slice.call(arguments, 1);
771 return E.replace(/\{(\d+)\}/g, function(m, i){
772 return Roo.util.Format.htmlEncode(F[i]);
778 * Utility function that allows you to easily switch a string between two alternating values. The passed value
779 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
780 * they are already different, the first value passed in is returned. Note that this method returns the new value
781 * but does not change the current string.
783 // alternate sort directions
784 sort = sort.toggle('ASC', 'DESC');
786 // instead of conditional logic:
787 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
789 * @param {String} value The value to compare to the current string
790 * @param {String} other The new value to use if the string already equals the first value passed in
791 * @return {String} The new value
794 String.prototype.toggle = function(G, H){
795 return this == G ? H : G;
799 * Ext JS Library 1.1.1
800 * Copyright(c) 2006-2007, Ext JS, LLC.
802 * Originally Released Under LGPL - original licence link has changed is not relivant.
805 * <script type="text/javascript">
811 Roo.applyIf(Number.prototype, {
813 * Checks whether or not the current number is within a desired range. If the number is already within the
814 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
815 * exceeded. Note that this method returns the constrained value but does not change the current number.
816 * @param {Number} min The minimum number in the range
817 * @param {Number} max The maximum number in the range
818 * @return {Number} The constrained value if outside the range, otherwise the current value
820 constrain : function(A, B){
821 return Math.min(Math.max(this, A), B);
826 * Ext JS Library 1.1.1
827 * Copyright(c) 2006-2007, Ext JS, LLC.
829 * Originally Released Under LGPL - original licence link has changed is not relivant.
832 * <script type="text/javascript">
837 Roo.applyIf(Array.prototype, {
839 * Checks whether or not the specified object exists in the array.
840 * @param {Object} o The object to check for
841 * @return {Number} The index of o in the array (or -1 if it is not found)
843 indexOf : function(o){
844 for (var i = 0, len = this.length; i < len; i++){
845 if(this[i] == o) return i;
851 * Removes the specified object from the array. If the object is not found nothing happens.
852 * @param {Object} o The object to remove
854 remove : function(o){
855 var A = this.indexOf(o);
863 * Ext JS Library 1.1.1
864 * Copyright(c) 2006-2007, Ext JS, LLC.
866 * Originally Released Under LGPL - original licence link has changed is not relivant.
869 * <script type="text/javascript">
875 * The date parsing and format syntax is a subset of
876 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
877 * supported will provide results equivalent to their PHP versions.
879 * Following is the list of all currently supported formats:
882 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
884 Format Output Description
885 ------ ---------- --------------------------------------------------------------
886 d 10 Day of the month, 2 digits with leading zeros
887 D Wed A textual representation of a day, three letters
888 j 10 Day of the month without leading zeros
889 l Wednesday A full textual representation of the day of the week
890 S th English ordinal day of month suffix, 2 chars (use with j)
891 w 3 Numeric representation of the day of the week
892 z 9 The julian date, or day of the year (0-365)
893 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
894 F January A full textual representation of the month
895 m 01 Numeric representation of a month, with leading zeros
896 M Jan Month name abbreviation, three letters
897 n 1 Numeric representation of a month, without leading zeros
898 t 31 Number of days in the given month
899 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
900 Y 2007 A full numeric representation of a year, 4 digits
901 y 07 A two digit representation of a year
902 a pm Lowercase Ante meridiem and Post meridiem
903 A PM Uppercase Ante meridiem and Post meridiem
904 g 3 12-hour format of an hour without leading zeros
905 G 15 24-hour format of an hour without leading zeros
906 h 03 12-hour format of an hour with leading zeros
907 H 15 24-hour format of an hour with leading zeros
908 i 05 Minutes with leading zeros
909 s 01 Seconds, with leading zeros
910 O -0600 Difference to Greenwich time (GMT) in hours
911 T CST Timezone setting of the machine running the code
912 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
915 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
917 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
918 document.write(dt.format('Y-m-d')); //2007-01-10
919 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
920 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
923 * Here are some standard date/time patterns that you might find helpful. They
924 * are not part of the source of Date.js, but to use them you can simply copy this
925 * block of code into any script that is included after Date.js and they will also become
926 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
929 ISO8601Long:"Y-m-d H:i:s",
930 ISO8601Short:"Y-m-d",
932 LongDate: "l, F d, Y",
933 FullDateTime: "l, F d, Y g:i:s A",
937 SortableDateTime: "Y-m-d\\TH:i:s",
938 UniversalSortableDateTime: "Y-m-d H:i:sO",
946 document.write(dt.format(Date.patterns.ShortDate));
951 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
952 * They generate precompiled functions from date formats instead of parsing and
953 * processing the pattern every time you format a date. These functions are available
954 * on every Date object (any javascript function).
956 * The original article and download are here:
957 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
964 Returns the number of milliseconds between this date and date
965 @param {Date} date (optional) Defaults to now
966 @return {Number} The diff in milliseconds
967 @member Date getElapsed
969 Date.prototype.getElapsed = function(A) {
970 return Math.abs((A || new Date()).getTime()-this.getTime());
972 // was in date file..
976 Date.parseFunctions = {count:0};
978 Date.parseRegexes = [];
980 Date.formatFunctions = {count:0};
983 Date.prototype.dateFormat = function(B) {
984 if (Date.formatFunctions[B] == null) {
985 Date.createNewFormat(B);
987 var C = Date.formatFunctions[B];
993 * Formats a date given the supplied format string
994 * @param {String} format The format string
995 * @return {String} The formatted date
998 Date.prototype.format = Date.prototype.dateFormat;
1001 Date.createNewFormat = function(D) {
1002 var E = "format" + Date.formatFunctions.count++;
1003 Date.formatFunctions[D] = E;
1004 var F = "Date.prototype." + E + " = function(){return ";
1007 for (var i = 0; i < D.length; ++i) {
1009 if (!G && ch == "\\") {
1014 F += "'" + String.escape(ch) + "' + ";
1017 F += Date.getFormatCode(ch);
1021 /** eval:var:zzzzzzzzzzzzz */
1022 eval(F.substring(0, F.length - 3) + ";}");
1026 Date.getFormatCode = function(H) {
1029 return "String.leftPad(this.getDate(), 2, '0') + ";
1031 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1033 return "this.getDate() + ";
1035 return "Date.dayNames[this.getDay()] + ";
1037 return "this.getSuffix() + ";
1039 return "this.getDay() + ";
1041 return "this.getDayOfYear() + ";
1043 return "this.getWeekOfYear() + ";
1045 return "Date.monthNames[this.getMonth()] + ";
1047 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1049 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1051 return "(this.getMonth() + 1) + ";
1053 return "this.getDaysInMonth() + ";
1055 return "(this.isLeapYear() ? 1 : 0) + ";
1057 return "this.getFullYear() + ";
1059 return "('' + this.getFullYear()).substring(2, 4) + ";
1061 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1063 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1065 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1067 return "this.getHours() + ";
1069 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1071 return "String.leftPad(this.getHours(), 2, '0') + ";
1073 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1075 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1077 return "this.getGMTOffset() + ";
1079 return "this.getTimezone() + ";
1081 return "(this.getTimezoneOffset() * -60) + ";
1083 return "'" + String.escape(H) + "' + ";
1088 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1089 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1090 * the date format that is not specified will default to the current date value for that part. Time parts can also
1091 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1092 * string or the parse operation will fail.
1095 //dt = Fri May 25 2007 (current date)
1096 var dt = new Date();
1098 //dt = Thu May 25 2006 (today's month/day in 2006)
1099 dt = Date.parseDate("2006", "Y");
1101 //dt = Sun Jan 15 2006 (all date parts specified)
1102 dt = Date.parseDate("2006-1-15", "Y-m-d");
1104 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1105 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1107 * @param {String} input The unparsed date as a string
1108 * @param {String} format The format the date is in
1109 * @return {Date} The parsed date
1112 Date.parseDate = function(I, J) {
1113 if (Date.parseFunctions[J] == null) {
1114 Date.createParser(J);
1116 var K = Date.parseFunctions[J];
1121 Date.createParser = function(L) {
1122 var M = "parse" + Date.parseFunctions.count++;
1123 var N = Date.parseRegexes.length;
1125 Date.parseFunctions[L] = M;
1127 var P = "Date." + M + " = function(input){\n"
1128 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1129 + "var d = new Date();\n"
1130 + "y = d.getFullYear();\n"
1131 + "m = d.getMonth();\n"
1132 + "d = d.getDate();\n"
1133 + "var results = input.match(Date.parseRegexes[" + N + "]);\n"
1134 + "if (results && results.length > 0) {";
1139 for (var i = 0; i < L.length; ++i) {
1141 if (!R && ch == "\\") {
1146 Q += String.escape(ch);
1149 var obj = Date.formatCodeToRegex(ch, O);
1152 if (obj.g && obj.c) {
1159 P += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1160 + "{v = new Date(y, m, d, h, i, s);}\n"
1161 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1162 + "{v = new Date(y, m, d, h, i);}\n"
1163 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1164 + "{v = new Date(y, m, d, h);}\n"
1165 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1166 + "{v = new Date(y, m, d);}\n"
1167 + "else if (y >= 0 && m >= 0)\n"
1168 + "{v = new Date(y, m);}\n"
1169 + "else if (y >= 0)\n"
1170 + "{v = new Date(y);}\n"
1171 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1172 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1173 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1176 Date.parseRegexes[N] = new RegExp("^" + Q + "$");
1177 /** eval:var:zzzzzzzzzzzzz */
1182 Date.formatCodeToRegex = function(S, T) {
1187 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1190 c:"d = parseInt(results[" + T + "], 10);\n",
1191 s:"(\\d{1,2})"}; // day of month without leading zeroes
1194 c:"d = parseInt(results[" + T + "], 10);\n",
1195 s:"(\\d{2})"}; // day of month with leading zeroes
1199 s:"(?:" + Date.dayNames.join("|") + ")"};
1203 s:"(?:st|nd|rd|th)"};
1218 c:"m = parseInt(Date.monthNumbers[results[" + T + "].substring(0, 3)], 10);\n",
1219 s:"(" + Date.monthNames.join("|") + ")"};
1222 c:"m = parseInt(Date.monthNumbers[results[" + T + "]], 10);\n",
1223 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1226 c:"m = parseInt(results[" + T + "], 10) - 1;\n",
1227 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1230 c:"m = parseInt(results[" + T + "], 10) - 1;\n",
1231 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1242 c:"y = parseInt(results[" + T + "], 10);\n",
1246 c:"var ty = parseInt(results[" + T + "], 10);\n"
1247 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1251 c:"if (results[" + T + "] == 'am') {\n"
1252 + "if (h == 12) { h = 0; }\n"
1253 + "} else { if (h < 12) { h += 12; }}",
1257 c:"if (results[" + T + "] == 'AM') {\n"
1258 + "if (h == 12) { h = 0; }\n"
1259 + "} else { if (h < 12) { h += 12; }}",
1264 c:"h = parseInt(results[" + T + "], 10);\n",
1265 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1269 c:"h = parseInt(results[" + T + "], 10);\n",
1270 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1273 c:"i = parseInt(results[" + T + "], 10);\n",
1277 c:"s = parseInt(results[" + T + "], 10);\n",
1282 "o = results[", T, "];\n",
1283 "var sn = o.substring(0,1);\n", // get + / - sign
1284 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1285 "var mn = o.substring(3,5) % 60;\n", // get minutes
1286 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1287 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1293 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1296 c:"z = results[" + T + "];\n" // -43200 <= UTC offset <= 50400
1297 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1298 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1302 s:String.escape(S)};
1307 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1308 * @return {String} The abbreviated timezone name (e.g. 'CST')
1310 Date.prototype.getTimezone = function() {
1311 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1315 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1316 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1318 Date.prototype.getGMTOffset = function() {
1319 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1320 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1321 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1325 * Get the numeric day number of the year, adjusted for leap year.
1326 * @return {Number} 0 through 364 (365 in leap years)
1328 Date.prototype.getDayOfYear = function() {
1330 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1331 for (var i = 0; i < this.getMonth(); ++i) {
1332 U += Date.daysInMonth[i];
1334 return U + this.getDate() - 1;
1338 * Get the string representation of the numeric week number of the year
1339 * (equivalent to the format specifier 'W').
1340 * @return {String} '00' through '52'
1342 Date.prototype.getWeekOfYear = function() {
1343 // Skip to Thursday of this week
1344 var V = this.getDayOfYear() + (4 - this.getDay());
1345 // Find the first Thursday of the year
1346 var W = new Date(this.getFullYear(), 0, 1);
1347 var X = (7 - W.getDay() + 4);
1348 return String.leftPad(((V - X) / 7) + 1, 2, "0");
1352 * Whether or not the current date is in a leap year.
1353 * @return {Boolean} True if the current date is in a leap year, else false
1355 Date.prototype.isLeapYear = function() {
1356 var Y = this.getFullYear();
1357 return ((Y & 3) == 0 && (Y % 100 || (Y % 400 == 0 && Y)));
1361 * Get the first day of the current month, adjusted for leap year. The returned value
1362 * is the numeric day index within the week (0-6) which can be used in conjunction with
1363 * the {@link #monthNames} array to retrieve the textual day name.
1366 var dt = new Date('1/10/2007');
1367 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1369 * @return {Number} The day number (0-6)
1371 Date.prototype.getFirstDayOfMonth = function() {
1372 var Z = (this.getDay() - (this.getDate() - 1)) % 7;
1373 return (Z < 0) ? (Z + 7) : Z;
1377 * Get the last day of the current month, adjusted for leap year. The returned value
1378 * is the numeric day index within the week (0-6) which can be used in conjunction with
1379 * the {@link #monthNames} array to retrieve the textual day name.
1382 var dt = new Date('1/10/2007');
1383 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1385 * @return {Number} The day number (0-6)
1387 Date.prototype.getLastDayOfMonth = function() {
1388 var a = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1389 return (a < 0) ? (a + 7) : a;
1394 * Get the first date of this date's month
1397 Date.prototype.getFirstDateOfMonth = function() {
1398 return new Date(this.getFullYear(), this.getMonth(), 1);
1402 * Get the last date of this date's month
1405 Date.prototype.getLastDateOfMonth = function() {
1406 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1409 * Get the number of days in the current month, adjusted for leap year.
1410 * @return {Number} The number of days in the month
1412 Date.prototype.getDaysInMonth = function() {
1413 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1414 return Date.daysInMonth[this.getMonth()];
1418 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1419 * @return {String} 'st, 'nd', 'rd' or 'th'
1421 Date.prototype.getSuffix = function() {
1422 switch (this.getDate()) {
1439 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1442 * An array of textual month names.
1443 * Override these values for international dates, for example...
1444 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1463 * An array of textual day names.
1464 * Override these values for international dates, for example...
1465 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1481 Date.monthNumbers = {
1496 * Creates and returns a new Date instance with the exact same date value as the called instance.
1497 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1498 * variable will also be changed. When the intention is to create a new variable that will not
1499 * modify the original instance, you should create a clone.
1501 * Example of correctly cloning a date:
1504 var orig = new Date('10/1/2006');
1507 document.write(orig); //returns 'Thu Oct 05 2006'!
1510 var orig = new Date('10/1/2006');
1511 var copy = orig.clone();
1513 document.write(orig); //returns 'Thu Oct 01 2006'
1515 * @return {Date} The new Date instance
1517 Date.prototype.clone = function() {
1518 return new Date(this.getTime());
1522 * Clears any time information from this date
1523 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1524 @return {Date} this or the clone
1526 Date.prototype.clearTime = function(b){
1528 return this.clone().clearTime();
1534 this.setMilliseconds(0);
1539 // safari setMonth is broken
1541 Date.brokenSetMonth = Date.prototype.setMonth;
1542 Date.prototype.setMonth = function(c){
1544 var n = Math.ceil(-c);
1545 var back_year = Math.ceil(n/12);
1546 var month = (n % 12) ? 12 - n % 12 : 0 ;
1547 this.setFullYear(this.getFullYear() - back_year);
1548 return Date.brokenSetMonth.call(this, month);
1550 return Date.brokenSetMonth.apply(this, arguments);
1556 /** Date interval constant
1560 /** Date interval constant
1564 /** Date interval constant
1568 /** Date interval constant
1572 /** Date interval constant
1576 /** Date interval constant
1580 /** Date interval constant
1586 * Provides a convenient method of performing basic date arithmetic. This method
1587 * does not modify the Date instance being called - it creates and returns
1588 * a new Date instance containing the resulting date value.
1593 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1594 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1596 //Negative values will subtract correctly:
1597 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1598 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1600 //You can even chain several calls together in one line!
1601 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1602 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1605 * @param {String} interval A valid date interval enum value
1606 * @param {Number} value The amount to add to the current date
1607 * @return {Date} The new Date instance
1609 Date.prototype.add = function(e, f){
1610 var d = this.clone();
1611 if (!e || f === 0) return d;
1612 switch(e.toLowerCase()){
1614 d.setMilliseconds(this.getMilliseconds() + f);
1617 d.setSeconds(this.getSeconds() + f);
1620 d.setMinutes(this.getMinutes() + f);
1623 d.setHours(this.getHours() + f);
1626 d.setDate(this.getDate() + f);
1629 var a = this.getDate();
1631 a = Math.min(a, this.getFirstDateOfMonth().add('mo', f).getLastDateOfMonth().getDate());
1635 d.setMonth(this.getMonth() + f);
1638 d.setFullYear(this.getFullYear() + f);
1645 * Ext JS Library 1.1.1
1646 * Copyright(c) 2006-2007, Ext JS, LLC.
1648 * Originally Released Under LGPL - original licence link has changed is not relivant.
1651 * <script type="text/javascript">
1655 getViewWidth : function(A) {
1656 return A ? this.getDocumentWidth() : this.getViewportWidth();
1659 getViewHeight : function(B) {
1660 return B ? this.getDocumentHeight() : this.getViewportHeight();
1663 getDocumentHeight: function() {
1664 var C = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1665 return Math.max(C, this.getViewportHeight());
1668 getDocumentWidth: function() {
1669 var D = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1670 return Math.max(D, this.getViewportWidth());
1673 getViewportHeight: function() {
1674 var E = self.innerHeight;
1675 var F = document.compatMode;
1677 if ((F || Roo.isIE) && !Roo.isOpera) {
1678 E = (F == "CSS1Compat") ?
1679 document.documentElement.clientHeight :
1680 document.body.clientHeight;
1686 getViewportWidth: function() {
1687 var G = self.innerWidth;
1688 var H = document.compatMode;
1690 if (H || Roo.isIE) {
1691 G = (H == "CSS1Compat") ?
1692 document.documentElement.clientWidth :
1693 document.body.clientWidth;
1698 isAncestor : function(p, c) {
1705 if (p.contains && !Roo.isSafari) {
1706 return p.contains(c);
1707 } else if (p.compareDocumentPosition) {
1708 return !!(p.compareDocumentPosition(c) & 16);
1710 var parent = c.parentNode;
1715 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1719 parent = parent.parentNode;
1725 getRegion : function(el) {
1726 return Roo.lib.Region.getRegion(el);
1729 getY : function(el) {
1730 return this.getXY(el)[1];
1733 getX : function(el) {
1734 return this.getXY(el)[0];
1737 getXY : function(el) {
1738 var p, pe, b, I, bd = document.body;
1739 el = Roo.getDom(el);
1740 var J = Roo.lib.AnimBase.fly;
1741 if (el.getBoundingClientRect) {
1742 b = el.getBoundingClientRect();
1743 I = J(document).getScroll();
1744 return [b.left + I.left, b.top + I.top];
1750 var K = J(el).getStyle("position") == "absolute";
1757 if (!K && J(p).getStyle("position") == "absolute") {
1764 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1765 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1772 if (p != el && pe.getStyle('overflow') != 'visible') {
1781 if (Roo.isSafari && K) {
1786 if (Roo.isGecko && !K) {
1788 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1789 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1794 while (p && p != bd) {
1795 if (!Roo.isOpera || (p.tagName != 'TR' && J(p).getStyle("display") != "inline")) {
1808 setXY : function(el, xy) {
1809 el = Roo.fly(el, '_setXY');
1811 var L = el.translatePoints(xy);
1812 if (xy[0] !== false) {
1813 el.dom.style.left = L.left + "px";
1815 if (xy[1] !== false) {
1816 el.dom.style.top = L.top + "px";
1820 setX : function(el, x) {
1821 this.setXY(el, [x, false]);
1824 setY : function(el, y) {
1825 this.setXY(el, [false, y]);
1830 * Portions of this file are based on pieces of Yahoo User Interface Library
1831 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1832 * YUI licensed under the BSD License:
1833 * http://developer.yahoo.net/yui/license.txt
1834 * <script type="text/javascript">
1838 Roo.lib.Event = function() {
1858 startInterval: function() {
1859 if (!this._interval) {
1861 var callback = function() {
1862 self._tryPreloadAttach();
1864 this._interval = setInterval(callback, this.POLL_INTERVAL);
1869 onAvailable: function(h, k, m, n) {
1874 checkReady: false });
1876 D = this.POLL_RETRYS;
1877 this.startInterval();
1881 addListener: function(el, o, fn) {
1882 el = Roo.getDom(el);
1887 if ("unload" == o) {
1893 var p = function(e) {
1894 return fn(Roo.lib.Event.getEvent(e));
1897 var li = [el, o, fn, p];
1902 this.doAdd(el, o, p, false);
1908 removeListener: function(el, r, fn) {
1911 el = Roo.getDom(el);
1914 return this.purgeElement(el, false, r);
1918 if ("unload" == r) {
1920 for (i = 0,s = C.length; i < s; i++) {
1937 var v = arguments[3];
1939 if ("undefined" == typeof v) {
1940 v = this._getCacheIndex(el, r, fn);
1952 this.doRemove(el, r, u[this.WFN], false);
1954 delete B[v][this.WFN];
1955 delete B[v][this.FN];
1963 getTarget: function(ev, w) {
1964 ev = ev.browserEvent || ev;
1965 var t = ev.target || ev.srcElement;
1966 return this.resolveTextNode(t);
1970 resolveTextNode: function(z) {
1971 if (Roo.isSafari && z && 3 == z.nodeType) {
1972 return z.parentNode;
1979 getPageX: function(ev) {
1980 ev = ev.browserEvent || ev;
1982 if (!x && 0 !== x) {
1983 x = ev.clientX || 0;
1986 x += this.getScroll()[1];
1994 getPageY: function(ev) {
1995 ev = ev.browserEvent || ev;
1997 if (!y && 0 !== y) {
1998 y = ev.clientY || 0;
2001 y += this.getScroll()[0];
2010 getXY: function(ev) {
2011 ev = ev.browserEvent || ev;
2012 return [this.getPageX(ev), this.getPageY(ev)];
2016 getRelatedTarget: function(ev) {
2017 ev = ev.browserEvent || ev;
2018 var t = ev.relatedTarget;
2020 if (ev.type == "mouseout") {
2022 } else if (ev.type == "mouseover") {
2027 return this.resolveTextNode(t);
2031 getTime: function(ev) {
2032 ev = ev.browserEvent || ev;
2034 var t = new Date().getTime();
2038 this.lastError = ex;
2047 stopEvent: function(ev) {
2048 this.stopPropagation(ev);
2049 this.preventDefault(ev);
2053 stopPropagation: function(ev) {
2054 ev = ev.browserEvent || ev;
2055 if (ev.stopPropagation) {
2056 ev.stopPropagation();
2058 ev.cancelBubble = true;
2063 preventDefault: function(ev) {
2064 ev = ev.browserEvent || ev;
2065 if(ev.preventDefault) {
2066 ev.preventDefault();
2068 ev.returnValue = false;
2073 getEvent: function(e) {
2074 var ev = e || window.event;
2076 var c = this.getEvent.caller;
2078 ev = c.arguments[0];
2079 if (ev && Event == ev.constructor) {
2090 getCharCode: function(ev) {
2091 ev = ev.browserEvent || ev;
2092 return ev.charCode || ev.keyCode || 0;
2096 _getCacheIndex: function(el, AA, fn) {
2097 for (var i = 0,s = B.length; i < s; ++i) {
2100 li[this.FN] == fn &&
2101 li[this.EL] == el &&
2102 li[this.TYPE] == AA) {
2114 getEl: function(id) {
2115 return document.getElementById(id);
2119 clearCache: function() {
2123 _load: function(e) {
2125 var EU = Roo.lib.Event;
2129 EU.doRemove(window, "load", EU._load);
2134 _tryPreloadAttach: function() {
2151 for (var i = 0,s = E.length; i < s; ++i) {
2154 var el = this.getEl(item.id);
2157 if (!item.checkReady ||
2160 (document && document.body)) {
2163 if (item.override) {
2164 if (item.override === true) {
2167 scope = item.override;
2171 item.fn.call(scope, item.obj);
2181 D = (AC.length === 0) ? 0 : D - 1;
2185 this.startInterval();
2187 clearInterval(this._interval);
2188 this._interval = null;
2192 this.locked = false;
2199 purgeElement: function(el, AD, AE) {
2200 var AF = this.getListeners(el, AE);
2202 for (var i = 0,s = AF.length; i < s; ++i) {
2204 this.removeListener(el, l.type, l.fn);
2208 if (AD && el && el.childNodes) {
2209 for (i = 0,s = el.childNodes.length; i < s; ++i) {
2210 this.purgeElement(el.childNodes[i], AD, AE);
2216 getListeners: function(el, AG) {
2220 } else if (AG == "unload") {
2226 for (var j = 0; j < AI.length; ++j) {
2227 var searchList = AI[j];
2228 if (searchList && searchList.length > 0) {
2229 for (var i = 0,s = searchList.length; i < s; ++i) {
2230 var l = searchList[i];
2231 if (l && l[this.EL] === el &&
2232 (!AG || AG === l[this.TYPE])) {
2237 adjust: l[this.ADJ_SCOPE],
2245 return (AH.length) ? AH : null;
2249 _unload: function(e) {
2251 var EU = Roo.lib.Event, i, j, l, AJ, AK;
2253 for (i = 0,AJ = C.length; i < AJ; ++i) {
2257 if (l[EU.ADJ_SCOPE]) {
2258 if (l[EU.ADJ_SCOPE] === true) {
2261 scope = l[EU.ADJ_SCOPE];
2265 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2275 if (B && B.length > 0) {
2281 EU.removeListener(l[EU.EL], l[EU.TYPE],
2294 EU.doRemove(window, "unload", EU._unload);
2299 getScroll: function() {
2300 var dd = document.documentElement, db = document.body;
2301 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2302 return [dd.scrollTop, dd.scrollLeft];
2304 return [db.scrollTop, db.scrollLeft];
2311 doAdd: function () {
2312 if (window.addEventListener) {
2313 return function(el, AL, fn, AM) {
2314 el.addEventListener(AL, fn, (AM));
2316 } else if (window.attachEvent) {
2317 return function(el, AL, fn, AM) {
2318 el.attachEvent("on" + AL, fn);
2327 doRemove: function() {
2328 if (window.removeEventListener) {
2329 return function (el, AL, fn, AM) {
2330 el.removeEventListener(AL, fn, (AM));
2332 } else if (window.detachEvent) {
2333 return function (el, AL, fn) {
2334 el.detachEvent("on" + AL, fn);
2346 var E = Roo.lib.Event;
2347 E.on = E.addListener;
2348 E.un = E.removeListener;
2350 if (document && document.body) {
2353 E.doAdd(window, "load", E._load);
2356 E.doAdd(window, "unload", E._unload);
2357 E._tryPreloadAttach();
2362 * Portions of this file are based on pieces of Yahoo User Interface Library
2363 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2364 * YUI licensed under the BSD License:
2365 * http://developer.yahoo.net/yui/license.txt
2366 * <script type="text/javascript">
2373 request : function(A, B, cb, C, D) {
2378 if(hs.hasOwnProperty(h)){
2379 this.initHeader(h, hs[h], false);
2384 this.initHeader('Content-Type', 'text/xml', false);
2390 return this.asyncRequest(A, B, cb, C);
2393 serializeForm : function(E) {
2394 if(typeof E == 'string') {
2395 E = (document.getElementById(E) || document.forms[E]);
2398 var el, F, G, H, I = '', J = false;
2399 for (var i = 0; i < E.elements.length; i++) {
2401 H = E.elements[i].disabled;
2402 F = E.elements[i].name;
2403 G = E.elements[i].value;
2409 case 'select-multiple':
2410 for (var j = 0; j < el.options.length; j++) {
2411 if (el.options[j].selected) {
2413 I += encodeURIComponent(F) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2416 I += encodeURIComponent(F) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2424 I += encodeURIComponent(F) + '=' + encodeURIComponent(G) + '&';
2438 I += encodeURIComponent(F) + '=' + encodeURIComponent(G) + '&';
2443 I += encodeURIComponent(F) + '=' + encodeURIComponent(G) + '&';
2449 I = I.substr(0, I.length - 1);
2457 useDefaultHeader:true,
2459 defaultPostHeader:'application/x-www-form-urlencoded',
2461 useDefaultXhrHeader:true,
2463 defaultXhrHeader:'XMLHttpRequest',
2465 hasDefaultHeaders:true,
2477 setProgId:function(id)
2479 this.activeX.unshift(id);
2482 setDefaultPostHeader:function(b)
2484 this.useDefaultHeader = b;
2487 setDefaultXhrHeader:function(b)
2489 this.useDefaultXhrHeader = b;
2492 setPollingInterval:function(i)
2494 if (typeof i == 'number' && isFinite(i)) {
2495 this.pollInterval = i;
2499 createXhrObject:function(K)
2505 M = new XMLHttpRequest();
2507 L = { conn:M, tId:K };
2511 for (var i = 0; i < this.activeX.length; ++i) {
2515 http = new ActiveXObject(this.activeX[i]);
2517 obj = { conn:http, tId:transactionId };
2530 getConnectionObject:function()
2533 var N = this.transactionId;
2537 o = this.createXhrObject(N);
2539 this.transactionId++;
2550 asyncRequest:function(O, P, Q, R)
2552 var o = this.getConnectionObject();
2558 o.conn.open(O, P, true);
2560 if (this.useDefaultXhrHeader) {
2561 if (!this.defaultHeaders['X-Requested-With']) {
2562 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2566 if(R && this.useDefaultHeader){
2567 this.initHeader('Content-Type', this.defaultPostHeader);
2570 if (this.hasDefaultHeaders || this.hasHeaders) {
2575 this.handleReadyState(o, Q);
2576 o.conn.send(R || null);
2582 handleReadyState:function(o, S)
2586 if (S && S.timeout) {
2587 this.timeout[o.tId] = window.setTimeout(function() {
2588 T.abort(o, S, true);
2593 this.poll[o.tId] = window.setInterval(
2595 if (o.conn && o.conn.readyState == 4) {
2596 window.clearInterval(T.poll[o.tId]);
2597 delete T.poll[o.tId];
2599 if(S && S.timeout) {
2600 window.clearTimeout(T.timeout[o.tId]);
2601 delete T.timeout[o.tId];
2605 T.handleTransactionResponse(o, S);
2608 , this.pollInterval);
2611 handleTransactionResponse:function(o, U, V)
2615 this.releaseObject(o);
2623 if (o.conn.status !== undefined && o.conn.status != 0) {
2636 if (W >= 200 && W < 300) {
2637 X = this.createResponseObject(o, U.argument);
2645 U.success.apply(U.scope, [X]);
2658 X = this.createExceptionObject(o.tId, U.argument, (V ? V : false));
2664 U.failure.apply(U.scope, [X]);
2669 X = this.createResponseObject(o, U.argument);
2675 U.failure.apply(U.scope, [X]);
2682 this.releaseObject(o);
2686 createResponseObject:function(o, Y)
2693 var headerStr = o.conn.getAllResponseHeaders();
2694 var header = headerStr.split('\n');
2695 for (var i = 0; i < header.length; i++) {
2696 var delimitPos = header[i].indexOf(':');
2697 if (delimitPos != -1) {
2698 a[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2707 Z.status = o.conn.status;
2708 Z.statusText = o.conn.statusText;
2709 Z.getResponseHeader = a;
2710 Z.getAllResponseHeaders = headerStr;
2711 Z.responseText = o.conn.responseText;
2712 Z.responseXML = o.conn.responseXML;
2714 if (typeof Y !== undefined) {
2721 createExceptionObject:function(c, d, f)
2724 var k = 'communication failure';
2726 var m = 'transaction aborted';
2747 initHeader:function(p, q, r)
2749 var s = (r) ? this.defaultHeaders : this.headers;
2751 if (s[p] === undefined) {
2757 s[p] = q + "," + s[p];
2761 this.hasDefaultHeaders = true;
2764 this.hasHeaders = true;
2769 setHeader:function(o)
2771 if (this.hasDefaultHeaders) {
2772 for (var prop in this.defaultHeaders) {
2773 if (this.defaultHeaders.hasOwnProperty(prop)) {
2774 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2779 if (this.hasHeaders) {
2780 for (var prop in this.headers) {
2781 if (this.headers.hasOwnProperty(prop)) {
2782 o.conn.setRequestHeader(prop, this.headers[prop]);
2787 this.hasHeaders = false;
2791 resetDefaultHeaders:function() {
2792 delete this.defaultHeaders;
2793 this.defaultHeaders = {};
2794 this.hasDefaultHeaders = false;
2797 abort:function(o, t, u)
2799 if(this.isCallInProgress(o)) {
2801 window.clearInterval(this.poll[o.tId]);
2802 delete this.poll[o.tId];
2804 delete this.timeout[o.tId];
2808 this.handleTransactionResponse(o, t, true);
2818 isCallInProgress:function(o)
2821 return o.conn.readyState != 4 && o.conn.readyState != 0;
2830 releaseObject:function(o)
2839 'MSXML2.XMLHTTP.3.0',
2848 * Portions of this file are based on pieces of Yahoo User Interface Library
2849 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2850 * YUI licensed under the BSD License:
2851 * http://developer.yahoo.net/yui/license.txt
2852 * <script type="text/javascript">
2856 Roo.lib.Region = function(t, r, b, l) {
2866 Roo.lib.Region.prototype = {
2867 contains : function(A) {
2868 return ( A.left >= this.left &&
2869 A.right <= this.right &&
2870 A.top >= this.top &&
2871 A.bottom <= this.bottom );
2875 getArea : function() {
2876 return ( (this.bottom - this.top) * (this.right - this.left) );
2879 intersect : function(B) {
2880 var t = Math.max(this.top, B.top);
2881 var r = Math.min(this.right, B.right);
2882 var b = Math.min(this.bottom, B.bottom);
2883 var l = Math.max(this.left, B.left);
2885 if (b >= t && r >= l) {
2886 return new Roo.lib.Region(t, r, b, l);
2891 union : function(C) {
2892 var t = Math.min(this.top, C.top);
2893 var r = Math.max(this.right, C.right);
2894 var b = Math.max(this.bottom, C.bottom);
2895 var l = Math.min(this.left, C.left);
2897 return new Roo.lib.Region(t, r, b, l);
2900 adjust : function(t, l, b, r) {
2909 Roo.lib.Region.getRegion = function(el) {
2910 var p = Roo.lib.Dom.getXY(el);
2913 var r = p[0] + el.offsetWidth;
2914 var b = p[1] + el.offsetHeight;
2917 return new Roo.lib.Region(t, r, b, l);
2921 * Portions of this file are based on pieces of Yahoo User Interface Library
2922 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2923 * YUI licensed under the BSD License:
2924 * http://developer.yahoo.net/yui/license.txt
2925 * <script type="text/javascript">
2928 //@@dep Roo.lib.Region
2931 Roo.lib.Point = function(x, y) {
2932 if (x instanceof Array) {
2937 this.x = this.right = this.left = this[0] = x;
2938 this.y = this.top = this.bottom = this[1] = y;
2941 Roo.lib.Point.prototype = new Roo.lib.Region();
2944 * Portions of this file are based on pieces of Yahoo User Interface Library
2945 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2946 * YUI licensed under the BSD License:
2947 * http://developer.yahoo.net/yui/license.txt
2948 * <script type="text/javascript">
2955 scroll : function(el, A, B, C, cb, D) {
2956 this.run(el, A, B, C, cb, D, Roo.lib.Scroll);
2959 motion : function(el, E, F, G, cb, H) {
2960 this.run(el, E, F, G, cb, H, Roo.lib.Motion);
2963 color : function(el, I, J, K, cb, L) {
2964 this.run(el, I, J, K, cb, L, Roo.lib.ColorAnim);
2967 run : function(el, M, N, O, cb, P, Q) {
2968 Q = Q || Roo.lib.AnimBase;
2969 if (typeof O == "string") {
2970 O = Roo.lib.Easing[O];
2972 var R = new Q(el, M, N, O);
2973 R.animateX(function() {
2974 Roo.callback(cb, P);
2981 * Portions of this file are based on pieces of Yahoo User Interface Library
2982 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2983 * YUI licensed under the BSD License:
2984 * http://developer.yahoo.net/yui/license.txt
2985 * <script type="text/javascript">
2994 A = new Roo.Element.Flyweight();
3002 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3006 Roo.lib.AnimBase = function(el, C, D, E) {
3008 this.init(el, C, D, E);
3012 Roo.lib.AnimBase.fly = B;
3016 Roo.lib.AnimBase.prototype = {
3018 toString: function() {
3019 var el = this.getEl();
3020 var id = el.id || el.tagName;
3021 return ("Anim " + id);
3025 noNegatives: /width|height|opacity|padding/i,
3026 offsetAttribute: /^((width|height)|(top|left))$/,
3027 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3028 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3032 doMethod: function(C, D, E) {
3033 return this.method(this.currentFrame, D, E - D, this.totalFrames);
3037 setAttribute: function(F, G, H) {
3038 if (this.patterns.noNegatives.test(F)) {
3039 G = (G > 0) ? G : 0;
3043 Roo.fly(this.getEl(), '_anim').setStyle(F, G + H);
3047 getAttribute: function(I) {
3048 var el = this.getEl();
3049 var J = B(el).getStyle(I);
3051 if (J !== 'auto' && !this.patterns.offsetUnit.test(J)) {
3052 return parseFloat(J);
3055 var a = this.patterns.offsetAttribute.exec(I) || [];
3060 if (L || (B(el).getStyle('position') == 'absolute' && K)) {
3061 J = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3070 getDefaultUnit: function(M) {
3071 if (this.patterns.defaultUnit.test(M)) {
3078 animateX : function(N, O) {
3079 var f = function() {
3080 this.onComplete.removeListener(f);
3081 if (typeof N == "function") {
3082 N.call(O || this, this);
3085 this.onComplete.addListener(f, this);
3090 setRuntimeAttribute: function(P) {
3093 var S = this.attributes;
3095 this.runtimeAttributes[P] = {};
3097 var T = function(U) {
3098 return (typeof U !== 'undefined');
3101 if (!T(S[P]['to']) && !T(S[P]['by'])) {
3106 Q = ( T(S[P]['from']) ) ? S[P]['from'] : this.getAttribute(P);
3109 if (T(S[P]['to'])) {
3111 } else if (T(S[P]['by'])) {
3112 if (Q.constructor == Array) {
3114 for (var i = 0, len = Q.length; i < len; ++i) {
3115 R[i] = Q[i] + S[P]['by'][i];
3123 this.runtimeAttributes[P].start = Q;
3124 this.runtimeAttributes[P].end = R;
3127 this.runtimeAttributes[P].unit = ( T(S[P].unit) ) ? S[P]['unit'] : this.getDefaultUnit(P);
3131 init: function(el, U, V, W) {
3142 el = Roo.getDom(el);
3145 this.attributes = U || {};
3148 this.duration = V || 1;
3151 this.method = W || Roo.lib.Easing.easeNone;
3154 this.useSeconds = true;
3157 this.currentFrame = 0;
3160 this.totalFrames = Roo.lib.AnimMgr.fps;
3163 this.getEl = function() {
3168 this.isAnimated = function() {
3173 this.getStartTime = function() {
3177 this.runtimeAttributes = {};
3180 this.animate = function() {
3181 if (this.isAnimated()) {
3186 this.currentFrame = 0;
3188 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3190 Roo.lib.AnimMgr.registerElement(this);
3194 this.stop = function(e) {
3196 this.currentFrame = this.totalFrames;
3197 this._onTween.fire();
3200 Roo.lib.AnimMgr.stop(this);
3203 var b = function() {
3204 this.onStart.fire();
3206 this.runtimeAttributes = {};
3207 for (var P in this.attributes) {
3208 this.setRuntimeAttribute(P);
3218 var c = function() {
3220 duration: new Date() - this.getStartTime(),
3221 currentFrame: this.currentFrame
3224 e.toString = function() {
3226 'duration: ' + e.duration +
3227 ', currentFrame: ' + e.currentFrame
3231 this.onTween.fire(e);
3233 var g = this.runtimeAttributes;
3236 this.setAttribute(P, this.doMethod(P, g[P].start, g[P].end), g[P].unit);
3243 var d = function() {
3244 var e = (new Date() - Y) / 1000 ;
3252 g.toString = function() {
3254 'duration: ' + g.duration +
3255 ', frames: ' + g.frames +
3262 this.onComplete.fire(g);
3266 this._onStart = new Roo.util.Event(this);
3267 this.onStart = new Roo.util.Event(this);
3268 this.onTween = new Roo.util.Event(this);
3269 this._onTween = new Roo.util.Event(this);
3270 this.onComplete = new Roo.util.Event(this);
3271 this._onComplete = new Roo.util.Event(this);
3272 this._onStart.addListener(b);
3273 this._onTween.addListener(c);
3274 this._onComplete.addListener(d);
3280 * Portions of this file are based on pieces of Yahoo User Interface Library
3281 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3282 * YUI licensed under the BSD License:
3283 * http://developer.yahoo.net/yui/license.txt
3284 * <script type="text/javascript">
3288 Roo.lib.AnimMgr = new function() {
3305 this.registerElement = function(F) {
3313 this.unRegister = function(F, G) {
3314 F._onComplete.fire();
3328 this.start = function() {
3330 A = setInterval(this.run, this.delay);
3335 this.stop = function(F) {
3339 for (var i = 0, len = B.length; i < len; ++i) {
3340 if (B[0].isAnimated()) {
3341 this.unRegister(B[0], 0);
3356 this.run = function() {
3357 for (var i = 0, len = B.length; i < len; ++i) {
3359 if (!tween || !tween.isAnimated()) {
3363 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3365 tween.currentFrame += 1;
3367 if (tween.useSeconds) {
3371 tween._onTween.fire();
3374 Roo.lib.AnimMgr.stop(tween, i);
3379 var D = function(F) {
3380 for (var i = 0, len = B.length; i < len; ++i) {
3389 var E = function(F) {
3390 var G = F.totalFrames;
3391 var H = F.currentFrame;
3392 var I = (F.currentFrame * F.duration * 1000 / F.totalFrames);
3393 var J = (new Date() - F.getStartTime());
3396 if (J < F.duration * 1000) {
3397 K = Math.round((J / I - 1) * F.currentFrame);
3401 if (K > 0 && isFinite(K)) {
3402 if (F.currentFrame + K >= G) {
3407 F.currentFrame += K;
3412 * Portions of this file are based on pieces of Yahoo User Interface Library
3413 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3414 * YUI licensed under the BSD License:
3415 * http://developer.yahoo.net/yui/license.txt
3416 * <script type="text/javascript">
3419 Roo.lib.Bezier = new function() {
3421 this.getPosition = function(A, t) {
3425 for (var i = 0; i < n; ++i) {
3426 B[i] = [A[i][0], A[i][1]];
3429 for (var j = 1; j < n; ++j) {
3430 for (i = 0; i < n - j; ++i) {
3431 B[i][0] = (1 - t) * B[i][0] + t * B[parseInt(i + 1, 10)][0];
3432 B[i][1] = (1 - t) * B[i][1] + t * B[parseInt(i + 1, 10)][1];
3436 return [ B[0][0], B[0][1] ];
3441 * Portions of this file are based on pieces of Yahoo User Interface Library
3442 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3443 * YUI licensed under the BSD License:
3444 * http://developer.yahoo.net/yui/license.txt
3445 * <script type="text/javascript">
3450 Roo.lib.ColorAnim = function(el, D, E, F) {
3451 Roo.lib.ColorAnim.superclass.constructor.call(this, el, D, E, F);
3454 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3456 var A = Roo.lib.AnimBase.fly;
3458 var B = Y.ColorAnim.superclass;
3459 var C = Y.ColorAnim.prototype;
3461 C.toString = function() {
3462 var el = this.getEl();
3463 var id = el.id || el.tagName;
3464 return ("ColorAnim " + id);
3467 C.patterns.color = /color$/i;
3468 C.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3469 C.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3470 C.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3471 C.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3474 C.parseColor = function(s) {
3475 if (s.length == 3) {
3479 var c = this.patterns.hex.exec(s);
3480 if (c && c.length == 4) {
3481 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3485 c = this.patterns.rgb.exec(s);
3486 if (c && c.length == 4) {
3487 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3491 c = this.patterns.hex3.exec(s);
3492 if (c && c.length == 4) {
3493 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3498 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3499 C.getAttribute = function(D) {
3500 var el = this.getEl();
3501 if (this.patterns.color.test(D)) {
3502 var val = A(el).getStyle(D);
3504 if (this.patterns.transparent.test(val)) {
3505 var parent = el.parentNode;
3506 val = A(parent).getStyle(D);
3508 while (parent && this.patterns.transparent.test(val)) {
3509 parent = parent.parentNode;
3510 val = A(parent).getStyle(D);
3511 if (parent.tagName.toUpperCase() == 'HTML') {
3517 val = B.getAttribute.call(this, D);
3522 C.getAttribute = function(D) {
3523 var el = this.getEl();
3524 if (this.patterns.color.test(D)) {
3525 var val = A(el).getStyle(D);
3527 if (this.patterns.transparent.test(val)) {
3528 var parent = el.parentNode;
3529 val = A(parent).getStyle(D);
3531 while (parent && this.patterns.transparent.test(val)) {
3532 parent = parent.parentNode;
3533 val = A(parent).getStyle(D);
3534 if (parent.tagName.toUpperCase() == 'HTML') {
3540 val = B.getAttribute.call(this, D);
3546 C.doMethod = function(D, E, F) {
3549 if (this.patterns.color.test(D)) {
3551 for (var i = 0, len = E.length; i < len; ++i) {
3552 G[i] = B.doMethod.call(this, D, E[i], F[i]);
3556 G = 'rgb(' + Math.floor(G[0]) + ',' + Math.floor(G[1]) + ',' + Math.floor(G[2]) + ')';
3559 G = B.doMethod.call(this, D, E, F);
3565 C.setRuntimeAttribute = function(D) {
3566 B.setRuntimeAttribute.call(this, D);
3568 if (this.patterns.color.test(D)) {
3569 var attributes = this.attributes;
3570 var start = this.parseColor(this.runtimeAttributes[D].start);
3571 var end = this.parseColor(this.runtimeAttributes[D].end);
3573 if (typeof attributes[D]['to'] === 'undefined' && typeof attributes[D]['by'] !== 'undefined') {
3574 end = this.parseColor(attributes[D].by);
3576 for (var i = 0, len = start.length; i < len; ++i) {
3577 end[i] = start[i] + end[i];
3582 this.runtimeAttributes[D].start = start;
3583 this.runtimeAttributes[D].end = end;
3590 * Portions of this file are based on pieces of Yahoo User Interface Library
3591 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3592 * YUI licensed under the BSD License:
3593 * http://developer.yahoo.net/yui/license.txt
3594 * <script type="text/javascript">
3600 easeNone: function (t, b, c, d) {
3601 return c * t / d + b;
3605 easeIn: function (t, b, c, d) {
3606 return c * (t /= d) * t + b;
3610 easeOut: function (t, b, c, d) {
3611 return -c * (t /= d) * (t - 2) + b;
3615 easeBoth: function (t, b, c, d) {
3616 if ((t /= d / 2) < 1) {
3617 return c / 2 * t * t + b;
3620 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3624 easeInStrong: function (t, b, c, d) {
3625 return c * (t /= d) * t * t * t + b;
3629 easeOutStrong: function (t, b, c, d) {
3630 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3634 easeBothStrong: function (t, b, c, d) {
3635 if ((t /= d / 2) < 1) {
3636 return c / 2 * t * t * t * t + b;
3639 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3644 elasticIn: function (t, b, c, d, a, p) {
3648 if ((t /= d) == 1) {
3655 if (!a || a < Math.abs(c)) {
3660 var s = p / (2 * Math.PI) * Math.asin(c / a);
3663 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3667 elasticOut: function (t, b, c, d, a, p) {
3671 if ((t /= d) == 1) {
3678 if (!a || a < Math.abs(c)) {
3683 var s = p / (2 * Math.PI) * Math.asin(c / a);
3686 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3690 elasticBoth: function (t, b, c, d, a, p) {
3695 if ((t /= d / 2) == 2) {
3703 if (!a || a < Math.abs(c)) {
3708 var s = p / (2 * Math.PI) * Math.asin(c / a);
3712 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3713 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3715 return a * Math.pow(2, -10 * (t -= 1)) *
3716 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3721 backIn: function (t, b, c, d, s) {
3722 if (typeof s == 'undefined') {
3725 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3729 backOut: function (t, b, c, d, s) {
3730 if (typeof s == 'undefined') {
3733 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3737 backBoth: function (t, b, c, d, s) {
3738 if (typeof s == 'undefined') {
3742 if ((t /= d / 2 ) < 1) {
3743 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3745 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3749 bounceIn: function (t, b, c, d) {
3750 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3754 bounceOut: function (t, b, c, d) {
3755 if ((t /= d) < (1 / 2.75)) {
3756 return c * (7.5625 * t * t) + b;
3757 } else if (t < (2 / 2.75)) {
3758 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3759 } else if (t < (2.5 / 2.75)) {
3760 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3762 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3766 bounceBoth: function (t, b, c, d) {
3768 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3770 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3774 * Portions of this file are based on pieces of Yahoo User Interface Library
3775 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3776 * YUI licensed under the BSD License:
3777 * http://developer.yahoo.net/yui/license.txt
3778 * <script type="text/javascript">
3782 Roo.lib.Motion = function(el, E, F, G) {
3784 Roo.lib.Motion.superclass.constructor.call(this, el, E, F, G);
3788 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3792 var A = Y.Motion.superclass;
3793 var B = Y.Motion.prototype;
3795 B.toString = function() {
3796 var el = this.getEl();
3797 var id = el.id || el.tagName;
3798 return ("Motion " + id);
3801 B.patterns.points = /^points$/i;
3803 B.setAttribute = function(E, F, G) {
3804 if (this.patterns.points.test(E)) {
3806 A.setAttribute.call(this, 'left', F[0], G);
3807 A.setAttribute.call(this, 'top', F[1], G);
3809 A.setAttribute.call(this, E, F, G);
3813 B.getAttribute = function(E) {
3814 if (this.patterns.points.test(E)) {
3816 A.getAttribute.call(this, 'left'),
3817 A.getAttribute.call(this, 'top')
3820 val = A.getAttribute.call(this, E);
3826 B.doMethod = function(E, F, G) {
3829 if (this.patterns.points.test(E)) {
3830 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3831 H = Y.Bezier.getPosition(this.runtimeAttributes[E], t);
3833 H = A.doMethod.call(this, E, F, G);
3838 B.setRuntimeAttribute = function(E) {
3839 if (this.patterns.points.test(E)) {
3840 var el = this.getEl();
3841 var attributes = this.attributes;
3843 var control = attributes['points']['control'] || [];
3847 if (control.length > 0 && !(control[0] instanceof Array)) {
3848 control = [control];
3851 for (i = 0,len = control.length; i < len; ++i) {
3852 tmp[i] = control[i];
3859 Roo.fly(el).position();
3861 if (D(attributes['points']['from'])) {
3862 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3865 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3869 start = this.getAttribute('points');
3872 if (D(attributes['points']['to'])) {
3873 end = C.call(this, attributes['points']['to'], start);
3875 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3876 for (i = 0,len = control.length; i < len; ++i) {
3877 control[i] = C.call(this, control[i], start);
3881 } else if (D(attributes['points']['by'])) {
3882 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3884 for (i = 0,len = control.length; i < len; ++i) {
3885 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3890 this.runtimeAttributes[E] = [start];
3892 if (control.length > 0) {
3893 this.runtimeAttributes[E] = this.runtimeAttributes[E].concat(control);
3897 this.runtimeAttributes[E][this.runtimeAttributes[E].length] = end;
3900 A.setRuntimeAttribute.call(this, E);
3904 var C = function(E, F) {
3905 var G = Roo.lib.Dom.getXY(this.getEl());
3906 E = [ E[0] - G[0] + F[0], E[1] - G[1] + F[1] ];
3911 var D = function(E) {
3912 return (typeof E !== 'undefined');
3917 * Portions of this file are based on pieces of Yahoo User Interface Library
3918 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3919 * YUI licensed under the BSD License:
3920 * http://developer.yahoo.net/yui/license.txt
3921 * <script type="text/javascript">
3925 Roo.lib.Scroll = function(el, C, D, E) {
3927 Roo.lib.Scroll.superclass.constructor.call(this, el, C, D, E);
3931 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3935 var A = Y.Scroll.superclass;
3936 var B = Y.Scroll.prototype;
3938 B.toString = function() {
3939 var el = this.getEl();
3940 var id = el.id || el.tagName;
3941 return ("Scroll " + id);
3944 B.doMethod = function(C, D, E) {
3947 if (C == 'scroll') {
3949 this.method(this.currentFrame, D[0], E[0] - D[0], this.totalFrames),
3950 this.method(this.currentFrame, D[1], E[1] - D[1], this.totalFrames)
3954 F = A.doMethod.call(this, C, D, E);
3959 B.getAttribute = function(C) {
3961 var el = this.getEl();
3963 if (C == 'scroll') {
3964 D = [ el.scrollLeft, el.scrollTop ];
3966 D = A.getAttribute.call(this, C);
3972 B.setAttribute = function(C, D, E) {
3973 var el = this.getEl();
3975 if (C == 'scroll') {
3976 el.scrollLeft = D[0];
3977 el.scrollTop = D[1];
3979 A.setAttribute.call(this, C, D, E);
3986 * Ext JS Library 1.1.1
3987 * Copyright(c) 2006-2007, Ext JS, LLC.
3989 * Originally Released Under LGPL - original licence link has changed is not relivant.
3992 * <script type="text/javascript">
3997 * @class Roo.DomHelper
3998 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3999 * 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>.
4002 Roo.DomHelper = function(){
4004 var B = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4005 var C = /^table|tbody|tr|td$/i;
4007 // build as innerHTML where available
4009 var E = function(o){
4010 if(typeof o == 'string'){
4020 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4021 if(attr == "style"){
4023 if(typeof s == "function"){
4026 if(typeof s == "string"){
4027 b += ' style="' + s + '"';
4028 }else if(typeof s == "object"){
4031 if(typeof s[key] != "function"){
4032 b += key + ":" + s[key] + ";";
4040 b += ' class="' + o["cls"] + '"';
4041 }else if(attr == "htmlFor"){
4042 b += ' for="' + o["htmlFor"] + '"';
4044 b += " " + attr + '="' + o[attr] + '"';
4052 var cn = o.children || o.cn;
4054 //http://bugs.kde.org/show_bug.cgi?id=71506
4055 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4056 for(var i = 0, len = cn.length; i < len; i++) {
4067 b += "</" + o.tag + ">";
4074 var F = function(o, M){
4076 // defininition craeted..
4078 if (o.ns && o.ns != 'html') {
4080 if (o.xmlns && typeof(D[o.ns]) == 'undefined') {
4084 if (typeof(D[o.ns]) == 'undefined') {
4085 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4092 if (typeof(o) == 'string') {
4093 return M.appendChild(document.createTextNode(o));
4096 o.tag = o.tag || div;
4097 if (o.ns && Roo.isIE) {
4099 o.tag = o.ns + ':' + o.tag;
4102 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4103 var N = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4106 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4107 attr == "style" || typeof o[attr] == "function") continue;
4109 if(attr=="cls" && Roo.isIE){
4110 el.className = o["cls"];
4112 if(N) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4113 else el[attr] = o[attr];
4117 Roo.DomHelper.applyStyles(el, o.style);
4118 var cn = o.children || o.cn;
4120 //http://bugs.kde.org/show_bug.cgi?id=71506
4121 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4122 for(var i = 0, len = cn.length; i < len; i++) {
4130 el.innerHTML = o.html;
4138 var G = function(M, s, h, e){
4139 A.innerHTML = [s, h, e].join('');
4147 // kill repeat to save bytes
4157 * Nasty code for IE's broken table implementation
4159 var L = function(M, N, el, O){
4161 A = document.createElement('div');
4166 if(N == 'afterbegin' || N == 'beforeend'){ // INTO a TD
4169 if(N == 'beforebegin'){
4180 if(N == 'beforebegin'){
4184 } else if(N == 'afterend'){
4188 } else { // INTO a TR
4189 if(N == 'afterbegin'){
4195 } else if(M == 'tbody'){
4196 if(N == 'beforebegin'){
4199 P = G(2, ts, O, te);
4200 } else if(N == 'afterend'){
4203 P = G(2, ts, O, te);
4205 if(N == 'afterbegin'){
4212 if(N == 'beforebegin' || N == 'afterend'){ // OUTSIDE the table
4215 if(N == 'afterbegin'){
4219 P = G(2, ts, O, te);
4222 el.insertBefore(P, Q);
4227 /** True to force the use of DOM instead of html fragments @type Boolean */
4231 * Returns the markup for the passed Element(s) config
4232 * @param {Object} o The Dom object spec (and children)
4235 markup : function(o){
4240 * Applies a style specification to an element
4241 * @param {String/HTMLElement} el The element to apply styles to
4242 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4243 * a function which returns such a specification.
4245 applyStyles : function(el, c){
4248 if(typeof c == "string"){
4249 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4251 while ((matches = re.exec(c)) != null){
4252 el.setStyle(matches[1], matches[2]);
4254 }else if (typeof c == "object"){
4255 for (var style in c){
4256 el.setStyle(style, c[style]);
4258 }else if (typeof c == "function"){
4259 Roo.DomHelper.applyStyles(el, c.call());
4265 * Inserts an HTML fragment into the Dom
4266 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4267 * @param {HTMLElement} el The context element
4268 * @param {String} html The HTML fragmenet
4269 * @return {HTMLElement} The new node
4271 insertHtml : function(d, el, e){
4272 d = d.toLowerCase();
4273 if(el.insertAdjacentHTML){
4274 if(C.test(el.tagName)){
4276 if(rs = L(el.tagName.toLowerCase(), d, el, e)){
4282 el.insertAdjacentHTML('BeforeBegin', e);
4283 return el.previousSibling;
4285 el.insertAdjacentHTML('AfterBegin', e);
4286 return el.firstChild;
4288 el.insertAdjacentHTML('BeforeEnd', e);
4289 return el.lastChild;
4291 el.insertAdjacentHTML('AfterEnd', e);
4292 return el.nextSibling;
4294 throw 'Illegal insertion point -> "' + d + '"';
4296 var f = el.ownerDocument.createRange();
4300 f.setStartBefore(el);
4301 g = f.createContextualFragment(e);
4302 el.parentNode.insertBefore(g, el);
4303 return el.previousSibling;
4306 f.setStartBefore(el.firstChild);
4307 g = f.createContextualFragment(e);
4308 el.insertBefore(g, el.firstChild);
4309 return el.firstChild;
4312 return el.firstChild;
4316 f.setStartAfter(el.lastChild);
4317 g = f.createContextualFragment(e);
4319 return el.lastChild;
4322 return el.lastChild;
4325 f.setStartAfter(el);
4326 g = f.createContextualFragment(e);
4327 el.parentNode.insertBefore(g, el.nextSibling);
4328 return el.nextSibling;
4330 throw 'Illegal insertion point -> "' + d + '"';
4334 * Creates new Dom element(s) and inserts them before el
4335 * @param {String/HTMLElement/Element} el The context element
4336 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4337 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4338 * @return {HTMLElement/Roo.Element} The new node
4340 insertBefore : function(el, o, h){
4341 return this.doInsert(el, o, h, "beforeBegin");
4345 * Creates new Dom element(s) and inserts them after el
4346 * @param {String/HTMLElement/Element} el The context element
4347 * @param {Object} o The Dom object spec (and children)
4348 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4349 * @return {HTMLElement/Roo.Element} The new node
4351 insertAfter : function(el, o, j){
4352 return this.doInsert(el, o, j, "afterEnd", "nextSibling");
4356 * Creates new Dom element(s) and inserts them as the first child of el
4357 * @param {String/HTMLElement/Element} el The context element
4358 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4359 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4360 * @return {HTMLElement/Roo.Element} The new node
4362 insertFirst : function(el, o, k){
4363 return this.doInsert(el, o, k, "afterBegin");
4367 doInsert : function(el, o, l, m, n){
4368 el = Roo.getDom(el);
4370 if(this.useDom || o.ns){
4372 el.parentNode.insertBefore(p, n ? el[n] : el);
4375 p = this.insertHtml(m, el, e);
4377 return l ? Roo.get(p, true) : p;
4381 * Creates new Dom element(s) and appends them to el
4382 * @param {String/HTMLElement/Element} el The context element
4383 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4384 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4385 * @return {HTMLElement/Roo.Element} The new node
4387 append : function(el, o, q){
4388 el = Roo.getDom(el);
4390 if(this.useDom || o.ns){
4395 r = this.insertHtml("beforeEnd", el, e);
4397 return q ? Roo.get(r, true) : r;
4401 * Creates new Dom element(s) and overwrites the contents of el with them
4402 * @param {String/HTMLElement/Element} el The context element
4403 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4404 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4405 * @return {HTMLElement/Roo.Element} The new node
4407 overwrite : function(el, o, t){
4408 el = Roo.getDom(el);
4411 while (el.childNodes.length) {
4412 el.removeChild(el.firstChild);
4417 el.innerHTML = E(o);
4420 return t ? Roo.get(el.firstChild, true) : el.firstChild;
4424 * Creates a new Roo.DomHelper.Template from the Dom object spec
4425 * @param {Object} o The Dom object spec (and children)
4426 * @return {Roo.DomHelper.Template} The new template
4428 createTemplate : function(o){
4430 return new Roo.Template(u);
4437 * Ext JS Library 1.1.1
4438 * Copyright(c) 2006-2007, Ext JS, LLC.
4440 * Originally Released Under LGPL - original licence link has changed is not relivant.
4443 * <script type="text/javascript">
4447 * @class Roo.Template
4448 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4449 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4452 var t = new Roo.Template(
4453 '<div name="{id}">',
4454 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4457 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4459 * 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>.
4461 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4463 Roo.Template = function(A){
4464 if(A instanceof Array){
4466 }else if(arguments.length > 1){
4467 A = Array.prototype.join.call(arguments, "");
4474 Roo.Template.prototype = {
4476 * Returns an HTML fragment of this template with the specified values applied.
4477 * @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'})
4478 * @return {String} The HTML fragment
4480 applyTemplate : function(B){
4482 return this.compiled(B);
4484 var C = this.disableFormats !== true;
4485 var fm = Roo.util.Format, D = this;
4486 var fn = function(m, E, F, G){
4488 if(F.substr(0, 5) == "this."){
4489 return D.call(F.substr(5), B[E], B);
4492 // quoted values are required for strings in compiled templates,
4493 // but for non compiled we need to strip them
4494 // quoted reversed for jsmin
4495 var re = /^\s*['"](.*)["']\s*$/;
4497 for(var i = 0, len = G.length; i < len; i++){
4498 G[i] = G[i].replace(re, "$1");
4501 G = [B[E]].concat(G);
4505 return fm[F].apply(fm, G);
4508 return B[E] !== undefined ? B[E] : "";
4511 return this.html.replace(this.re, fn);
4515 * Sets the HTML used as the template and optionally compiles it.
4516 * @param {String} html
4517 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4518 * @return {Roo.Template} this
4520 set : function(E, F){
4522 this.compiled = null;
4530 * True to disable format functions (defaults to false)
4533 disableFormats : false,
4536 * The regular expression used to match template variables
4540 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4543 * Compiles the template into an internal function, eliminating the RegEx overhead.
4544 * @return {Roo.Template} this
4546 compile : function(){
4547 var fm = Roo.util.Format;
4548 var G = this.disableFormats !== true;
4549 var H = Roo.isGecko ? "+" : ",";
4550 var fn = function(m, J, K, L){
4552 L = L ? ',' + L : "";
4553 if(K.substr(0, 5) != "this."){
4554 K = "fm." + K + '(';
4556 K = 'this.call("'+ K.substr(5) + '", ';
4560 L= ''; K = "(values['" + J + "'] == undefined ? '' : ";
4562 return "'"+ H + K + "values['" + J + "']" + L + ")"+H+"'";
4565 // branched to use + in gecko and [].join() in others
4567 I = "this.compiled = function(values){ return '" +
4568 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4571 I = ["this.compiled = function(values){ return ['"];
4572 I.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4573 I.push("'].join('');};");
4585 // private function used to call members
4586 call : function(J, K, L){
4587 return this[J](K, L);
4591 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4592 * @param {String/HTMLElement/Roo.Element} el The context element
4593 * @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'})
4594 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4595 * @return {HTMLElement/Roo.Element} The new node or Element
4597 insertFirst: function(el, M, N){
4598 return this.doInsert('afterBegin', el, M, N);
4602 * Applies the supplied values to the template and inserts the new node(s) before el.
4603 * @param {String/HTMLElement/Roo.Element} el The context element
4604 * @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'})
4605 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4606 * @return {HTMLElement/Roo.Element} The new node or Element
4608 insertBefore: function(el, O, P){
4609 return this.doInsert('beforeBegin', el, O, P);
4613 * Applies the supplied values to the template and inserts the new node(s) after el.
4614 * @param {String/HTMLElement/Roo.Element} el The context element
4615 * @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'})
4616 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4617 * @return {HTMLElement/Roo.Element} The new node or Element
4619 insertAfter : function(el, Q, R){
4620 return this.doInsert('afterEnd', el, Q, R);
4624 * Applies the supplied values to the template and appends the new node(s) to el.
4625 * @param {String/HTMLElement/Roo.Element} el The context element
4626 * @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'})
4627 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4628 * @return {HTMLElement/Roo.Element} The new node or Element
4630 append : function(el, S, T){
4631 return this.doInsert('beforeEnd', el, S, T);
4634 doInsert : function(U, el, V, W){
4635 el = Roo.getDom(el);
4636 var X = Roo.DomHelper.insertHtml(U, el, this.applyTemplate(V));
4637 return W ? Roo.get(X, true) : X;
4641 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4642 * @param {String/HTMLElement/Roo.Element} el The context element
4643 * @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'})
4644 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4645 * @return {HTMLElement/Roo.Element} The new node or Element
4647 overwrite : function(el, Y, Z){
4648 el = Roo.getDom(el);
4649 el.innerHTML = this.applyTemplate(Y);
4650 return Z ? Roo.get(el.firstChild, true) : el.firstChild;
4654 * Alias for {@link #applyTemplate}
4657 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4660 Roo.DomHelper.Template = Roo.Template;
4663 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4664 * @param {String/HTMLElement} el A DOM element or its id
4665 * @returns {Roo.Template} The created template
4668 Roo.Template.from = function(el){
4669 el = Roo.getDom(el);
4670 return new Roo.Template(el.value || el.innerHTML);
4674 * Ext JS Library 1.1.1
4675 * Copyright(c) 2006-2007, Ext JS, LLC.
4677 * Originally Released Under LGPL - original licence link has changed is not relivant.
4680 * <script type="text/javascript">
4685 * This is code is also distributed under MIT license for use
4686 * with jQuery and prototype JavaScript libraries.
4689 * @class Roo.DomQuery
4690 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).
4692 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>
4695 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.
4697 <h4>Element Selectors:</h4>
4699 <li> <b>*</b> any element</li>
4700 <li> <b>E</b> an element with the tag E</li>
4701 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4702 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4703 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4704 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4706 <h4>Attribute Selectors:</h4>
4707 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4709 <li> <b>E[foo]</b> has an attribute "foo"</li>
4710 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4711 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4712 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4713 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4714 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4715 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4717 <h4>Pseudo Classes:</h4>
4719 <li> <b>E:first-child</b> E is the first child of its parent</li>
4720 <li> <b>E:last-child</b> E is the last child of its parent</li>
4721 <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>
4722 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4723 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4724 <li> <b>E:only-child</b> E is the only child of its parent</li>
4725 <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>
4726 <li> <b>E:first</b> the first E in the resultset</li>
4727 <li> <b>E:last</b> the last E in the resultset</li>
4728 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4729 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4730 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4731 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4732 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4733 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4734 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4735 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4736 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4738 <h4>CSS Value Selectors:</h4>
4740 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4741 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4742 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4743 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4744 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4745 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4749 Roo.DomQuery = function(){
4750 var A = {}, simpleCache = {}, valueCache = {};
4752 var C = /^\s+|\s+$/g;
4753 var D = /\{(\d+)\}/g;
4754 var E = /^(\s?[\/>+~]\s?|\s|$)/;
4755 var F = /^(#)?([\w-\*]+)/;
4756 var G = /(\d*)n\+?(\d*)/, H = /\D/;
4760 var n = p.firstChild;
4762 if(n.nodeType == 1){
4774 while((n = n.nextSibling) && n.nodeType != 1);
4779 while((n = n.previousSibling) && n.nodeType != 1);
4784 var n = d.firstChild, ni = -1;
4786 var nx = n.nextSibling;
4787 if(n.nodeType == 3 && !B.test(n.nodeValue)){
4798 function M(c, a, v){
4802 var r = [], ri = -1, cn;
4803 for(var i = 0, ci; ci = c[i]; i++){
4804 if((' '+ci.className+' ').indexOf(v) != -1){
4812 if(!n.tagName && typeof n.length != "undefined"){
4821 if(f == "class" || f == "className"){
4824 return n.getAttribute(f) || n[f];
4828 function O(ns, f, g){
4829 var h = [], ri = -1, cs;
4835 if(typeof ns.getElementsByTagName != "undefined"){
4839 for(var i = 0, ni; ni = ns[i]; i++){
4840 cs = ni.getElementsByTagName(g);
4841 for(var j = 0, ci; ci = cs[j]; j++){
4845 }else if(f == "/" || f == ">"){
4846 var utag = g.toUpperCase();
4847 for(var i = 0, ni, cn; ni = ns[i]; i++){
4848 cn = ni.children || ni.childNodes;
4849 for(var j = 0, cj; cj = cn[j]; j++){
4850 if(cj.nodeName == utag || cj.nodeName == g || g == '*'){
4856 var utag = g.toUpperCase();
4857 for(var i = 0, n; n = ns[i]; i++){
4858 while((n = n.nextSibling) && n.nodeType != 1);
4859 if(n && (n.nodeName == utag || n.nodeName == g || g == '*')){
4864 for(var i = 0, n; n = ns[i]; i++){
4865 while((n = n.nextSibling) && (n.nodeType != 1 || (g == '*' || n.tagName.toLowerCase()!=g)));
4878 for(var i = 0, l = b.length; i < l; i++){
4885 if(cs.tagName || cs == document){
4891 var r = [], ri = -1;
4892 f = f.toLowerCase();
4893 for(var i = 0, ci; ci = cs[i]; i++){
4894 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==f){
4901 function R(cs, f, id){
4902 if(cs.tagName || cs == document){
4908 var r = [], ri = -1;
4909 for(var i = 0,ci; ci = cs[i]; i++){
4910 if(ci && ci.id == id){
4918 function S(cs, g, h, op, k){
4919 var r = [], ri = -1, st = k=="{";
4920 var f = Roo.DomQuery.operators[op];
4921 for(var i = 0, ci; ci = cs[i]; i++){
4924 a = Roo.DomQuery.getStyle(ci, g);
4926 else if(g == "class" || g == "className"){
4928 }else if(g == "for"){
4930 }else if(g == "href"){
4931 a = ci.getAttribute("href", 2);
4933 a = ci.getAttribute(g);
4935 if((f && f(a, h)) || (!f && a)){
4942 function T(cs, f, g){
4943 return Roo.DomQuery.pseudos[f](cs, g);
4946 // This is for IE MSXML which does not support expandos.
4947 // IE runs the same speed using setAttribute, however FF slows way down
4948 // and Safari completely fails so they need to continue to use expandos.
4949 var U = window.ActiveXObject ? true : false;
4951 // this eval is stop the compressor from
4952 // renaming the variable to something shorter
4954 /** eval:var:batch */
4961 cs[0].setAttribute("_nodup", d);
4963 for(var i = 1, len = cs.length; i < len; i++){
4965 if(!c.getAttribute("_nodup") != d){
4966 c.setAttribute("_nodup", d);
4970 for(var i = 0, len = cs.length; i < len; i++){
4971 cs[i].removeAttribute("_nodup");
4980 var f = cs.length, c, i, r = cs, cj, ri = -1;
4981 if(!f || typeof cs.nodeType != "undefined" || f == 1){
4984 if(U && typeof cs[0].selectSingleNode != "undefined"){
4989 for(i = 1; c = cs[i]; i++){
4994 for(var j = 0; j < i; j++){
4997 for(j = i+1; cj = cs[j]; j++){
5011 for(var i = 0, len = c1.length; i < len; i++){
5012 c1[i].setAttribute("_qdiff", d);
5015 for(var i = 0, len = c2.length; i < len; i++){
5016 if(c2[i].getAttribute("_qdiff") != d){
5017 r[r.length] = c2[i];
5020 for(var i = 0, len = c1.length; i < len; i++){
5021 c1[i].removeAttribute("_qdiff");
5031 if(U && c1[0].selectSingleNode){
5035 for(var i = 0; i < f; i++){
5039 for(var i = 0, len = c2.length; i < len; i++){
5040 if(c2[i]._qdiff != d){
5041 r[r.length] = c2[i];
5047 function e(ns, f, g, id){
5049 var d = g.ownerDocument || g;
5050 return d.getElementById(id);
5054 return R(ns, null, id);
5058 getStyle : function(el, AK){
5059 return Roo.fly(el).getStyle(AK);
5062 * Compiles a selector/xpath query into a reusable function. The returned function
5063 * takes one parameter "root" (optional), which is the context node from where the query should start.
5064 * @param {String} selector The selector/xpath query
5065 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5066 * @return {Function}
5068 compile : function(AL, AM){
5069 AM = AM || "select";
5071 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5073 var tk = Roo.DomQuery.matchers;
5077 // accept leading mode switch
5078 var AP = q.match(E);
5080 fn[fn.length] = 'mode="'+AP[1].replace(C, "")+'";';
5081 q = q.replace(AP[1], "");
5083 // strip leading slashes
5084 while(AL.substr(0, 1)=="/"){
5088 while(q && lq != q){
5090 var tm = q.match(F);
5094 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5096 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5099 q = q.replace(tm[0], "");
5100 }else if(q.substr(0, 1) != '@'){
5101 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5106 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5108 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5111 q = q.replace(tm[0], "");
5114 while(!(mm = q.match(E))){
5115 var matched = false;
5116 for(var j = 0; j < AO; j++){
5118 var m = q.match(t.re);
5120 fn[fn.length] = t.select.replace(D, function(x, i){
5123 q = q.replace(m[0], "");
5128 // prevent infinite loop on bad selector
5130 throw 'Error parsing selector, parsing failed at "' + q + '"';
5134 fn[fn.length] = 'mode="'+mm[1].replace(C, "")+'";';
5135 q = q.replace(mm[1], "");
5139 fn[fn.length] = "return nodup(n);\n}";
5142 * list of variables that need from compression as they are used by eval.
5152 * eval:var:byClassName
5154 * eval:var:byAttribute
5155 * eval:var:attrValue
5163 * Selects a group of elements.
5164 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5165 * @param {Node} root (optional) The start of the query (defaults to document).
5168 select : function(AQ, AR, AS){
5169 if(!AR || AR == document){
5172 if(typeof AR == "string"){
5173 AR = document.getElementById(AR);
5175 var AT = AQ.split(",");
5177 for(var i = 0, len = AT.length; i < len; i++){
5178 var p = AT[i].replace(C, "");
5180 A[p] = Roo.DomQuery.compile(p);
5182 throw p + " is not a valid selector";
5186 if(AJ && AJ != document){
5197 * Selects a single element.
5198 * @param {String} selector The selector/xpath query
5199 * @param {Node} root (optional) The start of the query (defaults to document).
5202 selectNode : function(AV, AW){
5203 return Roo.DomQuery.select(AV, AW)[0];
5207 * Selects the value of a node, optionally replacing null with the defaultValue.
5208 * @param {String} selector The selector/xpath query
5209 * @param {Node} root (optional) The start of the query (defaults to document).
5210 * @param {String} defaultValue
5212 selectValue : function(AX, AY, AZ){
5213 AX = AX.replace(C, "");
5214 if(!valueCache[AX]){
5215 valueCache[AX] = Roo.DomQuery.compile(AX, "select");
5217 var n = valueCache[AX](AY);
5218 n = n[0] ? n[0] : n;
5219 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5220 return ((v === null||v === undefined||v==='') ? AZ : v);
5224 * Selects the value of a node, parsing integers and floats.
5225 * @param {String} selector The selector/xpath query
5226 * @param {Node} root (optional) The start of the query (defaults to document).
5227 * @param {Number} defaultValue
5230 selectNumber : function(Aa, Ab, Ac){
5231 var v = Roo.DomQuery.selectValue(Aa, Ab, Ac || 0);
5232 return parseFloat(v);
5236 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5237 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5238 * @param {String} selector The simple selector to test
5241 is : function(el, ss){
5242 if(typeof el == "string"){
5243 el = document.getElementById(el);
5245 var Ad = (el instanceof Array);
5246 var Ae = Roo.DomQuery.filter(Ad ? el : [el], ss);
5247 return Ad ? (Ae.length == el.length) : (Ae.length > 0);
5251 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5252 * @param {Array} el An array of elements to filter
5253 * @param {String} selector The simple selector to test
5254 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5255 * the selector instead of the ones that match
5258 filter : function(Af, ss, Ag){
5259 ss = ss.replace(C, "");
5260 if(!simpleCache[ss]){
5261 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5263 var Ah = simpleCache[ss](Af);
5264 return Ag ? b(Ah, Af) : Ah;
5268 * Collection of matching regular expressions and code snippets.
5272 select: 'n = byClassName(n, null, " {1} ");'
5274 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5275 select: 'n = byPseudo(n, "{1}", "{2}");'
5277 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5278 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5281 select: 'n = byId(n, null, "{1}");'
5284 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5289 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5290 * 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, > <.
5293 "=" : function(a, v){
5296 "!=" : function(a, v){
5299 "^=" : function(a, v){
5300 return a && a.substr(0, v.length) == v;
5302 "$=" : function(a, v){
5303 return a && a.substr(a.length-v.length) == v;
5305 "*=" : function(a, v){
5306 return a && a.indexOf(v) !== -1;
5308 "%=" : function(a, v){
5309 return (a % v) == 0;
5311 "|=" : function(a, v){
5312 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5314 "~=" : function(a, v){
5315 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5320 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5321 * and the argument (if any) supplied in the selector.
5324 "first-child" : function(c){
5325 var r = [], ri = -1, n;
5326 for(var i = 0, ci; ci = n = c[i]; i++){
5327 while((n = n.previousSibling) && n.nodeType != 1);
5335 "last-child" : function(c){
5336 var r = [], ri = -1, n;
5337 for(var i = 0, ci; ci = n = c[i]; i++){
5338 while((n = n.nextSibling) && n.nodeType != 1);
5346 "nth-child" : function(c, a) {
5347 var r = [], ri = -1;
5348 var m = G.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !H.test(a) && "n+" + a || a);
5349 var f = (m[1] || 1) - 0, l = m[2] - 0;
5350 for(var i = 0, n; n = c[i]; i++){
5351 var pn = n.parentNode;
5352 if (V != pn._batch) {
5354 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5355 if(cn.nodeType == 1){
5363 if (l == 0 || n.nodeIndex == l){
5366 } else if ((n.nodeIndex + l) % f == 0){
5374 "only-child" : function(c){
5375 var r = [], ri = -1;;
5376 for(var i = 0, ci; ci = c[i]; i++){
5377 if(!K(ci) && !J(ci)){
5384 "empty" : function(c){
5385 var r = [], ri = -1;
5386 for(var i = 0, ci; ci = c[i]; i++){
5387 var cns = ci.childNodes, j = 0, cn, empty = true;
5390 if(cn.nodeType == 1 || cn.nodeType == 3){
5402 "contains" : function(c, v){
5403 var r = [], ri = -1;
5404 for(var i = 0, ci; ci = c[i]; i++){
5405 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5412 "nodeValue" : function(c, v){
5413 var r = [], ri = -1;
5414 for(var i = 0, ci; ci = c[i]; i++){
5415 if(ci.firstChild && ci.firstChild.nodeValue == v){
5422 "checked" : function(c){
5423 var r = [], ri = -1;
5424 for(var i = 0, ci; ci = c[i]; i++){
5425 if(ci.checked == true){
5432 "not" : function(c, ss){
5433 return Roo.DomQuery.filter(c, ss, true);
5436 "odd" : function(c){
5437 return this["nth-child"](c, "odd");
5440 "even" : function(c){
5441 return this["nth-child"](c, "even");
5444 "nth" : function(c, a){
5445 return c[a-1] || [];
5448 "first" : function(c){
5452 "last" : function(c){
5453 return c[c.length-1] || [];
5456 "has" : function(c, ss){
5457 var s = Roo.DomQuery.select;
5458 var r = [], ri = -1;
5459 for(var i = 0, ci; ci = c[i]; i++){
5460 if(s(ss, ci).length > 0){
5467 "next" : function(c, ss){
5468 var is = Roo.DomQuery.is;
5469 var r = [], ri = -1;
5470 for(var i = 0, ci; ci = c[i]; i++){
5479 "prev" : function(c, ss){
5480 var is = Roo.DomQuery.is;
5481 var r = [], ri = -1;
5482 for(var i = 0, ci; ci = c[i]; i++){
5495 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5496 * @param {String} path The selector/xpath query
5497 * @param {Node} root (optional) The start of the query (defaults to document).
5502 Roo.query = Roo.DomQuery.select;
5506 * Ext JS Library 1.1.1
5507 * Copyright(c) 2006-2007, Ext JS, LLC.
5509 * Originally Released Under LGPL - original licence link has changed is not relivant.
5512 * <script type="text/javascript">
5516 * @class Roo.util.Observable
5517 * Base class that provides a common interface for publishing events. Subclasses are expected to
5518 * to have a property "events" with all the events defined.<br>
5521 Employee = function(name){
5528 Roo.extend(Employee, Roo.util.Observable);
5530 * @param {Object} config properties to use (incuding events / listeners)
5533 Roo.util.Observable = function(A){
5536 this.addEvents(A.events || {});
5538 delete A.events; // make sure
5545 this.on(this.listeners);
5546 delete this.listeners;
5549 Roo.util.Observable.prototype = {
5551 * @cfg {Object} listeners list of events and functions to call for this object,
5555 'click' : function(e) {
5565 * Fires the specified event with the passed parameters (minus the event name).
5566 * @param {String} eventName
5567 * @param {Object...} args Variable number of parameters are passed to handlers
5568 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5570 fireEvent : function(){
5571 var ce = this.events[arguments[0].toLowerCase()];
5572 if(typeof ce == "object"){
5573 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5580 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5583 * Appends an event handler to this component
5584 * @param {String} eventName The type of event to listen for
5585 * @param {Function} handler The method the event invokes
5586 * @param {Object} scope (optional) The scope in which to execute the handler
5587 * function. The handler function's "this" context.
5588 * @param {Object} options (optional) An object containing handler configuration
5589 * properties. This may contain any of the following properties:<ul>
5590 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5591 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5592 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5593 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5594 * by the specified number of milliseconds. If the event fires again within that time, the original
5595 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5598 * <b>Combining Options</b><br>
5599 * Using the options argument, it is possible to combine different types of listeners:<br>
5601 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5603 el.on('click', this.onClick, this, {
5610 * <b>Attaching multiple handlers in 1 call</b><br>
5611 * The method also allows for a single argument to be passed which is a config object containing properties
5612 * which specify multiple handlers.
5621 fn: this.onMouseOver,
5625 fn: this.onMouseOut,
5631 * Or a shorthand syntax which passes the same scope object to all handlers:
5634 'click': this.onClick,
5635 'mouseover': this.onMouseOver,
5636 'mouseout': this.onMouseOut,
5641 addListener : function(B, fn, C, o){
5642 if(typeof B == "object"){
5645 if(this.filterOptRe.test(e)){
5648 if(typeof o[e] == "function"){
5650 this.addListener(e, o[e], o.scope, o);
5652 // individual options
5653 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5659 o = (!o || typeof o == "boolean") ? {} : o;
5660 B = B.toLowerCase();
5661 var ce = this.events[B] || true;
5662 if(typeof ce == "boolean"){
5663 ce = new Roo.util.Event(this, B);
5664 this.events[B] = ce;
5667 ce.addListener(fn, C, o);
5671 * Removes a listener
5672 * @param {String} eventName The type of event to listen for
5673 * @param {Function} handler The handler to remove
5674 * @param {Object} scope (optional) The scope (this object) for the handler
5676 removeListener : function(D, fn, E){
5677 var ce = this.events[D.toLowerCase()];
5678 if(typeof ce == "object"){
5679 ce.removeListener(fn, E);
5684 * Removes all listeners for this object
5686 purgeListeners : function(){
5687 for(var evt in this.events){
5688 if(typeof this.events[evt] == "object"){
5689 this.events[evt].clearListeners();
5694 relayEvents : function(o, F){
5695 var G = function(H){
5697 return this.fireEvent.apply(this, Roo.combine(H, Array.prototype.slice.call(arguments, 0)));
5700 for(var i = 0, len = F.length; i < len; i++){
5702 if(!this.events[ename]){ this.events[ename] = true; };
5703 o.on(ename, G(ename), this);
5708 * Used to define events on this Observable
5709 * @param {Object} object The object with the events defined
5711 addEvents : function(o){
5716 Roo.applyIf(this.events, o);
5720 * Checks to see if this object has any listeners for a specified event
5721 * @param {String} eventName The name of the event to check for
5722 * @return {Boolean} True if the event is being listened for, else false
5724 hasListener : function(H){
5725 var e = this.events[H];
5726 return typeof e == "object" && e.listeners.length > 0;
5730 * Appends an event handler to this element (shorthand for addListener)
5731 * @param {String} eventName The type of event to listen for
5732 * @param {Function} handler The method the event invokes
5733 * @param {Object} scope (optional) The scope in which to execute the handler
5734 * function. The handler function's "this" context.
5735 * @param {Object} options (optional)
5738 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5740 * Removes a listener (shorthand for removeListener)
5741 * @param {String} eventName The type of event to listen for
5742 * @param {Function} handler The handler to remove
5743 * @param {Object} scope (optional) The scope (this object) for the handler
5746 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5749 * Starts capture on the specified Observable. All events will be passed
5750 * to the supplied function with the event name + standard signature of the event
5751 * <b>before</b> the event is fired. If the supplied function returns false,
5752 * the event will not fire.
5753 * @param {Observable} o The Observable to capture
5754 * @param {Function} fn The function to call
5755 * @param {Object} scope (optional) The scope (this object) for the fn
5758 Roo.util.Observable.capture = function(o, fn, I){
5759 o.fireEvent = o.fireEvent.createInterceptor(fn, I);
5763 * Removes <b>all</b> added captures from the Observable.
5764 * @param {Observable} o The Observable to release
5767 Roo.util.Observable.releaseCapture = function(o){
5768 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5773 var J = function(h, o, M){
5774 var N = new Roo.util.DelayedTask();
5776 N.delay(o.buffer, h, M, Array.prototype.slice.call(arguments, 0));
5780 var K = function(h, e, fn, M){
5782 e.removeListener(fn, M);
5783 return h.apply(M, arguments);
5787 var L = function(h, o, M){
5789 var N = Array.prototype.slice.call(arguments, 0);
5790 setTimeout(function(){
5796 Roo.util.Event = function(M, N){
5799 this.listeners = [];
5802 Roo.util.Event.prototype = {
5803 addListener : function(fn, M, N){
5806 if(!this.isListening(fn, M)){
5807 var l = {fn: fn, scope: M, options: o};
5813 h = K(h, this, fn, M);
5820 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5821 this.listeners.push(l);
5823 this.listeners = this.listeners.slice(0);
5824 this.listeners.push(l);
5829 findListener : function(fn, O){
5831 var ls = this.listeners;
5832 for(var i = 0, len = ls.length; i < len; i++){
5834 if(l.fn == fn && l.scope == O){
5841 isListening : function(fn, P){
5842 return this.findListener(fn, P) != -1;
5845 removeListener : function(fn, Q){
5847 if((R = this.findListener(fn, Q)) != -1){
5849 this.listeners.splice(R, 1);
5851 this.listeners = this.listeners.slice(0);
5852 this.listeners.splice(R, 1);
5859 clearListeners : function(){
5860 this.listeners = [];
5864 var ls = this.listeners, S, T = ls.length;
5867 var args = Array.prototype.slice.call(arguments, 0);
5868 for(var i = 0; i < T; i++){
5870 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5871 this.firing = false;
5876 this.firing = false;
5884 * Ext JS Library 1.1.1
5885 * Copyright(c) 2006-2007, Ext JS, LLC.
5887 * Originally Released Under LGPL - original licence link has changed is not relivant.
5890 * <script type="text/javascript">
5894 * @class Roo.EventManager
5895 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5896 * several useful events directly.
5897 * See {@link Roo.EventObject} for more details on normalized event objects.
5900 Roo.EventManager = function(){
5901 var A, B, C = false;
5903 var E = Roo.lib.Event;
5904 var D = Roo.lib.Dom;
5914 if(Roo.isGecko || Roo.isOpera) {
5915 document.removeEventListener("DOMContentLoaded", J, false);
5918 var defer = document.getElementById("ie-deferred-loader");
5920 defer.onreadystatechange = null;
5921 defer.parentNode.removeChild(defer);
5932 A = new Roo.util.Event();
5933 if(Roo.isGecko || Roo.isOpera) {
5934 document.addEventListener("DOMContentLoaded", J, false);
5936 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5937 var defer = document.getElementById("ie-deferred-loader");
5938 defer.onreadystatechange = function(){
5939 if(this.readyState == "complete"){
5943 }else if(Roo.isSafari){
5944 B = setInterval(function(){
5945 var rs = document.readyState;
5946 if(rs == "complete") {
5952 // no matter what, make sure it fires on load
5953 E.on(window, "load", J);
5956 var L = function(h, o){
5957 var S = new Roo.util.DelayedTask(h);
5959 // create new event object impl so new events don't wipe out properties
5960 e = new Roo.EventObjectImpl(e);
5961 S.delay(o.buffer, h, null, [e]);
5965 var M = function(h, el, S, fn){
5967 Roo.EventManager.removeListener(el, S, fn);
5972 var N = function(h, o){
5974 // create new event object impl so new events don't wipe out properties
5975 e = new Roo.EventObjectImpl(e);
5976 setTimeout(function(){
5982 var O = function(S, T, U, fn, V){
5983 var o = (!U || typeof U == "boolean") ? {} : U;
5984 fn = fn || o.fn; V = V || o.scope;
5985 var el = Roo.getDom(S);
5987 throw "Error listening for \"" + T + '\". Element "' + S + '" doesn\'t exist.';
5989 var h = function(e){
5990 e = Roo.EventObject.setEvent(e);
5993 t = e.getTarget(o.delegate, el);
6000 if(o.stopEvent === true){
6003 if(o.preventDefault === true){
6006 if(o.stopPropagation === true){
6007 e.stopPropagation();
6010 if(o.normalized === false){
6015 fn.call(V || el, e, t, o);
6021 h = M(h, el, T, fn);
6027 fn._handlers = fn._handlers || [];
6028 fn._handlers.push([Roo.id(el), T, h]);
6031 if(T == "mousewheel" && el.addEventListener){ // workaround for jQuery
6032 el.addEventListener("DOMMouseScroll", h, false);
6033 E.on(window, 'unload', function(){
6034 el.removeEventListener("DOMMouseScroll", h, false);
6037 if(T == "mousedown" && el == document){ // fix stopped mousedowns on the document
6038 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6043 var P = function(el, S, fn){
6044 var id = Roo.id(el), T = fn._handlers, hd = fn;
6046 for(var i = 0, len = T.length; i < len; i++){
6048 if(h[0] == id && h[1] == S){
6057 el = Roo.getDom(el);
6058 if(S == "mousewheel" && el.addEventListener){
6059 el.removeEventListener("DOMMouseScroll", hd, false);
6061 if(S == "mousedown" && el == document){ // fix stopped mousedowns on the document
6062 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6066 var Q = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6073 * @scope Roo.EventManager
6078 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6079 * object with a Roo.EventObject
6080 * @param {Function} fn The method the event invokes
6081 * @param {Object} scope An object that becomes the scope of the handler
6082 * @param {boolean} override If true, the obj passed in becomes
6083 * the execution scope of the listener
6084 * @return {Function} The wrapped function
6087 wrap : function(fn, S, T){
6089 Roo.EventObject.setEvent(e);
6090 fn.call(T ? S || window : window, Roo.EventObject, S);
6095 * Appends an event handler to an element (shorthand for addListener)
6096 * @param {String/HTMLElement} element The html element or id to assign the
6097 * @param {String} eventName The type of event to listen for
6098 * @param {Function} handler The method the event invokes
6099 * @param {Object} scope (optional) The scope in which to execute the handler
6100 * function. The handler function's "this" context.
6101 * @param {Object} options (optional) An object containing handler configuration
6102 * properties. This may contain any of the following properties:<ul>
6103 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6104 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6105 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6106 * <li>preventDefault {Boolean} True to prevent the default action</li>
6107 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6108 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6109 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6110 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6111 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6112 * by the specified number of milliseconds. If the event fires again within that time, the original
6113 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6116 * <b>Combining Options</b><br>
6117 * Using the options argument, it is possible to combine different types of listeners:<br>
6119 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6121 el.on('click', this.onClick, this, {
6128 * <b>Attaching multiple handlers in 1 call</b><br>
6129 * The method also allows for a single argument to be passed which is a config object containing properties
6130 * which specify multiple handlers.
6140 fn: this.onMouseOver
6149 * Or a shorthand syntax:<br>
6152 'click' : this.onClick,
6153 'mouseover' : this.onMouseOver,
6154 'mouseout' : this.onMouseOut
6158 addListener : function(U, V, fn, W, X){
6159 if(typeof V == "object"){
6165 if(typeof o[e] == "function"){
6167 O(U, e, o, o[e], o.scope);
6169 // individual options
6175 return O(U, V, X, fn, W);
6179 * Removes an event handler
6181 * @param {String/HTMLElement} element The id or html element to remove the
6183 * @param {String} eventName The type of event
6184 * @param {Function} fn
6185 * @return {Boolean} True if a listener was actually removed
6187 removeListener : function(Y, Z, fn){
6192 * Fires when the document is ready (before onload and before images are loaded). Can be
6193 * accessed shorthanded Roo.onReady().
6194 * @param {Function} fn The method the event invokes
6195 * @param {Object} scope An object that becomes the scope of the handler
6196 * @param {boolean} options
6198 onDocumentReady : function(fn, a, b){
6199 if(C){ // if it already fired
6200 A.addListener(fn, a, b);
6209 A.addListener(fn, a, b);
6213 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6214 * @param {Function} fn The method the event invokes
6215 * @param {Object} scope An object that becomes the scope of the handler
6216 * @param {boolean} options
6218 onWindowResize : function(fn, c, d){
6220 F = new Roo.util.Event();
6221 G = new Roo.util.DelayedTask(function(){
6222 F.fire(D.getViewWidth(), D.getViewHeight());
6224 E.on(window, "resize", function(){
6228 F.fire(D.getViewWidth(), D.getViewHeight());
6233 F.addListener(fn, c, d);
6237 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6238 * @param {Function} fn The method the event invokes
6239 * @param {Object} scope An object that becomes the scope of the handler
6240 * @param {boolean} options
6242 onTextResize : function(fn, f, g){
6244 H = new Roo.util.Event();
6245 var textEl = new Roo.Element(document.createElement('div'));
6246 textEl.dom.className = 'x-text-resize';
6247 textEl.dom.innerHTML = 'X';
6248 textEl.appendTo(document.body);
6249 I = textEl.dom.offsetHeight;
6250 setInterval(function(){
6251 if(textEl.dom.offsetHeight != I){
6252 H.fire(I, I = textEl.dom.offsetHeight);
6254 }, this.textResizeInterval);
6257 H.addListener(fn, f, g);
6261 * Removes the passed window resize listener.
6262 * @param {Function} fn The method the event invokes
6263 * @param {Object} scope The scope of handler
6265 removeResizeListener : function(fn, j){
6267 F.removeListener(fn, j);
6272 fireResize : function(){
6274 F.fire(D.getViewWidth(), D.getViewHeight());
6278 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6282 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6284 textResizeInterval : 50
6289 * @scopeAlias pub=Roo.EventManager
6293 * Appends an event handler to an element (shorthand for addListener)
6294 * @param {String/HTMLElement} element The html element or id to assign the
6295 * @param {String} eventName The type of event to listen for
6296 * @param {Function} handler The method the event invokes
6297 * @param {Object} scope (optional) The scope in which to execute the handler
6298 * function. The handler function's "this" context.
6299 * @param {Object} options (optional) An object containing handler configuration
6300 * properties. This may contain any of the following properties:<ul>
6301 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6302 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6303 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6304 * <li>preventDefault {Boolean} True to prevent the default action</li>
6305 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6306 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6307 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6308 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6309 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6310 * by the specified number of milliseconds. If the event fires again within that time, the original
6311 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6314 * <b>Combining Options</b><br>
6315 * Using the options argument, it is possible to combine different types of listeners:<br>
6317 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6319 el.on('click', this.onClick, this, {
6326 * <b>Attaching multiple handlers in 1 call</b><br>
6327 * The method also allows for a single argument to be passed which is a config object containing properties
6328 * which specify multiple handlers.
6338 fn: this.onMouseOver
6347 * Or a shorthand syntax:<br>
6350 'click' : this.onClick,
6351 'mouseover' : this.onMouseOver,
6352 'mouseout' : this.onMouseOut
6356 R.on = R.addListener;
6357 R.un = R.removeListener;
6359 R.stoppedMouseDownEvent = new Roo.util.Event();
6363 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6364 * @param {Function} fn The method the event invokes
6365 * @param {Object} scope An object that becomes the scope of the handler
6366 * @param {boolean} override If true, the obj passed in becomes
6367 * the execution scope of the listener
6371 Roo.onReady = Roo.EventManager.onDocumentReady;
6373 Roo.onReady(function(){
6374 var bd = Roo.get(document.body);
6379 : Roo.isGecko ? "roo-gecko"
6380 : Roo.isOpera ? "roo-opera"
6381 : Roo.isSafari ? "roo-safari" : ""];
6387 S.push("roo-linux");
6389 if(Roo.isBorderBox){
6390 S.push('roo-border-box');
6392 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6393 var p = bd.dom.parentNode;
6395 p.className += ' roo-strict';
6399 bd.addClass(S.join(' '));
6403 * @class Roo.EventObject
6404 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6405 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6408 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6410 var target = e.getTarget();
6413 var myDiv = Roo.get("myDiv");
6414 myDiv.on("click", handleClick);
6416 Roo.EventManager.on("myDiv", 'click', handleClick);
6417 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6421 Roo.EventObject = function(){
6423 var E = Roo.lib.Event;
6425 // safari keypress events for special keys return bad keycodes
6428 63235 : 39, // right
6431 63276 : 33, // page up
6432 63277 : 34, // page down
6433 63272 : 46, // delete
6438 // normalize button clicks
6439 var U = Roo.isIE ? {1:0,4:1,2:2} :
6440 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6442 Roo.EventObjectImpl = function(e){
6444 this.setEvent(e.browserEvent || e);
6447 Roo.EventObjectImpl.prototype = {
6449 * Used to fix doc tools.
6450 * @scope Roo.EventObject.prototype
6456 /** The normal browser event */
6457 browserEvent : null,
6458 /** The button pressed in a mouse event */
6460 /** True if the shift key was down during the event */
6462 /** True if the control key was down during the event */
6464 /** True if the alt key was down during the event */
6523 setEvent : function(e){
6524 if(e == this || (e && e.browserEvent)){ // already wrapped
6528 this.browserEvent = e;
6530 // normalize buttons
6531 this.button = e.button ? U[e.button] : (e.which ? e.which-1 : -1);
6532 if(e.type == 'click' && this.button == -1){
6537 this.shiftKey = e.shiftKey;
6538 // mac metaKey behaves like ctrlKey
6539 this.ctrlKey = e.ctrlKey || e.metaKey;
6540 this.altKey = e.altKey;
6541 // in getKey these will be normalized for the mac
6542 this.keyCode = e.keyCode;
6543 // keyup warnings on firefox.
6544 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6545 // cache the target for the delayed and or buffered events
6546 this.target = E.getTarget(e);
6548 this.xy = E.getXY(e);
6551 this.shiftKey = false;
6552 this.ctrlKey = false;
6553 this.altKey = false;
6563 * Stop the event (preventDefault and stopPropagation)
6565 stopEvent : function(){
6566 if(this.browserEvent){
6567 if(this.browserEvent.type == 'mousedown'){
6568 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6571 E.stopEvent(this.browserEvent);
6576 * Prevents the browsers default handling of the event.
6578 preventDefault : function(){
6579 if(this.browserEvent){
6580 E.preventDefault(this.browserEvent);
6585 isNavKeyPress : function(){
6586 var k = this.keyCode;
6587 k = Roo.isSafari ? (T[k] || k) : k;
6588 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6591 isSpecialKey : function(){
6592 var k = this.keyCode;
6593 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6594 (k == 16) || (k == 17) ||
6595 (k >= 18 && k <= 20) ||
6596 (k >= 33 && k <= 35) ||
6597 (k >= 36 && k <= 39) ||
6598 (k >= 44 && k <= 45);
6601 * Cancels bubbling of the event.
6603 stopPropagation : function(){
6604 if(this.browserEvent){
6605 if(this.type == 'mousedown'){
6606 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6609 E.stopPropagation(this.browserEvent);
6614 * Gets the key code for the event.
6617 getCharCode : function(){
6618 return this.charCode || this.keyCode;
6622 * Returns a normalized keyCode for the event.
6623 * @return {Number} The key code
6625 getKey : function(){
6626 var k = this.keyCode || this.charCode;
6627 return Roo.isSafari ? (T[k] || k) : k;
6631 * Gets the x coordinate of the event.
6634 getPageX : function(){
6639 * Gets the y coordinate of the event.
6642 getPageY : function(){
6647 * Gets the time of the event.
6650 getTime : function(){
6651 if(this.browserEvent){
6652 return E.getTime(this.browserEvent);
6658 * Gets the page coordinates of the event.
6659 * @return {Array} The xy values like [x, y]
6666 * Gets the target for the event.
6667 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6668 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6669 search as a number or element (defaults to 10 || document.body)
6670 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6671 * @return {HTMLelement}
6673 getTarget : function(V, W, X){
6674 return V ? Roo.fly(this.target).findParent(V, W, X) : this.target;
6677 * Gets the related target.
6678 * @return {HTMLElement}
6680 getRelatedTarget : function(){
6681 if(this.browserEvent){
6682 return E.getRelatedTarget(this.browserEvent);
6688 * Normalizes mouse wheel delta across browsers
6689 * @return {Number} The delta
6691 getWheelDelta : function(){
6692 var e = this.browserEvent;
6694 if(e.wheelDelta){ /* IE/Opera. */
6695 Y = e.wheelDelta/120;
6696 }else if(e.detail){ /* Mozilla case. */
6703 * Returns true if the control, meta, shift or alt key was pressed during this event.
6706 hasModifier : function(){
6707 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6711 * Returns true if the target of this event equals el or is a child of el
6712 * @param {String/HTMLElement/Element} el
6713 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6716 within : function(el, Z){
6717 var t = this[Z ? "getRelatedTarget" : "getTarget"]();
6718 return t && Roo.fly(el).contains(t);
6721 getPoint : function(){
6722 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6726 return new Roo.EventObjectImpl();
6732 * Ext JS Library 1.1.1
6733 * Copyright(c) 2006-2007, Ext JS, LLC.
6735 * Originally Released Under LGPL - original licence link has changed is not relivant.
6738 * <script type="text/javascript">
6742 // was in Composite Element!??!?!
6745 var D = Roo.lib.Dom;
6746 var E = Roo.lib.Event;
6747 var A = Roo.lib.Anim;
6749 // local style camelizing for speed
6751 var C = /(-[a-z])/gi;
6752 var F = function(m, a){ return a.charAt(1).toUpperCase(); };
6753 var G = document.defaultView;
6756 * @class Roo.Element
6757 * Represents an Element in the DOM.<br><br>
6760 var el = Roo.get("my-div");
6763 var el = getEl("my-div");
6765 // or with a DOM element
6766 var el = Roo.get(myDivElement);
6768 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6769 * each call instead of constructing a new one.<br><br>
6770 * <b>Animations</b><br />
6771 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6772 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6774 Option Default Description
6775 --------- -------- ---------------------------------------------
6776 duration .35 The duration of the animation in seconds
6777 easing easeOut The YUI easing method
6778 callback none A function to execute when the anim completes
6779 scope this The scope (this) of the callback function
6781 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6782 * manipulate the animation. Here's an example:
6784 var el = Roo.get("my-div");
6789 // default animation
6790 el.setWidth(100, true);
6792 // animation with some options set
6799 // using the "anim" property to get the Anim object
6805 el.setWidth(100, opt);
6807 if(opt.anim.isAnimated()){
6811 * <b> Composite (Collections of) Elements</b><br />
6812 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6813 * @constructor Create a new Element directly.
6814 * @param {String/HTMLElement} element
6815 * @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).
6817 Roo.Element = function(J, K){
6818 var L = typeof J == "string" ?
6819 document.getElementById(J) : J;
6820 if(!L){ // invalid id/element
6824 if(K !== true && id && Roo.Element.cache[id]){ // element object already exists
6825 return Roo.Element.cache[id];
6836 * The DOM element ID
6839 this.id = id || Roo.id(L);
6842 var El = Roo.Element;
6846 * The element's default display mode (defaults to "")
6849 originalDisplay : "",
6853 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6858 * Sets the element's visibility mode. When setVisible() is called it
6859 * will use this to determine whether to set the visibility or the display property.
6860 * @param visMode Element.VISIBILITY or Element.DISPLAY
6861 * @return {Roo.Element} this
6863 setVisibilityMode : function(J){
6864 this.visibilityMode = J;
6868 * Convenience method for setVisibilityMode(Element.DISPLAY)
6869 * @param {String} display (optional) What to set display to when visible
6870 * @return {Roo.Element} this
6872 enableDisplayMode : function(K){
6873 this.setVisibilityMode(El.DISPLAY);
6874 if(typeof K != "undefined") this.originalDisplay = K;
6879 * 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)
6880 * @param {String} selector The simple selector to test
6881 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6882 search as a number or element (defaults to 10 || document.body)
6883 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6884 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6886 findParent : function(L, M, N){
6887 var p = this.dom, b = document.body, O = 0, dq = Roo.DomQuery, P;
6889 if(typeof M != "number"){
6893 while(p && p.nodeType == 1 && O < M && p != b && p != P){
6895 return N ? Roo.get(p) : p;
6906 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6907 * @param {String} selector The simple selector to test
6908 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6909 search as a number or element (defaults to 10 || document.body)
6910 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6911 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6913 findParentNode : function(Q, R, S){
6914 var p = Roo.fly(this.dom.parentNode, '_internal');
6915 return p ? p.findParent(Q, R, S) : null;
6919 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6920 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6921 * @param {String} selector The simple selector to test
6922 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6923 search as a number or element (defaults to 10 || document.body)
6924 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6926 up : function(T, U){
6927 return this.findParentNode(T, U, true);
6933 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6934 * @param {String} selector The simple selector to test
6935 * @return {Boolean} True if this element matches the selector, else false
6938 return Roo.DomQuery.is(this.dom, V);
6942 * Perform animation on this element.
6943 * @param {Object} args The YUI animation control args
6944 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6945 * @param {Function} onComplete (optional) Function to call when animation completes
6946 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6947 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6948 * @return {Roo.Element} this
6950 animate : function(W, X, Y, Z, c){
6951 this.anim(W, {duration: X, callback: Y, easing: Z}, c);
6956 * @private Internal animation call
6958 anim : function(e, g, h, j, k, cb){
6961 var l = Roo.lib.Anim[h](
6963 (g.duration || j) || .35,
6964 (g.easing || k) || 'easeOut',
6966 Roo.callback(cb, this);
6967 Roo.callback(g.callback, g.scope || this, [this, g]);
6975 // private legacy anim prep
6976 preanim : function(a, i){
6977 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6981 * Removes worthless text nodes
6982 * @param {Boolean} forceReclean (optional) By default the element
6983 * keeps track if it has been cleaned already so
6984 * you can call this over and over. However, if you update the element and
6985 * need to force a reclean, you can pass true.
6987 clean : function(o){
6988 if(this.isCleaned && o !== true){
6992 var d = this.dom, n = d.firstChild, ni = -1;
6994 var nx = n.nextSibling;
6995 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7004 this.isCleaned = true;
7009 calcOffsetsTo : function(el){
7013 if(el.getStyle('position') == 'static'){
7014 el.position('relative');
7019 while(op && op != d && op.tagName != 'HTML'){
7022 op = op.offsetParent;
7025 el.position('static');
7031 * Scrolls this element into view within the passed container.
7032 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7033 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7034 * @return {Roo.Element} this
7036 scrollIntoView : function(u, v){
7037 var c = Roo.getDom(u) || document.body;
7040 var o = this.calcOffsetsTo(c),
7043 b = t+el.offsetHeight,
7044 r = l+el.offsetWidth;
7046 var ch = c.clientHeight;
7047 var ct = parseInt(c.scrollTop, 10);
7048 var cl = parseInt(c.scrollLeft, 10);
7050 var cr = cl + c.clientWidth;
7062 c.scrollLeft = r-c.clientWidth;
7069 scrollChildIntoView : function(w, z){
7070 Roo.fly(w, '_scrollChildIntoView').scrollIntoView(this, z);
7074 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7075 * the new height may not be available immediately.
7076 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7077 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7078 * @param {Function} onComplete (optional) Function to call when animation completes
7079 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7080 * @return {Roo.Element} this
7082 autoHeight : function(AA, AB, AC, AD){
7083 var AE = this.getHeight();
7085 this.setHeight(1); // force clipping
7086 setTimeout(function(){
7087 var AG = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7091 if(typeof AC == "function"){
7095 this.setHeight(AE); // restore original height
7096 this.setHeight(AG, AA, AB, function(){
7098 if(typeof AC == "function") AC();
7099 }.createDelegate(this), AD);
7101 }.createDelegate(this), 0);
7106 * Returns true if this element is an ancestor of the passed element
7107 * @param {HTMLElement/String} el The element to check
7108 * @return {Boolean} True if this element is an ancestor of el, else false
7110 contains : function(el){
7111 if(!el){return false;}
7112 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7116 * Checks whether the element is currently visible using both visibility and display properties.
7117 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7118 * @return {Boolean} True if the element is currently visible, else false
7120 isVisible : function(AF) {
7121 var AG = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7122 if(AF !== true || !AG){
7125 var p = this.dom.parentNode;
7126 while(p && p.tagName.toLowerCase() != "body"){
7127 if(!Roo.fly(p, '_isVisible').isVisible()){
7137 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7138 * @param {String} selector The CSS selector
7139 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7140 * @return {CompositeElement/CompositeElementLite} The composite element
7142 select : function(AH, AI){
7143 return El.select(AH, AI, this.dom);
7147 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7148 * @param {String} selector The CSS selector
7149 * @return {Array} An array of the matched nodes
7151 query : function(AJ, AK){
7152 return Roo.DomQuery.select(AJ, this.dom);
7156 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7157 * @param {String} selector The CSS selector
7158 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7159 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7161 child : function(AL, AM){
7162 var n = Roo.DomQuery.selectNode(AL, this.dom);
7163 return AM ? n : Roo.get(n);
7167 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7168 * @param {String} selector The CSS selector
7169 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7170 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7172 down : function(AN, AO){
7173 var n = Roo.DomQuery.selectNode(" > " + AN, this.dom);
7174 return AO ? n : Roo.get(n);
7178 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7179 * @param {String} group The group the DD object is member of
7180 * @param {Object} config The DD config object
7181 * @param {Object} overrides An object containing methods to override/implement on the DD object
7182 * @return {Roo.dd.DD} The DD object
7184 initDD : function(AP, AQ, AR){
7185 var dd = new Roo.dd.DD(Roo.id(this.dom), AP, AQ);
7186 return Roo.apply(dd, AR);
7190 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7191 * @param {String} group The group the DDProxy object is member of
7192 * @param {Object} config The DDProxy config object
7193 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7194 * @return {Roo.dd.DDProxy} The DDProxy object
7196 initDDProxy : function(AS, AT, AU){
7197 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), AS, AT);
7198 return Roo.apply(dd, AU);
7202 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7203 * @param {String} group The group the DDTarget object is member of
7204 * @param {Object} config The DDTarget config object
7205 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7206 * @return {Roo.dd.DDTarget} The DDTarget object
7208 initDDTarget : function(AV, AW, AX){
7209 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), AV, AW);
7210 return Roo.apply(dd, AX);
7214 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7215 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7216 * @param {Boolean} visible Whether the element is visible
7217 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7218 * @return {Roo.Element} this
7220 setVisible : function(AY, AZ){
7222 if(this.visibilityMode == El.DISPLAY){
7223 this.setDisplayed(AY);
7226 this.dom.style.visibility = AY ? "visible" : "hidden";
7229 // closure for composites
7231 var J = this.visibilityMode;
7233 this.setOpacity(.01);
7234 this.setVisible(true);
7237 this.anim({opacity: { to: (AY?1:0) }},
7238 this.preanim(arguments, 1),
7239 null, .35, 'easeIn', function(){
7241 if(J == El.DISPLAY){
7242 dom.style.display = "none";
7244 dom.style.visibility = "hidden";
7247 Roo.get(dom).setOpacity(1);
7255 * Returns true if display is not "none"
7258 isDisplayed : function() {
7259 return this.getStyle("display") != "none";
7263 * Toggles the element's visibility or display, depending on visibility mode.
7264 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7265 * @return {Roo.Element} this
7267 toggle : function(Aa){
7268 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7273 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7274 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7275 * @return {Roo.Element} this
7277 setDisplayed : function(Ab) {
7278 if(typeof Ab == "boolean"){
7279 Ab = Ab ? this.originalDisplay : "none";
7282 this.setStyle("display", Ab);
7287 * Tries to focus the element. Any exceptions are caught and ignored.
7288 * @return {Roo.Element} this
7290 focus : function() {
7298 * Tries to blur the element. Any exceptions are caught and ignored.
7299 * @return {Roo.Element} this
7309 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7310 * @param {String/Array} className The CSS class to add, or an array of classes
7311 * @return {Roo.Element} this
7313 addClass : function(Ac){
7314 if(Ac instanceof Array){
7315 for(var i = 0, len = Ac.length; i < len; i++) {
7316 this.addClass(Ac[i]);
7319 if(Ac && !this.hasClass(Ac)){
7320 this.dom.className = this.dom.className + " " + Ac;
7327 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7328 * @param {String/Array} className The CSS class to add, or an array of classes
7329 * @return {Roo.Element} this
7331 radioClass : function(Ad){
7332 var Ae = this.dom.parentNode.childNodes;
7333 for(var i = 0; i < Ae.length; i++) {
7335 if(s.nodeType == 1){
7336 Roo.get(s).removeClass(Ad);
7345 * Removes one or more CSS classes from the element.
7346 * @param {String/Array} className The CSS class to remove, or an array of classes
7347 * @return {Roo.Element} this
7349 removeClass : function(Af){
7350 if(!Af || !this.dom.className){
7353 if(Af instanceof Array){
7354 for(var i = 0, len = Af.length; i < len; i++) {
7355 this.removeClass(Af[i]);
7358 if(this.hasClass(Af)){
7359 var re = this.classReCache[Af];
7361 re = new RegExp('(?:^|\\s+)' + Af + '(?:\\s+|$)', "g");
7362 this.classReCache[Af] = re;
7365 this.dom.className =
7366 this.dom.className.replace(re, " ");
7376 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7377 * @param {String} className The CSS class to toggle
7378 * @return {Roo.Element} this
7380 toggleClass : function(Ag){
7381 if(this.hasClass(Ag)){
7382 this.removeClass(Ag);
7390 * Checks if the specified CSS class exists on this element's DOM node.
7391 * @param {String} className The CSS class to check for
7392 * @return {Boolean} True if the class exists, else false
7394 hasClass : function(Ah){
7395 return Ah && (' '+this.dom.className+' ').indexOf(' '+Ah+' ') != -1;
7399 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7400 * @param {String} oldClassName The CSS class to replace
7401 * @param {String} newClassName The replacement CSS class
7402 * @return {Roo.Element} this
7404 replaceClass : function(Ai, Aj){
7405 this.removeClass(Ai);
7411 * Returns an object with properties matching the styles requested.
7412 * For example, el.getStyles('color', 'font-size', 'width') might return
7413 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7414 * @param {String} style1 A style name
7415 * @param {String} style2 A style name
7416 * @param {String} etc.
7417 * @return {Object} The style object
7419 getStyles : function(){
7420 var a = arguments, Ak = a.length, r = {};
7421 for(var i = 0; i < Ak; i++){
7422 r[a[i]] = this.getStyle(a[i]);
7428 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7429 * @param {String} property The style property whose value is returned.
7430 * @return {String} The current value of the style property for this element.
7432 getStyle : function(){
7433 return G && G.getComputedStyle ?
7435 var el = this.dom, v, cs, Am;
7439 if(el.style && (v = el.style[Al])){
7442 if(cs = G.getComputedStyle(el, "")){
7444 Am = B[Al] = Al.replace(C, F);
7451 var el = this.dom, v, cs, Am;
7452 if(Al == 'opacity'){
7453 if(typeof el.style.filter == 'string'){
7454 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7456 var fv = parseFloat(m[1]);
7458 return fv ? fv / 100 : 0;
7463 }else if(Al == 'float'){
7467 Am = B[Al] = Al.replace(C, F);
7469 if(v = el.style[Am]){
7472 if(cs = el.currentStyle){
7480 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7481 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7482 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7483 * @return {Roo.Element} this
7485 setStyle : function(Al, Am){
7486 if(typeof Al == "string"){
7488 if(!(camel = B[Al])){
7489 camel = B[Al] = Al.replace(C, F);
7491 if(camel == 'opacity') {
7492 this.setOpacity(Am);
7494 this.dom.style[camel] = Am;
7497 for(var style in Al){
7498 if(typeof Al[style] != "function"){
7499 this.setStyle(style, Al[style]);
7507 * More flexible version of {@link #setStyle} for setting style properties.
7508 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7509 * a function which returns such a specification.
7510 * @return {Roo.Element} this
7512 applyStyles : function(An){
7513 Roo.DomHelper.applyStyles(this.dom, An);
7518 * 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).
7519 * @return {Number} The X position of the element
7522 return D.getX(this.dom);
7526 * 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).
7527 * @return {Number} The Y position of the element
7530 return D.getY(this.dom);
7534 * 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).
7535 * @return {Array} The XY position of the element
7538 return D.getXY(this.dom);
7542 * 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).
7543 * @param {Number} The X position of the element
7544 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7545 * @return {Roo.Element} this
7547 setX : function(x, Ao){
7549 D.setX(this.dom, x);
7551 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7557 * 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).
7558 * @param {Number} The Y position of the element
7559 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7560 * @return {Roo.Element} this
7562 setY : function(y, Ap){
7564 D.setY(this.dom, y);
7566 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7572 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7573 * @param {String} left The left CSS property value
7574 * @return {Roo.Element} this
7576 setLeft : function(Aq){
7577 this.setStyle("left", this.addUnits(Aq));
7582 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7583 * @param {String} top The top CSS property value
7584 * @return {Roo.Element} this
7586 setTop : function(Ar){
7587 this.setStyle("top", this.addUnits(Ar));
7592 * Sets the element's CSS right style.
7593 * @param {String} right The right CSS property value
7594 * @return {Roo.Element} this
7596 setRight : function(As){
7597 this.setStyle("right", this.addUnits(As));
7602 * Sets the element's CSS bottom style.
7603 * @param {String} bottom The bottom CSS property value
7604 * @return {Roo.Element} this
7606 setBottom : function(At){
7607 this.setStyle("bottom", this.addUnits(At));
7612 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7613 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7614 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7615 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7616 * @return {Roo.Element} this
7618 setXY : function(Au, Av){
7620 D.setXY(this.dom, Au);
7622 this.anim({points: {to: Au}}, this.preanim(arguments, 1), 'motion');
7628 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7629 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7630 * @param {Number} x X value for new position (coordinates are page-based)
7631 * @param {Number} y Y value for new position (coordinates are page-based)
7632 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7633 * @return {Roo.Element} this
7635 setLocation : function(x, y, Aw){
7636 this.setXY([x, y], this.preanim(arguments, 2));
7641 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7642 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7643 * @param {Number} x X value for new position (coordinates are page-based)
7644 * @param {Number} y Y value for new position (coordinates are page-based)
7645 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7646 * @return {Roo.Element} this
7648 moveTo : function(x, y, Ax){
7649 this.setXY([x, y], this.preanim(arguments, 2));
7654 * Returns the region of the given element.
7655 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7656 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7658 getRegion : function(){
7659 return D.getRegion(this.dom);
7663 * Returns the offset height of the element
7664 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7665 * @return {Number} The element's height
7667 getHeight : function(Ay){
7668 var h = this.dom.offsetHeight || 0;
7669 return Ay !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7673 * Returns the offset width of the element
7674 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7675 * @return {Number} The element's width
7677 getWidth : function(Az){
7678 var w = this.dom.offsetWidth || 0;
7679 return Az !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7683 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7684 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7685 * if a height has not been set using CSS.
7688 getComputedHeight : function(){
7689 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7691 h = parseInt(this.getStyle('height'), 10) || 0;
7692 if(!this.isBorderBox()){
7693 h += this.getFrameWidth('tb');
7700 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7701 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7702 * if a width has not been set using CSS.
7705 getComputedWidth : function(){
7706 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7708 w = parseInt(this.getStyle('width'), 10) || 0;
7709 if(!this.isBorderBox()){
7710 w += this.getFrameWidth('lr');
7717 * Returns the size of the element.
7718 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7719 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7721 getSize : function(A0){
7722 return {width: this.getWidth(A0), height: this.getHeight(A0)};
7726 * Returns the width and height of the viewport.
7727 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7729 getViewSize : function(){
7730 var d = this.dom, A1 = document, aw = 0, ah = 0;
7731 if(d == A1 || d == A1.body){
7732 return {width : D.getViewWidth(), height: D.getViewHeight()};
7735 width : d.clientWidth,
7736 height: d.clientHeight
7742 * Returns the value of the "value" attribute
7743 * @param {Boolean} asNumber true to parse the value as a number
7744 * @return {String/Number}
7746 getValue : function(A2){
7747 return A2 ? parseInt(this.dom.value, 10) : this.dom.value;
7751 adjustWidth : function(A3){
7752 if(typeof A3 == "number"){
7753 if(this.autoBoxAdjust && !this.isBorderBox()){
7754 A3 -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7764 adjustHeight : function(A4){
7765 if(typeof A4 == "number"){
7766 if(this.autoBoxAdjust && !this.isBorderBox()){
7767 A4 -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7777 * Set the width of the element
7778 * @param {Number} width The new width
7779 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7780 * @return {Roo.Element} this
7782 setWidth : function(A5, A6){
7783 A5 = this.adjustWidth(A5);
7785 this.dom.style.width = this.addUnits(A5);
7787 this.anim({width: {to: A5}}, this.preanim(arguments, 1));
7793 * Set the height of the element
7794 * @param {Number} height The new height
7795 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7796 * @return {Roo.Element} this
7798 setHeight : function(A7, A8){
7799 A7 = this.adjustHeight(A7);
7801 this.dom.style.height = this.addUnits(A7);
7803 this.anim({height: {to: A7}}, this.preanim(arguments, 1));
7809 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7810 * @param {Number} width The new width
7811 * @param {Number} height The new height
7812 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7813 * @return {Roo.Element} this
7815 setSize : function(A9, BA, BB){
7816 if(typeof A9 == "object"){ // in case of object from getSize()
7817 BA = A9.height; A9 = A9.width;
7820 A9 = this.adjustWidth(A9); BA = this.adjustHeight(BA);
7822 this.dom.style.width = this.addUnits(A9);
7823 this.dom.style.height = this.addUnits(BA);
7825 this.anim({width: {to: A9}, height: {to: BA}}, this.preanim(arguments, 2));
7831 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7832 * @param {Number} x X value for new position (coordinates are page-based)
7833 * @param {Number} y Y value for new position (coordinates are page-based)
7834 * @param {Number} width The new width
7835 * @param {Number} height The new height
7836 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7837 * @return {Roo.Element} this
7839 setBounds : function(x, y, BC, BD, BE){
7841 this.setSize(BC, BD);
7842 this.setLocation(x, y);
7844 BC = this.adjustWidth(BC); BD = this.adjustHeight(BD);
7845 this.anim({points: {to: [x, y]}, width: {to: BC}, height: {to: BD}},
7846 this.preanim(arguments, 4), 'motion');
7852 * 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.
7853 * @param {Roo.lib.Region} region The region to fill
7854 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7855 * @return {Roo.Element} this
7857 setRegion : function(BF, BG){
7858 this.setBounds(BF.left, BF.top, BF.right-BF.left, BF.bottom-BF.top, this.preanim(arguments, 1));
7863 * Appends an event handler
7865 * @param {String} eventName The type of event to append
7866 * @param {Function} fn The method the event invokes
7867 * @param {Object} scope (optional) The scope (this object) of the fn
7868 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7870 addListener : function(BH, fn, BI, BJ){
7871 Roo.EventManager.on(this.dom, BH, fn, BI || this, BJ);
7875 * Removes an event handler from this element
7876 * @param {String} eventName the type of event to remove
7877 * @param {Function} fn the method the event invokes
7878 * @return {Roo.Element} this
7880 removeListener : function(BK, fn){
7881 Roo.EventManager.removeListener(this.dom, BK, fn);
7886 * Removes all previous added listeners from this element
7887 * @return {Roo.Element} this
7889 removeAllListeners : function(){
7890 E.purgeElement(this.dom);
7894 relayEvent : function(BL, BM){
7895 this.on(BL, function(e){
7896 BM.fireEvent(BL, e);
7901 * Set the opacity of the element
7902 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7903 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7904 * @return {Roo.Element} this
7906 setOpacity : function(BN, BO){
7908 var s = this.dom.style;
7911 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7912 (BN == 1 ? "" : "alpha(opacity=" + BN * 100 + ")");
7917 this.anim({opacity: {to: BN}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7923 * Gets the left X coordinate
7924 * @param {Boolean} local True to get the local css position instead of page coordinate
7927 getLeft : function(BP){
7931 return parseInt(this.getStyle("left"), 10) || 0;
7936 * Gets the right X coordinate of the element (element X position + element width)
7937 * @param {Boolean} local True to get the local css position instead of page coordinate
7940 getRight : function(BQ){
7942 return this.getX() + this.getWidth();
7944 return (this.getLeft(true) + this.getWidth()) || 0;
7949 * Gets the top Y coordinate
7950 * @param {Boolean} local True to get the local css position instead of page coordinate
7953 getTop : function(BR) {
7957 return parseInt(this.getStyle("top"), 10) || 0;
7962 * Gets the bottom Y coordinate of the element (element Y position + element height)
7963 * @param {Boolean} local True to get the local css position instead of page coordinate
7966 getBottom : function(BS){
7968 return this.getY() + this.getHeight();
7970 return (this.getTop(true) + this.getHeight()) || 0;
7975 * Initializes positioning on this element. If a desired position is not passed, it will make the
7976 * the element positioned relative IF it is not already positioned.
7977 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7978 * @param {Number} zIndex (optional) The zIndex to apply
7979 * @param {Number} x (optional) Set the page X position
7980 * @param {Number} y (optional) Set the page Y position
7982 position : function(BT, BU, x, y){
7984 if(this.getStyle('position') == 'static'){
7985 this.setStyle('position', 'relative');
7988 this.setStyle("position", BT);
7991 this.setStyle("z-index", BU);
7993 if(x !== undefined && y !== undefined){
7995 }else if(x !== undefined){
7997 }else if(y !== undefined){
8003 * Clear positioning back to the default when the document was loaded
8004 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8005 * @return {Roo.Element} this
8007 clearPositioning : function(BV){
8015 "position" : "static"
8021 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8022 * snapshot before performing an update and then restoring the element.
8025 getPositioning : function(){
8026 var l = this.getStyle("left");
8027 var t = this.getStyle("top");
8029 "position" : this.getStyle("position"),
8031 "right" : l ? "" : this.getStyle("right"),
8033 "bottom" : t ? "" : this.getStyle("bottom"),
8034 "z-index" : this.getStyle("z-index")
8039 * Gets the width of the border(s) for the specified side(s)
8040 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8041 * passing lr would get the border (l)eft width + the border (r)ight width.
8042 * @return {Number} The width of the sides passed added together
8044 getBorderWidth : function(BW){
8045 return this.addStyles(BW, El.borders);
8049 * Gets the width of the padding(s) for the specified side(s)
8050 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8051 * passing lr would get the padding (l)eft + the padding (r)ight.
8052 * @return {Number} The padding of the sides passed added together
8054 getPadding : function(BX){
8055 return this.addStyles(BX, El.paddings);
8059 * Set positioning with an object returned by getPositioning().
8060 * @param {Object} posCfg
8061 * @return {Roo.Element} this
8063 setPositioning : function(pc){
8064 this.applyStyles(pc);
8065 if(pc.right == "auto"){
8066 this.dom.style.right = "";
8068 if(pc.bottom == "auto"){
8069 this.dom.style.bottom = "";
8075 fixDisplay : function(){
8076 if(this.getStyle("display") == "none"){
8077 this.setStyle("visibility", "hidden");
8078 this.setStyle("display", this.originalDisplay); // first try reverting to default
8079 if(this.getStyle("display") == "none"){ // if that fails, default to block
8080 this.setStyle("display", "block");
8086 * Quick set left and top adding default units
8087 * @param {String} left The left CSS property value
8088 * @param {String} top The top CSS property value
8089 * @return {Roo.Element} this
8091 setLeftTop : function(BY, BZ){
8092 this.dom.style.left = this.addUnits(BY);
8093 this.dom.style.top = this.addUnits(BZ);
8098 * Move this element relative to its current position.
8099 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8100 * @param {Number} distance How far to move the element in pixels
8101 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8102 * @return {Roo.Element} this
8104 move : function(Ba, Bb, Bc){
8105 var xy = this.getXY();
8106 Ba = Ba.toLowerCase();
8110 this.moveTo(xy[0]-Bb, xy[1], this.preanim(arguments, 2));
8114 this.moveTo(xy[0]+Bb, xy[1], this.preanim(arguments, 2));
8119 this.moveTo(xy[0], xy[1]-Bb, this.preanim(arguments, 2));
8124 this.moveTo(xy[0], xy[1]+Bb, this.preanim(arguments, 2));
8131 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8132 * @return {Roo.Element} this
8135 if(!this.isClipped){
8136 this.isClipped = true;
8137 this.originalClip = {
8138 "o": this.getStyle("overflow"),
8139 "x": this.getStyle("overflow-x"),
8140 "y": this.getStyle("overflow-y")
8142 this.setStyle("overflow", "hidden");
8143 this.setStyle("overflow-x", "hidden");
8144 this.setStyle("overflow-y", "hidden");
8150 * Return clipping (overflow) to original clipping before clip() was called
8151 * @return {Roo.Element} this
8153 unclip : function(){
8155 this.isClipped = false;
8156 var o = this.originalClip;
8157 if(o.o){this.setStyle("overflow", o.o);}
8158 if(o.x){this.setStyle("overflow-x", o.x);}
8159 if(o.y){this.setStyle("overflow-y", o.y);}
8166 * Gets the x,y coordinates specified by the anchor position on the element.
8167 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8168 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8169 * {width: (target width), height: (target height)} (defaults to the element's current size)
8170 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8171 * @return {Array} [x, y] An array containing the element's x and y coordinates
8173 getAnchorXY : function(Bd, Be, s){
8174 //Passing a different size is useful for pre-calculating anchors,
8175 //especially for anchored animations that change the el size.
8177 var w, h, vp = false;
8180 if(d == document.body || d == document){
8182 w = D.getViewWidth(); h = D.getViewHeight();
8184 w = this.getWidth(); h = this.getHeight();
8187 w = s.width; h = s.height;
8189 var x = 0, y = 0, r = Math.round;
8190 switch((Bd || "tl").toLowerCase()){
8232 var sc = this.getScroll();
8233 return [x + sc.left, y + sc.top];
8235 //Add the element's offset xy
8236 var o = this.getXY();
8237 return [x+o[0], y+o[1]];
8241 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8242 * supported position values.
8243 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8244 * @param {String} position The position to align to.
8245 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8246 * @return {Array} [x, y]
8248 getAlignToXY : function(el, p, o){
8252 throw "Element.alignTo with an element that doesn't exist";
8254 var c = false; //constrain to viewport
8255 var p1 = "", p2 = "";
8262 }else if(p.indexOf("-") == -1){
8266 p = p.toLowerCase();
8267 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8269 throw "Element.alignTo with an invalid alignment " + p;
8272 p1 = m[1]; p2 = m[2]; c = !!m[3];
8274 //Subtract the aligned el's internal xy from the target's offset xy
8275 //plus custom offset to get the aligned el's new offset xy
8276 var a1 = this.getAnchorXY(p1, true);
8277 var a2 = el.getAnchorXY(p2, false);
8278 var x = a2[0] - a1[0] + o[0];
8279 var y = a2[1] - a1[1] + o[1];
8281 //constrain the aligned el to viewport if necessary
8282 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8283 // 5px of margin for ie
8284 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8286 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8287 //perpendicular to the vp border, allow the aligned el to slide on that border,
8288 //otherwise swap the aligned el to the opposite border of the target.
8289 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8290 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8291 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8292 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8295 var scrollX = (A1.documentElement.scrollLeft || A1.body.scrollLeft || 0)+5;
8296 var scrollY = (A1.documentElement.scrollTop || A1.body.scrollTop || 0)+5;
8298 if((x+w) > dw + scrollX){
8299 x = swapX ? r.left-w : dw+scrollX-w;
8302 x = swapX ? r.right : scrollX;
8304 if((y+h) > dh + scrollY){
8305 y = swapY ? r.top-h : dh+scrollY-h;
8308 y = swapY ? r.bottom : scrollY;
8315 getConstrainToXY : function(){
8316 var os = {top:0, left:0, bottom:0, right: 0};
8318 return function(el, Bf, Bg, Bh){
8320 Bg = Bg ? Roo.applyIf(Bg, os) : os;
8322 var vw, vh, vx = 0, vy = 0;
8323 if(el.dom == document.body || el.dom == document){
8324 vw = Roo.lib.Dom.getViewWidth();
8325 vh = Roo.lib.Dom.getViewHeight();
8327 vw = el.dom.clientWidth;
8328 vh = el.dom.clientHeight;
8330 var vxy = el.getXY();
8336 var s = el.getScroll();
8338 vx += Bg.left + s.left;
8339 vy += Bg.top + s.top;
8347 var xy = Bh || (!Bf ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8348 var x = xy[0], y = xy[1];
8349 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8351 // only move it if it needs it
8354 // first validate right/bottom
8363 // then make sure top/left isn't negative
8372 return Bi ? [x, y] : false;
8377 adjustForConstraints : function(xy, Bf, Bg){
8378 return this.getConstrainToXY(Bf || document, false, Bg, xy) || xy;
8382 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8383 * document it aligns it to the viewport.
8384 * The position parameter is optional, and can be specified in any one of the following formats:
8386 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8387 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8388 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8389 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8390 * <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
8391 * element's anchor point, and the second value is used as the target's anchor point.</li>
8393 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8394 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8395 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8396 * that specified in order to enforce the viewport constraints.
8397 * Following are all of the supported anchor positions:
8400 ----- -----------------------------
8401 tl The top left corner (default)
8402 t The center of the top edge
8403 tr The top right corner
8404 l The center of the left edge
8405 c In the center of the element
8406 r The center of the right edge
8407 bl The bottom left corner
8408 b The center of the bottom edge
8409 br The bottom right corner
8413 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8414 el.alignTo("other-el");
8416 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8417 el.alignTo("other-el", "tr?");
8419 // align the bottom right corner of el with the center left edge of other-el
8420 el.alignTo("other-el", "br-l?");
8422 // align the center of el with the bottom left corner of other-el and
8423 // adjust the x position by -6 pixels (and the y position by 0)
8424 el.alignTo("other-el", "c-bl", [-6, 0]);
8426 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8427 * @param {String} position The position to align to.
8428 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8429 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8430 * @return {Roo.Element} this
8432 alignTo : function(Bh, Bi, Bj, Bk){
8433 var xy = this.getAlignToXY(Bh, Bi, Bj);
8434 this.setXY(xy, this.preanim(arguments, 3));
8439 * Anchors an element to another element and realigns it when the window is resized.
8440 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8441 * @param {String} position The position to align to.
8442 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8443 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8444 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8445 * is a number, it is used as the buffer delay (defaults to 50ms).
8446 * @param {Function} callback The function to call after the animation finishes
8447 * @return {Roo.Element} this
8449 anchorTo : function(el, Bl, Bm, Bn, Bo, Bp){
8450 var Bq = function(){
8451 this.alignTo(el, Bl, Bm, Bn);
8452 Roo.callback(Bp, this);
8454 Roo.EventManager.onWindowResize(Bq, this);
8456 if(tm != 'undefined'){
8457 Roo.EventManager.on(window, 'scroll', Bq, this,
8458 {buffer: tm == 'number' ? Bo : 50});
8461 Bq.call(this); // align immediately
8465 * Clears any opacity settings from this element. Required in some cases for IE.
8466 * @return {Roo.Element} this
8468 clearOpacity : function(){
8469 if (window.ActiveXObject) {
8470 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8471 this.dom.style.filter = "";
8474 this.dom.style.opacity = "";
8475 this.dom.style["-moz-opacity"] = "";
8476 this.dom.style["-khtml-opacity"] = "";
8482 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8483 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8484 * @return {Roo.Element} this
8486 hide : function(Br){
8487 this.setVisible(false, this.preanim(arguments, 0));
8492 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8493 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8494 * @return {Roo.Element} this
8496 show : function(Bs){
8497 this.setVisible(true, this.preanim(arguments, 0));
8502 * @private Test if size has a unit, otherwise appends the default
8504 addUnits : function(Bt){
8505 return Roo.Element.addUnits(Bt, this.defaultUnit);
8509 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8510 * @return {Roo.Element} this
8512 beginMeasure : function(){
8514 if(el.offsetWidth || el.offsetHeight){
8515 return this; // offsets work already
8518 var p = this.dom, b = document.body; // start with this element
8519 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8520 var pe = Roo.get(p);
8521 if(pe.getStyle('display') == 'none'){
8522 Bu.push({el: p, visibility: pe.getStyle("visibility")});
8523 p.style.visibility = "hidden";
8524 p.style.display = "block";
8530 this._measureChanged = Bu;
8536 * Restores displays to before beginMeasure was called
8537 * @return {Roo.Element} this
8539 endMeasure : function(){
8540 var Bv = this._measureChanged;
8542 for(var i = 0, Ak = Bv.length; i < Ak; i++) {
8544 r.el.style.visibility = r.visibility;
8545 r.el.style.display = "none";
8548 this._measureChanged = null;
8554 * Update the innerHTML of this element, optionally searching for and processing scripts
8555 * @param {String} html The new HTML
8556 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8557 * @param {Function} callback For async script loading you can be noticed when the update completes
8558 * @return {Roo.Element} this
8560 update : function(Bw, Bx, By){
8561 if(typeof Bw == "undefined"){
8565 this.dom.innerHTML = Bw;
8566 if(typeof By == "function"){
8574 Bw += '<span id="' + id + '"></span>';
8576 E.onAvailable(id, function(){
8577 var hd = document.getElementsByTagName("head")[0];
8578 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8579 var B0 = /\ssrc=([\'\"])(.*?)\1/i;
8580 var B1 = /\stype=([\'\"])(.*?)\1/i;
8583 while(B2 = re.exec(Bw)){
8585 var srcMatch = attrs ? attrs.match(B0) : false;
8586 if(srcMatch && srcMatch[2]){
8587 var s = document.createElement("script");
8588 s.src = srcMatch[2];
8589 var typeMatch = attrs.match(B1);
8590 if(typeMatch && typeMatch[2]){
8591 s.type = typeMatch[2];
8595 }else if(B2[2] && B2[2].length > 0){
8596 if(window.execScript) {
8597 window.execScript(B2[2]);
8609 var el = document.getElementById(id);
8610 if(el){el.parentNode.removeChild(el);}
8611 if(typeof By == "function"){
8615 Bz.innerHTML = Bw.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8620 * Direct access to the UpdateManager update() method (takes the same parameters).
8621 * @param {String/Function} url The url for this request or a function to call to get the url
8622 * @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}
8623 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8624 * @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.
8625 * @return {Roo.Element} this
8628 var um = this.getUpdateManager();
8629 um.update.apply(um, arguments);
8634 * Gets this element's UpdateManager
8635 * @return {Roo.UpdateManager} The UpdateManager
8637 getUpdateManager : function(){
8638 if(!this.updateManager){
8639 this.updateManager = new Roo.UpdateManager(this);
8641 return this.updateManager;
8645 * Disables text selection for this element (normalized across browsers)
8646 * @return {Roo.Element} this
8648 unselectable : function(){
8649 this.dom.unselectable = "on";
8650 this.swallowEvent("selectstart", true);
8651 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8652 this.addClass("x-unselectable");
8657 * Calculates the x, y to center this element on the screen
8658 * @return {Array} The x, y values [x, y]
8660 getCenterXY : function(){
8661 return this.getAlignToXY(document, 'c-c');
8665 * Centers the Element in either the viewport, or another Element.
8666 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8668 center : function(B0){
8669 this.alignTo(B0 || document, 'c-c');
8674 * Tests various css rules/browsers to determine if this element uses a border box
8677 isBorderBox : function(){
8678 return I[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8682 * Return a box {x, y, width, height} that can be used to set another elements
8683 * size/location to match this element.
8684 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8685 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8686 * @return {Object} box An object in the format {x, y, width, height}
8688 getBox : function(B1, B2){
8693 var BY = parseInt(this.getStyle("left"), 10) || 0;
8694 var BZ = parseInt(this.getStyle("top"), 10) || 0;
8697 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8699 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8701 var l = this.getBorderWidth("l")+this.getPadding("l");
8702 var r = this.getBorderWidth("r")+this.getPadding("r");
8703 var t = this.getBorderWidth("t")+this.getPadding("t");
8704 var b = this.getBorderWidth("b")+this.getPadding("b");
8705 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)};
8708 bx.right = bx.x + bx.width;
8709 bx.bottom = bx.y + bx.height;
8714 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8715 for more information about the sides.
8716 * @param {String} sides
8719 getFrameWidth : function(B3, B4){
8720 return B4 && Roo.isBorderBox ? 0 : (this.getPadding(B3) + this.getBorderWidth(B3));
8724 * 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.
8725 * @param {Object} box The box to fill {x, y, width, height}
8726 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8727 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8728 * @return {Roo.Element} this
8730 setBox : function(B5, B6, B7){
8731 var w = B5.width, h = B5.height;
8732 if((B6 && !this.autoBoxAdjust) && !this.isBorderBox()){
8733 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8734 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8737 this.setBounds(B5.x, B5.y, w, h, this.preanim(arguments, 2));
8742 * Forces the browser to repaint this element
8743 * @return {Roo.Element} this
8745 repaint : function(){
8747 this.addClass("x-repaint");
8748 setTimeout(function(){
8749 Roo.get(B8).removeClass("x-repaint");
8755 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8756 * then it returns the calculated width of the sides (see getPadding)
8757 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8758 * @return {Object/Number}
8760 getMargins : function(B9){
8763 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8764 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8765 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8766 right: parseInt(this.getStyle("margin-right"), 10) || 0
8769 return this.addStyles(B9, El.margins);
8774 addStyles : function(CA, CB){
8776 for(var i = 0, Ak = CA.length; i < Ak; i++){
8777 v = this.getStyle(CB[CA.charAt(i)]);
8779 w = parseInt(v, 10);
8787 * Creates a proxy element of this element
8788 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8789 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8790 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8791 * @return {Roo.Element} The new proxy element
8793 createProxy : function(CD, CE, CF){
8795 CE = Roo.getDom(CE);
8800 CD = typeof CD == "object" ?
8801 CD : {tag : "div", cls: CD};
8802 var CG = Roo.DomHelper.append(CE, CD, true);
8804 CG.setBox(this.getBox());
8810 * Puts a mask over this element to disable user interaction. Requires core.css.
8811 * This method can only be applied to elements which accept child nodes.
8812 * @param {String} msg (optional) A message to display in the mask
8813 * @param {String} msgCls (optional) A css class to apply to the msg element
8814 * @return {Element} The mask element
8816 mask : function(CH, CI){
8817 if(this.getStyle("position") == "static"){
8818 this.setStyle("position", "relative");
8821 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8824 this.addClass("x-masked");
8825 this._mask.setDisplayed(true);
8826 if(typeof CH == 'string'){
8828 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8830 var mm = this._maskMsg;
8831 mm.dom.className = CI ? "roo-el-mask-msg " + CI : "roo-el-mask-msg";
8832 mm.dom.firstChild.innerHTML = CH;
8833 mm.setDisplayed(true);
8836 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8837 this._mask.setHeight(this.getHeight());
8843 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8844 * it is cached for reuse.
8846 unmask : function(CJ){
8849 this._mask.remove();
8852 this._maskMsg.remove();
8853 delete this._maskMsg;
8856 this._mask.setDisplayed(false);
8858 this._maskMsg.setDisplayed(false);
8863 this.removeClass("x-masked");
8867 * Returns true if this element is masked
8870 isMasked : function(){
8871 return this._mask && this._mask.isVisible();
8875 * Creates an iframe shim for this element to keep selects and other windowed objects from
8877 * @return {Roo.Element} The new shim element
8879 createShim : function(){
8880 var el = document.createElement('iframe');
8881 el.frameBorder = 'no';
8882 el.className = 'roo-shim';
8883 if(Roo.isIE && Roo.isSecure){
8884 el.src = Roo.SSL_SECURE_URL;
8886 var CK = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8887 CK.autoBoxAdjust = false;
8892 * Removes this element from the DOM and deletes it from the cache
8894 remove : function(){
8895 if(this.dom.parentNode){
8896 this.dom.parentNode.removeChild(this.dom);
8898 delete El.cache[this.dom.id];
8902 * Sets up event handlers to add and remove a css class when the mouse is over this element
8903 * @param {String} className
8904 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8905 * mouseout events for children elements
8906 * @return {Roo.Element} this
8908 addClassOnOver : function(CL, CM){
8909 this.on("mouseover", function(){
8910 Roo.fly(this, '_internal').addClass(CL);
8912 var CN = function(e){
8913 if(CM !== true || !e.within(this, true)){
8914 Roo.fly(this, '_internal').removeClass(CL);
8917 this.on("mouseout", CN, this.dom);
8922 * Sets up event handlers to add and remove a css class when this element has the focus
8923 * @param {String} className
8924 * @return {Roo.Element} this
8926 addClassOnFocus : function(CO){
8927 this.on("focus", function(){
8928 Roo.fly(this, '_internal').addClass(CO);
8930 this.on("blur", function(){
8931 Roo.fly(this, '_internal').removeClass(CO);
8936 * 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)
8937 * @param {String} className
8938 * @return {Roo.Element} this
8940 addClassOnClick : function(CP){
8942 this.on("mousedown", function(){
8943 Roo.fly(CQ, '_internal').addClass(CP);
8944 var d = Roo.get(document);
8945 var fn = function(){
8946 Roo.fly(CQ, '_internal').removeClass(CP);
8947 d.removeListener("mouseup", fn);
8949 d.on("mouseup", fn);
8955 * Stops the specified event from bubbling and optionally prevents the default action
8956 * @param {String} eventName
8957 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8958 * @return {Roo.Element} this
8960 swallowEvent : function(CR, CS){
8961 var fn = function(e){
8962 e.stopPropagation();
8967 if(CR instanceof Array){
8968 for(var i = 0, Ak = CR.length; i < Ak; i++){
8981 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8984 * Sizes this element to its parent element's dimensions performing
8985 * neccessary box adjustments.
8986 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8987 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8988 * @return {Roo.Element} this
8990 fitToParent : function(CT, CU) {
8991 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8992 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8993 if (CT === true && !this.dom.parentNode) { // check if this Element still exists
8996 var p = Roo.get(CU || this.dom.parentNode);
8997 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8999 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, CU]);
9000 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9006 * Gets the next sibling, skipping text nodes
9007 * @return {HTMLElement} The next sibling or null
9009 getNextSibling : function(){
9010 var n = this.dom.nextSibling;
9011 while(n && n.nodeType != 1){
9018 * Gets the previous sibling, skipping text nodes
9019 * @return {HTMLElement} The previous sibling or null
9021 getPrevSibling : function(){
9022 var n = this.dom.previousSibling;
9023 while(n && n.nodeType != 1){
9024 n = n.previousSibling;
9031 * Appends the passed element(s) to this element
9032 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9033 * @return {Roo.Element} this
9035 appendChild: function(el){
9042 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9043 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9044 * automatically generated with the specified attributes.
9045 * @param {HTMLElement} insertBefore (optional) a child element of this element
9046 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9047 * @return {Roo.Element} The new child element
9049 createChild: function(CV, CW, CX){
9050 CV = CV || {tag:'div'};
9052 return Roo.DomHelper.insertBefore(CW, CV, CX !== true);
9054 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, CV, CX !== true);
9058 * Appends this element to the passed element
9059 * @param {String/HTMLElement/Element} el The new parent element
9060 * @return {Roo.Element} this
9062 appendTo: function(el){
9063 el = Roo.getDom(el);
9064 el.appendChild(this.dom);
9069 * Inserts this element before the passed element in the DOM
9070 * @param {String/HTMLElement/Element} el The element to insert before
9071 * @return {Roo.Element} this
9073 insertBefore: function(el){
9074 el = Roo.getDom(el);
9075 el.parentNode.insertBefore(this.dom, el);
9080 * Inserts this element after the passed element in the DOM
9081 * @param {String/HTMLElement/Element} el The element to insert after
9082 * @return {Roo.Element} this
9084 insertAfter: function(el){
9085 el = Roo.getDom(el);
9086 el.parentNode.insertBefore(this.dom, el.nextSibling);
9091 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9092 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9093 * @return {Roo.Element} The new child
9095 insertFirst: function(el, CY){
9097 if(typeof el == 'object' && !el.nodeType){ // dh config
9098 return this.createChild(el, this.dom.firstChild, CY);
9100 el = Roo.getDom(el);
9101 this.dom.insertBefore(el, this.dom.firstChild);
9102 return !CY ? Roo.get(el) : el;
9107 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9108 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9109 * @param {String} where (optional) 'before' or 'after' defaults to before
9110 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9111 * @return {Roo.Element} the inserted Element
9113 insertSibling: function(el, CZ, Ca){
9114 CZ = CZ ? CZ.toLowerCase() : 'before';
9116 var rt, Cb = CZ == 'before' ? this.dom : this.dom.nextSibling;
9118 if(typeof el == 'object' && !el.nodeType){ // dh config
9119 if(CZ == 'after' && !this.dom.nextSibling){
9120 rt = Roo.DomHelper.append(this.dom.parentNode, el, !Ca);
9122 rt = Roo.DomHelper[CZ == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !Ca);
9126 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9127 CZ == 'before' ? this.dom : this.dom.nextSibling);
9136 * Creates and wraps this element with another element
9137 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9138 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9139 * @return {HTMLElement/Element} The newly created wrapper element
9141 wrap: function(Cc, Cd){
9145 var Ce = Roo.DomHelper.insertBefore(this.dom, Cc, !Cd);
9146 Ce.dom ? Ce.dom.appendChild(this.dom) : Ce.appendChild(this.dom);
9151 * Replaces the passed element with this element
9152 * @param {String/HTMLElement/Element} el The element to replace
9153 * @return {Roo.Element} this
9155 replace: function(el){
9157 this.insertBefore(el);
9163 * Inserts an html fragment into this element
9164 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9165 * @param {String} html The HTML fragment
9166 * @param {Boolean} returnEl True to return an Roo.Element
9167 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9169 insertHtml : function(Cf, Cg, Ch){
9170 var el = Roo.DomHelper.insertHtml(Cf, this.dom, Cg);
9171 return Ch ? Roo.get(el) : el;
9175 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9176 * @param {Object} o The object with the attributes
9177 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9178 * @return {Roo.Element} this
9180 set : function(o, Ci){
9182 Ci = typeof Ci == 'undefined' ? (el.setAttribute ? true : false) : Ci;
9184 if(attr == "style" || typeof o[attr] == "function") continue;
9186 el.className = o["cls"];
9188 if(Ci) el.setAttribute(attr, o[attr]);
9189 else el[attr] = o[attr];
9193 Roo.DomHelper.applyStyles(el, o.style);
9199 * Convenience method for constructing a KeyMap
9200 * @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:
9201 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9202 * @param {Function} fn The function to call
9203 * @param {Object} scope (optional) The scope of the function
9204 * @return {Roo.KeyMap} The KeyMap created
9206 addKeyListener : function(Cj, fn, Ck){
9208 if(typeof Cj != "object" || Cj instanceof Array){
9224 return new Roo.KeyMap(this, Cl);
9228 * Creates a KeyMap for this element
9229 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9230 * @return {Roo.KeyMap} The KeyMap created
9232 addKeyMap : function(Cm){
9233 return new Roo.KeyMap(this, Cm);
9237 * Returns true if this element is scrollable.
9240 isScrollable : function(){
9242 return Cn.scrollHeight > Cn.clientHeight || Cn.scrollWidth > Cn.clientWidth;
9246 * 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().
9247 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9248 * @param {Number} value The new scroll value
9249 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9250 * @return {Element} this
9253 scrollTo : function(Co, Cp, Cq){
9254 var Cr = Co.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9258 var to = Cr == "scrollLeft" ? [Cp, this.dom.scrollTop] : [this.dom.scrollLeft, Cp];
9259 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9265 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9266 * within this element's scrollable range.
9267 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9268 * @param {Number} distance How far to scroll the element in pixels
9269 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9270 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9271 * was scrolled as far as it could go.
9273 scroll : function(Cs, Ct, Cu){
9274 if(!this.isScrollable()){
9278 var l = el.scrollLeft, t = el.scrollTop;
9279 var w = el.scrollWidth, h = el.scrollHeight;
9280 var cw = el.clientWidth, ch = el.clientHeight;
9281 Cs = Cs.toLowerCase();
9283 var a = this.preanim(arguments, 2);
9288 var v = Math.min(l + Ct, w-cw);
9289 this.scrollTo("left", v, a);
9296 var v = Math.max(l - Ct, 0);
9297 this.scrollTo("left", v, a);
9305 var v = Math.max(t - Ct, 0);
9306 this.scrollTo("top", v, a);
9314 var v = Math.min(t + Ct, h-ch);
9315 this.scrollTo("top", v, a);
9324 * Translates the passed page coordinates into left/top css values for this element
9325 * @param {Number/Array} x The page x or an array containing [x, y]
9326 * @param {Number} y The page y
9327 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9329 translatePoints : function(x, y){
9330 if(typeof x == 'object' || x instanceof Array){
9333 var p = this.getStyle('position');
9334 var o = this.getXY();
9336 var l = parseInt(this.getStyle('left'), 10);
9337 var t = parseInt(this.getStyle('top'), 10);
9340 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9343 t = (p == "relative") ? 0 : this.dom.offsetTop;
9346 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9350 * Returns the current scroll position of the element.
9351 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9353 getScroll : function(){
9354 var d = this.dom, Cw = document;
9355 if(d == Cw || d == Cw.body){
9356 var l = window.pageXOffset || Cw.documentElement.scrollLeft || Cw.body.scrollLeft || 0;
9357 var t = window.pageYOffset || Cw.documentElement.scrollTop || Cw.body.scrollTop || 0;
9358 return {left: l, top: t};
9360 return {left: d.scrollLeft, top: d.scrollTop};
9365 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9366 * are convert to standard 6 digit hex color.
9367 * @param {String} attr The css attribute
9368 * @param {String} defaultValue The default value to use when a valid color isn't found
9369 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9372 getColor : function(Cx, Cy, Cz){
9373 var v = this.getStyle(Cx);
9374 if(!v || v == "transparent" || v == "inherit") {
9377 var C0 = typeof Cz == "undefined" ? "#" : Cz;
9378 if(v.substr(0, 4) == "rgb("){
9379 var rvs = v.slice(4, v.length -1).split(",");
9380 for(var i = 0; i < 3; i++){
9381 var h = parseInt(rvs[i]).toString(16);
9389 if(v.substr(0, 1) == "#"){
9391 for(var i = 1; i < 4; i++){
9392 var c = v.charAt(i);
9395 }else if(v.length == 7){
9400 return (C0.length > 5 ? C0.toLowerCase() : Cy);
9404 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9405 * gradient background, rounded corners and a 4-way shadow.
9406 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9407 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9408 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9409 * @return {Roo.Element} this
9411 boxWrap : function(C1){
9413 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', C1)));
9414 el.child('.'+C1+'-mc').dom.appendChild(this.dom);
9419 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9420 * @param {String} namespace The namespace in which to look for the attribute
9421 * @param {String} name The attribute name
9422 * @return {String} The attribute value
9424 getAttributeNS : Roo.isIE ? function(ns, C2){
9426 var C3 = typeof d[ns+":"+C2];
9427 if(C3 != 'undefined' && C3 != 'unknown'){
9428 return d[ns+":"+C2];
9431 } : function(ns, C4){
9433 return d.getAttributeNS(ns, C4) || d.getAttribute(ns+":"+C4) || d.getAttribute(C4) || d[C4];
9437 var ep = El.prototype;
9440 * Appends an event handler (Shorthand for addListener)
9441 * @param {String} eventName The type of event to append
9442 * @param {Function} fn The method the event invokes
9443 * @param {Object} scope (optional) The scope (this object) of the fn
9444 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9447 ep.on = ep.addListener;
9449 ep.mon = ep.addListener;
9452 * Removes an event handler from this element (shorthand for removeListener)
9453 * @param {String} eventName the type of event to remove
9454 * @param {Function} fn the method the event invokes
9455 * @return {Roo.Element} this
9458 ep.un = ep.removeListener;
9461 * true to automatically adjust width and height settings for box-model issues (default to true)
9463 ep.autoBoxAdjust = true;
9466 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9469 El.addUnits = function(v, J){
9470 if(v === "" || v == "auto"){
9473 if(v === undefined){
9476 if(typeof v == "number" || !El.unitPattern.test(v)){
9477 return v + (J || 'px');
9482 // special markup used throughout Roo when box wrapping elements
9483 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>';
9485 * Visibility mode constant - Use visibility to hide element
9491 * Visibility mode constant - Use display to hide element
9497 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9498 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9499 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9511 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9512 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9513 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9514 * @return {Element} The Element object
9517 El.get = function(el){
9519 if(!el){ return null; }
9520 if(typeof el == "string"){ // element id
9521 if(!(J = document.getElementById(el))){
9524 if(ex = El.cache[el]){
9527 ex = El.cache[el] = new El(J);
9530 }else if(el.tagName){ // dom element
9534 if(ex = El.cache[id]){
9537 ex = El.cache[id] = new El(el);
9540 }else if(el instanceof El){
9542 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9543 // catch case where it hasn't been appended
9544 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9547 }else if(el.isComposite){
9549 }else if(el instanceof Array){
9550 return El.select(el);
9551 }else if(el == document){
9552 // create a bogus element object representing the document object
9554 var f = function(){};
9555 f.prototype = El.prototype;
9565 El.uncache = function(el){
9566 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9568 delete El.cache[a[i].id || a[i]];
9574 // Garbage collection - uncache elements/purge listeners on orphaned elements
9575 // so we don't hold a reference and cause the browser to retain them
9576 El.garbageCollect = function(){
9577 if(!Roo.enableGarbageCollector){
9578 clearInterval(El.collectorThread);
9581 for(var eid in El.cache){
9582 var el = El.cache[eid], d = el.dom;
9583 // -------------------------------------------------------
9584 // Determining what is garbage:
9585 // -------------------------------------------------------
9587 // dom node is null, definitely garbage
9588 // -------------------------------------------------------
9590 // no parentNode == direct orphan, definitely garbage
9591 // -------------------------------------------------------
9592 // !d.offsetParent && !document.getElementById(eid)
9593 // display none elements have no offsetParent so we will
9594 // also try to look it up by it's id. However, check
9595 // offsetParent first so we don't do unneeded lookups.
9596 // This enables collection of elements that are not orphans
9597 // directly, but somewhere up the line they have an orphan
9599 // -------------------------------------------------------
9600 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9601 delete El.cache[eid];
9602 if(d && Roo.enableListenerCollection){
9609 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9613 El.Flyweight = function(J){
9616 El.Flyweight.prototype = El.prototype;
9618 El._flyweights = {};
9620 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9621 * the dom node can be overwritten by other code.
9622 * @param {String/HTMLElement} el The dom node or id
9623 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9624 * prevent conflicts (e.g. internally Roo uses "_internal")
9626 * @return {Element} The shared Element object
9628 El.fly = function(el, J){
9630 el = Roo.getDom(el);
9634 if(!El._flyweights[J]){
9635 El._flyweights[J] = new El.Flyweight();
9638 El._flyweights[J].dom = el;
9639 return El._flyweights[J];
9643 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9644 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9645 * Shorthand of {@link Roo.Element#get}
9646 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9647 * @return {Element} The Element object
9653 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9654 * the dom node can be overwritten by other code.
9655 * Shorthand of {@link Roo.Element#fly}
9656 * @param {String/HTMLElement} el The dom node or id
9657 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9658 * prevent conflicts (e.g. internally Roo uses "_internal")
9660 * @return {Element} The shared Element object
9666 // speedy lookup for elements never to box adjust
9667 var I = Roo.isStrict ? {
9670 input:1, select:1, textarea:1
9672 if(Roo.isIE || Roo.isGecko){
9678 Roo.EventManager.on(window, 'unload', function(){
9680 delete El._flyweights;
9688 Roo.Element.selectorFunction = Roo.DomQuery.select;
9692 Roo.Element.select = function(J, K, L){
9694 if(typeof J == "string"){
9695 M = Roo.Element.selectorFunction(J, L);
9696 }else if(J.length !== undefined){
9699 throw "Invalid selector";
9702 return new Roo.CompositeElement(M);
9704 return new Roo.CompositeElementLite(M);
9708 * Selects elements based on the passed CSS selector to enable working on them as 1.
9709 * @param {String/Array} selector The CSS selector or an array of elements
9710 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9711 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9712 * @return {CompositeElementLite/CompositeElement}
9716 Roo.select = Roo.Element.select;
9734 * Ext JS Library 1.1.1
9735 * Copyright(c) 2006-2007, Ext JS, LLC.
9737 * Originally Released Under LGPL - original licence link has changed is not relivant.
9740 * <script type="text/javascript">
9745 //Notifies Element that fx methods are available
9746 Roo.enableFx = true;
9750 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9751 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9752 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9753 * Element effects to work.</p><br/>
9755 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9756 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9757 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9758 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9759 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9760 * expected results and should be done with care.</p><br/>
9762 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9763 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9766 ----- -----------------------------
9767 tl The top left corner
9768 t The center of the top edge
9769 tr The top right corner
9770 l The center of the left edge
9771 r The center of the right edge
9772 bl The bottom left corner
9773 b The center of the bottom edge
9774 br The bottom right corner
9776 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9777 * below are common options that can be passed to any Fx method.</b>
9778 * @cfg {Function} callback A function called when the effect is finished
9779 * @cfg {Object} scope The scope of the effect function
9780 * @cfg {String} easing A valid Easing value for the effect
9781 * @cfg {String} afterCls A css class to apply after the effect
9782 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9783 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9784 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9785 * effects that end with the element being visually hidden, ignored otherwise)
9786 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9787 * a function which returns such a specification that will be applied to the Element after the effect finishes
9788 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9789 * @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
9790 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9794 * Slides the element into view. An anchor point can be optionally passed to set the point of
9795 * origin for the slide effect. This function automatically handles wrapping the element with
9796 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9799 // default: slide the element in from the top
9802 // custom: slide the element in from the right with a 2-second duration
9803 el.slideIn('r', { duration: 2 });
9805 // common config options shown with default values
9811 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9812 * @param {Object} options (optional) Object literal with any of the Fx config options
9813 * @return {Roo.Element} The Element
9815 slideIn : function(A, o){
9816 var el = this.getFxEl();
9819 el.queueFx(o, function(){
9823 // fix display to visibility
9826 // restore values after effect
9827 var r = this.getFxRestore();
9828 var b = this.getBox();
9829 // fixed size for slide
9833 var B = this.fxWrap(r.pos, o, "hidden");
9835 var st = this.dom.style;
9836 st.visibility = "visible";
9837 st.position = "absolute";
9839 // clear out temp styles after slide and unwrap
9841 el.fxUnwrap(B, r.pos, o);
9843 st.height = r.height;
9846 // time to calc the positions
9847 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9849 switch(A.toLowerCase()){
9851 B.setSize(b.width, 0);
9852 st.left = st.bottom = "0";
9856 B.setSize(0, b.height);
9857 st.right = st.top = "0";
9861 B.setSize(0, b.height);
9863 st.left = st.top = "0";
9864 a = {width: bw, points: pt};
9867 B.setSize(b.width, 0);
9869 st.left = st.top = "0";
9870 a = {height: bh, points: pt};
9874 st.right = st.bottom = "0";
9875 a = {width: bw, height: bh};
9879 B.setY(b.y+b.height);
9880 st.right = st.top = "0";
9881 a = {width: bw, height: bh, points: pt};
9885 B.setXY([b.right, b.bottom]);
9886 st.left = st.top = "0";
9887 a = {width: bw, height: bh, points: pt};
9891 B.setX(b.x+b.width);
9892 st.left = st.bottom = "0";
9893 a = {width: bw, height: bh, points: pt};
9897 this.dom.style.visibility = "visible";
9900 arguments.callee.anim = B.fxanim(a,
9910 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9911 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9912 * 'hidden') but block elements will still take up space in the document. The element must be removed
9913 * from the DOM using the 'remove' config option if desired. This function automatically handles
9914 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9917 // default: slide the element out to the top
9920 // custom: slide the element out to the right with a 2-second duration
9921 el.slideOut('r', { duration: 2 });
9923 // common config options shown with default values
9931 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9932 * @param {Object} options (optional) Object literal with any of the Fx config options
9933 * @return {Roo.Element} The Element
9935 slideOut : function(B, o){
9936 var el = this.getFxEl();
9939 el.queueFx(o, function(){
9943 // restore values after effect
9944 var r = this.getFxRestore();
9946 var b = this.getBox();
9947 // fixed size for slide
9951 var C = this.fxWrap(r.pos, o, "visible");
9953 var st = this.dom.style;
9954 st.visibility = "visible";
9955 st.position = "absolute";
9961 el.setDisplayed(false);
9967 el.fxUnwrap(C, r.pos, o);
9970 st.height = r.height;
9976 switch(B.toLowerCase()){
9978 st.left = st.bottom = "0";
9982 st.right = st.top = "0";
9986 st.left = st.top = "0";
9987 a = {width: E, points: {to:[b.right, b.y]}};
9990 st.left = st.top = "0";
9991 a = {height: E, points: {to:[b.x, b.bottom]}};
9994 st.right = st.bottom = "0";
9995 a = {width: E, height: E};
9998 st.right = st.top = "0";
9999 a = {width: E, height: E, points: {to:[b.x, b.bottom]}};
10002 st.left = st.top = "0";
10003 a = {width: E, height: E, points: {to:[b.x+b.width, b.bottom]}};
10006 st.left = st.bottom = "0";
10007 a = {width: E, height: E, points: {to:[b.right, b.y]}};
10012 arguments.callee.anim = C.fxanim(a,
10022 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10023 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10024 * The element must be removed from the DOM using the 'remove' config option if desired.
10030 // common config options shown with default values
10038 * @param {Object} options (optional) Object literal with any of the Fx config options
10039 * @return {Roo.Element} The Element
10041 puff : function(o){
10042 var el = this.getFxEl();
10045 el.queueFx(o, function(){
10046 this.clearOpacity();
10049 // restore values after effect
10050 var r = this.getFxRestore();
10051 var st = this.dom.style;
10053 var C = function(){
10055 el.setDisplayed(false);
10063 el.setPositioning(r.pos);
10064 st.width = r.width;
10065 st.height = r.height;
10070 var D = this.getWidth();
10071 var E = this.getHeight();
10073 arguments.callee.anim = this.fxanim({
10074 width : {to: this.adjustWidth(D * 2)},
10075 height : {to: this.adjustHeight(E * 2)},
10076 points : {by: [-(D * .5), -(E * .5)]},
10078 fontSize: {to:200, unit: "%"}
10089 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10090 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10091 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10097 // all config options shown with default values
10105 * @param {Object} options (optional) Object literal with any of the Fx config options
10106 * @return {Roo.Element} The Element
10108 switchOff : function(o){
10109 var el = this.getFxEl();
10112 el.queueFx(o, function(){
10113 this.clearOpacity();
10116 // restore values after effect
10117 var r = this.getFxRestore();
10118 var st = this.dom.style;
10120 var C = function(){
10122 el.setDisplayed(false);
10129 el.setPositioning(r.pos);
10130 st.width = r.width;
10131 st.height = r.height;
10136 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10137 this.clearOpacity();
10141 points:{by:[0, this.getHeight() * .5]}
10142 }, o, 'motion', 0.3, 'easeIn', C);
10143 }).defer(100, this);
10150 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10151 * changed using the "attr" config option) and then fading back to the original color. If no original
10152 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10155 // default: highlight background to yellow
10158 // custom: highlight foreground text to blue for 2 seconds
10159 el.highlight("0000ff", { attr: 'color', duration: 2 });
10161 // common config options shown with default values
10162 el.highlight("ffff9c", {
10163 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10164 endColor: (current color) or "ffffff",
10169 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10170 * @param {Object} options (optional) Object literal with any of the Fx config options
10171 * @return {Roo.Element} The Element
10173 highlight : function(C, o){
10174 var el = this.getFxEl();
10177 el.queueFx(o, function(){
10179 attr = o.attr || "backgroundColor";
10181 this.clearOpacity();
10184 var D = this.getColor(attr);
10185 var E = this.dom.style[attr];
10186 endColor = (o.endColor || D) || "ffffff";
10188 var F = function(){
10189 el.dom.style[attr] = E;
10194 a[attr] = {from: C, to: endColor};
10195 arguments.callee.anim = this.fxanim(a,
10205 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10208 // default: a single light blue ripple
10211 // custom: 3 red ripples lasting 3 seconds total
10212 el.frame("ff0000", 3, { duration: 3 });
10214 // common config options shown with default values
10215 el.frame("C3DAF9", 1, {
10216 duration: 1 //duration of entire animation (not each individual ripple)
10217 // Note: Easing is not configurable and will be ignored if included
10220 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10221 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10222 * @param {Object} options (optional) Object literal with any of the Fx config options
10223 * @return {Roo.Element} The Element
10225 frame : function(D, E, o){
10226 var el = this.getFxEl();
10229 el.queueFx(o, function(){
10230 D = D || "#C3DAF9";
10236 duration = o.duration || 1;
10239 var b = this.getBox();
10240 var F = function(){
10241 var G = this.createProxy({
10244 visbility:"hidden",
10245 position:"absolute",
10246 "z-index":"35000", // yee haw
10247 border:"0px solid " + D
10250 var H = Roo.isBorderBox ? 2 : 1;
10252 top:{from:b.y, to:b.y - 20},
10253 left:{from:b.x, to:b.x - 20},
10254 borderWidth:{from:0, to:10},
10255 opacity:{from:1, to:0},
10256 height:{from:b.height, to:(b.height + (20*H))},
10257 width:{from:b.width, to:(b.width + (20*H))}
10258 }, duration, function(){
10262 F.defer((duration/2)*1000, this);
10273 * Creates a pause before any subsequent queued effects begin. If there are
10274 * no effects queued after the pause it will have no effect.
10279 * @param {Number} seconds The length of time to pause (in seconds)
10280 * @return {Roo.Element} The Element
10282 pause : function(F){
10283 var el = this.getFxEl();
10286 el.queueFx(o, function(){
10287 setTimeout(function(){
10295 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10296 * using the "endOpacity" config option.
10299 // default: fade in from opacity 0 to 100%
10302 // custom: fade in from opacity 0 to 75% over 2 seconds
10303 el.fadeIn({ endOpacity: .75, duration: 2});
10305 // common config options shown with default values
10307 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10312 * @param {Object} options (optional) Object literal with any of the Fx config options
10313 * @return {Roo.Element} The Element
10315 fadeIn : function(o){
10316 var el = this.getFxEl();
10318 el.queueFx(o, function(){
10319 this.setOpacity(0);
10321 this.dom.style.visibility = 'visible';
10322 var to = o.endOpacity || 1;
10323 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10324 o, null, .5, "easeOut", function(){
10326 this.clearOpacity();
10336 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10337 * using the "endOpacity" config option.
10340 // default: fade out from the element's current opacity to 0
10343 // custom: fade out from the element's current opacity to 25% over 2 seconds
10344 el.fadeOut({ endOpacity: .25, duration: 2});
10346 // common config options shown with default values
10348 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10355 * @param {Object} options (optional) Object literal with any of the Fx config options
10356 * @return {Roo.Element} The Element
10358 fadeOut : function(o){
10359 var el = this.getFxEl();
10361 el.queueFx(o, function(){
10362 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10363 o, null, .5, "easeOut", function(){
10364 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10365 this.dom.style.display = "none";
10367 this.dom.style.visibility = "hidden";
10370 this.clearOpacity();
10378 * Animates the transition of an element's dimensions from a starting height/width
10379 * to an ending height/width.
10382 // change height and width to 100x100 pixels
10383 el.scale(100, 100);
10385 // common config options shown with default values. The height and width will default to
10386 // the element's existing values if passed as null.
10389 [element's height], {
10394 * @param {Number} width The new width (pass undefined to keep the original width)
10395 * @param {Number} height The new height (pass undefined to keep the original height)
10396 * @param {Object} options (optional) Object literal with any of the Fx config options
10397 * @return {Roo.Element} The Element
10399 scale : function(w, h, o){
10400 this.shift(Roo.apply({}, o, {
10408 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10409 * Any of these properties not specified in the config object will not be changed. This effect
10410 * requires that at least one new dimension, position or opacity setting must be passed in on
10411 * the config object in order for the function to have any effect.
10414 // slide the element horizontally to x position 200 while changing the height and opacity
10415 el.shift({ x: 200, height: 50, opacity: .8 });
10417 // common config options shown with default values.
10419 width: [element's width],
10420 height: [element's height],
10421 x: [element's x position],
10422 y: [element's y position],
10423 opacity: [element's opacity],
10428 * @param {Object} options Object literal with any of the Fx config options
10429 * @return {Roo.Element} The Element
10431 shift : function(o){
10432 var el = this.getFxEl();
10434 el.queueFx(o, function(){
10435 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10436 if(w !== undefined){
10437 a.width = {to: this.adjustWidth(w)};
10439 if(h !== undefined){
10440 a.height = {to: this.adjustHeight(h)};
10442 if(x !== undefined || y !== undefined){
10444 x !== undefined ? x : this.getX(),
10445 y !== undefined ? y : this.getY()
10448 if(op !== undefined){
10449 a.opacity = {to: op};
10451 if(o.xy !== undefined){
10452 a.points = {to: o.xy};
10455 arguments.callee.anim = this.fxanim(a,
10456 o, 'motion', .35, "easeOut", function(){
10464 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10465 * ending point of the effect.
10468 // default: slide the element downward while fading out
10471 // custom: slide the element out to the right with a 2-second duration
10472 el.ghost('r', { duration: 2 });
10474 // common config options shown with default values
10482 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10483 * @param {Object} options (optional) Object literal with any of the Fx config options
10484 * @return {Roo.Element} The Element
10486 ghost : function(G, o){
10487 var el = this.getFxEl();
10490 el.queueFx(o, function(){
10493 // restore values after effect
10494 var r = this.getFxRestore();
10495 var w = this.getWidth(),
10496 h = this.getHeight();
10498 var st = this.dom.style;
10500 var H = function(){
10502 el.setDisplayed(false);
10509 el.setPositioning(r.pos);
10510 st.width = r.width;
10511 st.height = r.height;
10516 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10517 switch(G.toLowerCase()){
10545 arguments.callee.anim = this.fxanim(a,
10555 * Ensures that all effects queued after syncFx is called on the element are
10556 * run concurrently. This is the opposite of {@link #sequenceFx}.
10557 * @return {Roo.Element} The Element
10559 syncFx : function(){
10560 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10569 * Ensures that all effects queued after sequenceFx is called on the element are
10570 * run in sequence. This is the opposite of {@link #syncFx}.
10571 * @return {Roo.Element} The Element
10573 sequenceFx : function(){
10574 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10576 concurrent : false,
10583 nextFx : function(){
10584 var ef = this.fxQueue[0];
10591 * Returns true if the element has any effects actively running or queued, else returns false.
10592 * @return {Boolean} True if element has active effects, else false
10594 hasActiveFx : function(){
10595 return this.fxQueue && this.fxQueue[0];
10599 * Stops any running effects and clears the element's internal effects queue if it contains
10600 * any additional effects that haven't started yet.
10601 * @return {Roo.Element} The Element
10603 stopFx : function(){
10604 if(this.hasActiveFx()){
10605 var cur = this.fxQueue[0];
10606 if(cur && cur.anim && cur.anim.isAnimated()){
10607 this.fxQueue = [cur]; // clear out others
10608 cur.anim.stop(true);
10615 beforeFx : function(o){
10616 if(this.hasActiveFx() && !o.concurrent){
10627 * Returns true if the element is currently blocking so that no other effect can be queued
10628 * until this effect is finished, else returns false if blocking is not set. This is commonly
10629 * used to ensure that an effect initiated by a user action runs to completion prior to the
10630 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10631 * @return {Boolean} True if blocking, else false
10633 hasFxBlock : function(){
10634 var q = this.fxQueue;
10635 return q && q[0] && q[0].block;
10639 queueFx : function(o, fn){
10643 if(!this.hasFxBlock()){
10644 Roo.applyIf(o, this.fxDefaults);
10646 var run = this.beforeFx(o);
10647 fn.block = o.block;
10648 this.fxQueue.push(fn);
10660 fxWrap : function(H, o, I){
10662 if(!o.wrap || !(J = Roo.get(o.wrap))){
10665 wrapXY = this.getXY();
10667 var div = document.createElement("div");
10668 div.style.visibility = I;
10669 J = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10670 J.setPositioning(H);
10671 if(J.getStyle("position") == "static"){
10672 J.position("relative");
10675 this.clearPositioning('auto');
10677 J.dom.appendChild(this.dom);
10686 fxUnwrap : function(K, L, o){
10687 this.clearPositioning();
10688 this.setPositioning(L);
10690 K.dom.parentNode.insertBefore(this.dom, K.dom);
10696 getFxRestore : function(){
10697 var st = this.dom.style;
10698 return {pos: this.getPositioning(), width: st.width, height : st.height};
10702 afterFx : function(o){
10704 this.applyStyles(o.afterStyle);
10707 this.addClass(o.afterCls);
10709 if(o.remove === true){
10713 Roo.callback(o.callback, o.scope, [this]);
10715 this.fxQueue.shift();
10721 getFxEl : function(){ // support for composite element fx
10722 return Roo.get(this.dom);
10726 fxanim : function(M, N, O, P, Q, cb){
10729 var R = Roo.lib.Anim[O](
10731 (N.duration || P) || .35,
10732 (N.easing || Q) || 'easeOut',
10734 Roo.callback(cb, this);
10743 // backwords compat
10744 Roo.Fx.resize = Roo.Fx.scale;
10746 //When included, Roo.Fx is automatically applied to Element so that all basic
10747 //effects are available directly via the Element API
10748 Roo.apply(Roo.Element.prototype, Roo.Fx);
10751 * Ext JS Library 1.1.1
10752 * Copyright(c) 2006-2007, Ext JS, LLC.
10754 * Originally Released Under LGPL - original licence link has changed is not relivant.
10757 * <script type="text/javascript">
10762 * @class Roo.CompositeElement
10763 * Standard composite class. Creates a Roo.Element for every element in the collection.
10765 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10766 * actions will be performed on all the elements in this collection.</b>
10768 * All methods return <i>this</i> and can be chained.
10770 var els = Roo.select("#some-el div.some-class", true);
10771 // or select directly from an existing element
10772 var el = Roo.get('some-el');
10773 el.select('div.some-class', true);
10775 els.setWidth(100); // all elements become 100 width
10776 els.hide(true); // all elements fade out and hide
10778 els.setWidth(100).hide(true);
10781 Roo.CompositeElement = function(A){
10782 this.elements = [];
10783 this.addElements(A);
10785 Roo.CompositeElement.prototype = {
10787 addElements : function(B){
10788 if(!B) return this;
10789 if(typeof B == "string"){
10790 B = Roo.Element.selectorFunction(B);
10792 var C = this.elements;
10793 var D = C.length-1;
10794 for(var i = 0, len = B.length; i < len; i++) {
10795 C[++D] = Roo.get(B[i]);
10801 * Clears this composite and adds the elements returned by the passed selector.
10802 * @param {String/Array} els A string CSS selector, an array of elements or an element
10803 * @return {CompositeElement} this
10805 fill : function(E){
10806 this.elements = [];
10812 * Filters this composite to only elements that match the passed selector.
10813 * @param {String} selector A string CSS selector
10814 * @return {CompositeElement} this
10816 filter : function(F){
10818 this.each(function(el){
10820 G[G.length] = el.dom;
10827 invoke : function(fn, H){
10828 var I = this.elements;
10829 for(var i = 0, len = I.length; i < len; i++) {
10830 Roo.Element.prototype[fn].apply(I[i], H);
10835 * Adds elements to this composite.
10836 * @param {String/Array} els A string CSS selector, an array of elements or an element
10837 * @return {CompositeElement} this
10840 if(typeof J == "string"){
10841 this.addElements(Roo.Element.selectorFunction(J));
10842 }else if(J.length !== undefined){
10843 this.addElements(J);
10845 this.addElements([J]);
10850 * Calls the passed function passing (el, this, index) for each element in this composite.
10851 * @param {Function} fn The function to call
10852 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10853 * @return {CompositeElement} this
10855 each : function(fn, K){
10856 var L = this.elements;
10857 for(var i = 0, len = L.length; i < len; i++){
10858 if(fn.call(K || L[i], L[i], this, i) === false) {
10866 * Returns the Element object at the specified index
10867 * @param {Number} index
10868 * @return {Roo.Element}
10870 item : function(M){
10871 return this.elements[M] || null;
10875 * Returns the first Element
10876 * @return {Roo.Element}
10878 first : function(){
10879 return this.item(0);
10883 * Returns the last Element
10884 * @return {Roo.Element}
10887 return this.item(this.elements.length-1);
10891 * Returns the number of elements in this composite
10894 getCount : function(){
10895 return this.elements.length;
10899 * Returns true if this composite contains the passed element
10902 contains : function(el){
10903 return this.indexOf(el) !== -1;
10907 * Returns true if this composite contains the passed element
10910 indexOf : function(el){
10911 return this.elements.indexOf(Roo.get(el));
10916 * Removes the specified element(s).
10917 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10918 * or an array of any of those.
10919 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10920 * @return {CompositeElement} this
10922 removeElement : function(el, N){
10923 if(el instanceof Array){
10924 for(var i = 0, len = el.length; i < len; i++){
10925 this.removeElement(el[i]);
10929 var O = typeof el == 'number' ? el : this.indexOf(el);
10932 var d = this.elements[O];
10936 d.parentNode.removeChild(d);
10940 this.elements.splice(O, 1);
10946 * Replaces the specified element with the passed element.
10947 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10949 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10950 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10951 * @return {CompositeElement} this
10953 replaceElement : function(el, P, Q){
10954 var R = typeof el == 'number' ? el : this.indexOf(el);
10957 this.elements[R].replaceWith(P);
10959 this.elements.splice(R, 1, Roo.get(P))
10966 * Removes all elements.
10968 clear : function(){
10969 this.elements = [];
10973 Roo.CompositeElement.createCall = function(S, T){
10976 return this.invoke(T, arguments);
10980 for(var fnName in Roo.Element.prototype){
10981 if(typeof Roo.Element.prototype[fnName] == "function"){
10982 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10989 * Ext JS Library 1.1.1
10990 * Copyright(c) 2006-2007, Ext JS, LLC.
10992 * Originally Released Under LGPL - original licence link has changed is not relivant.
10995 * <script type="text/javascript">
10999 * @class Roo.CompositeElementLite
11000 * @extends Roo.CompositeElement
11001 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11003 var els = Roo.select("#some-el div.some-class");
11004 // or select directly from an existing element
11005 var el = Roo.get('some-el');
11006 el.select('div.some-class');
11008 els.setWidth(100); // all elements become 100 width
11009 els.hide(true); // all elements fade out and hide
11011 els.setWidth(100).hide(true);
11012 </code></pre><br><br>
11013 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11014 * actions will be performed on all the elements in this collection.</b>
11016 Roo.CompositeElementLite = function(A){
11017 Roo.CompositeElementLite.superclass.constructor.call(this, A);
11018 this.el = new Roo.Element.Flyweight();
11020 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11021 addElements : function(B){
11023 if(B instanceof Array){
11024 this.elements = this.elements.concat(B);
11026 var yels = this.elements;
11027 var index = yels.length-1;
11028 for(var i = 0, len = B.length; i < len; i++) {
11029 yels[++index] = B[i];
11035 invoke : function(fn, C){
11036 var D = this.elements;
11038 for(var i = 0, len = D.length; i < len; i++) {
11040 Roo.Element.prototype[fn].apply(el, C);
11045 * Returns a flyweight Element of the dom element object at the specified index
11046 * @param {Number} index
11047 * @return {Roo.Element}
11049 item : function(E){
11050 if(!this.elements[E]){
11054 this.el.dom = this.elements[E];
11058 // fixes scope with flyweight
11059 addListener : function(F, G, H, I){
11060 var J = this.elements;
11061 for(var i = 0, len = J.length; i < len; i++) {
11062 Roo.EventManager.on(J[i], F, G, H || J[i], I);
11068 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11069 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11070 * a reference to the dom node, use el.dom.</b>
11071 * @param {Function} fn The function to call
11072 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11073 * @return {CompositeElement} this
11075 each : function(fn, K){
11076 var L = this.elements;
11078 for(var i = 0, len = L.length; i < len; i++){
11080 if(fn.call(K || el, el, this, i) === false){
11087 indexOf : function(el){
11088 return this.elements.indexOf(Roo.getDom(el));
11091 replaceElement : function(el, M, N){
11092 var O = typeof el == 'number' ? el : this.indexOf(el);
11096 var d = this.elements[O];
11097 d.parentNode.insertBefore(M, d);
11098 d.parentNode.removeChild(d);
11101 this.elements.splice(O, 1, M);
11106 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11111 * Ext JS Library 1.1.1
11112 * Copyright(c) 2006-2007, Ext JS, LLC.
11114 * Originally Released Under LGPL - original licence link has changed is not relivant.
11117 * <script type="text/javascript">
11123 * @class Roo.data.Connection
11124 * @extends Roo.util.Observable
11125 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11126 * either to a configured URL, or to a URL specified at request time.<br><br>
11128 * Requests made by this class are asynchronous, and will return immediately. No data from
11129 * the server will be available to the statement immediately following the {@link #request} call.
11130 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11132 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11133 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11134 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11135 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11136 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11137 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11138 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11139 * standard DOM methods.
11141 * @param {Object} config a configuration object.
11143 Roo.data.Connection = function(A){
11144 Roo.apply(this, A);
11147 * @event beforerequest
11148 * Fires before a network request is made to retrieve a data object.
11149 * @param {Connection} conn This Connection object.
11150 * @param {Object} options The options config object passed to the {@link #request} method.
11152 "beforerequest" : true,
11154 * @event requestcomplete
11155 * Fires if the request was successfully completed.
11156 * @param {Connection} conn This Connection object.
11157 * @param {Object} response The XHR object containing the response data.
11158 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11159 * @param {Object} options The options config object passed to the {@link #request} method.
11161 "requestcomplete" : true,
11163 * @event requestexception
11164 * Fires if an error HTTP status was returned from the server.
11165 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11166 * @param {Connection} conn This Connection object.
11167 * @param {Object} response The XHR object containing the response data.
11168 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11169 * @param {Object} options The options config object passed to the {@link #request} method.
11171 "requestexception" : true
11173 Roo.data.Connection.superclass.constructor.call(this);
11176 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11178 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11181 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11182 * extra parameters to each request made by this object. (defaults to undefined)
11185 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11186 * to each request made by this object. (defaults to undefined)
11189 * @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)
11192 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11196 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11202 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11205 disableCaching: true,
11208 * Sends an HTTP request to a remote server.
11209 * @param {Object} options An object which may contain the following properties:<ul>
11210 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11211 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11212 * request, a url encoded string or a function to call to get either.</li>
11213 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11214 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11215 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11216 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11217 * <li>options {Object} The parameter to the request call.</li>
11218 * <li>success {Boolean} True if the request succeeded.</li>
11219 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11221 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11222 * The callback is passed the following parameters:<ul>
11223 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11224 * <li>options {Object} The parameter to the request call.</li>
11226 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11227 * The callback is passed the following parameters:<ul>
11228 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11229 * <li>options {Object} The parameter to the request call.</li>
11231 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11232 * for the callback function. Defaults to the browser window.</li>
11233 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11234 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11235 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11236 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11237 * params for the post data. Any params will be appended to the URL.</li>
11238 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11240 * @return {Number} transactionId
11242 request : function(o){
11243 if(this.fireEvent("beforerequest", this, o) !== false){
11246 if(typeof p == "function"){
11247 p = p.call(o.scope||window, o);
11249 if(typeof p == "object"){
11250 p = Roo.urlEncode(o.params);
11252 if(this.extraParams){
11253 var extras = Roo.urlEncode(this.extraParams);
11254 p = p ? (p + '&' + extras) : extras;
11257 var url = o.url || this.url;
11258 if(typeof url == 'function'){
11259 url = url.call(o.scope||window, o);
11263 var form = Roo.getDom(o.form);
11264 url = url || form.action;
11266 var enctype = form.getAttribute("enctype");
11267 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11268 return this.doFormUpload(o, p, url);
11270 var f = Roo.lib.Ajax.serializeForm(form);
11271 p = p ? (p + '&' + f) : f;
11274 var hs = o.headers;
11275 if(this.defaultHeaders){
11276 hs = Roo.apply(hs || {}, this.defaultHeaders);
11283 success: this.handleResponse,
11284 failure: this.handleFailure,
11286 argument: {options: o},
11287 timeout : this.timeout
11290 var method = o.method||this.method||(p ? "POST" : "GET");
11292 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11293 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11296 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11300 }else if(this.autoAbort !== false){
11304 if((method == 'GET' && p) || o.xmlData){
11305 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11309 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11310 return this.transId;
11312 Roo.callback(o.callback, o.scope, [o, null, null]);
11318 * Determine whether this object has a request outstanding.
11319 * @param {Number} transactionId (Optional) defaults to the last transaction
11320 * @return {Boolean} True if there is an outstanding request.
11322 isLoading : function(B){
11324 return Roo.lib.Ajax.isCallInProgress(B);
11326 return this.transId ? true : false;
11331 * Aborts any outstanding request.
11332 * @param {Number} transactionId (Optional) defaults to the last transaction
11334 abort : function(C){
11335 if(C || this.isLoading()){
11336 Roo.lib.Ajax.abort(C || this.transId);
11341 handleResponse : function(D){
11342 this.transId = false;
11343 var E = D.argument.options;
11344 D.argument = E ? E.argument : null;
11345 this.fireEvent("requestcomplete", this, D, E);
11346 Roo.callback(E.success, E.scope, [D, E]);
11347 Roo.callback(E.callback, E.scope, [E, true, D]);
11351 handleFailure : function(F, e){
11352 this.transId = false;
11353 var G = F.argument.options;
11354 F.argument = G ? G.argument : null;
11355 this.fireEvent("requestexception", this, F, G, e);
11356 Roo.callback(G.failure, G.scope, [F, G]);
11357 Roo.callback(G.callback, G.scope, [G, false, F]);
11361 doFormUpload : function(o, ps, H){
11363 var I = document.createElement('iframe');
11366 I.className = 'x-hidden';
11368 I.src = Roo.SSL_SECURE_URL;
11371 document.body.appendChild(I);
11374 document.frames[id].name = id;
11377 var J = Roo.getDom(o.form);
11380 J.enctype = J.encoding = 'multipart/form-data';
11386 if(ps){ // add dynamic params
11388 ps = Roo.urlDecode(ps, false);
11390 if(ps.hasOwnProperty(k)){
11391 hd = document.createElement('input');
11392 hd.type = 'hidden';
11402 var r = { // bogus response object
11407 r.argument = o ? o.argument : null;
11412 doc = I.contentWindow.document;
11414 doc = (I.contentDocument || window.frames[id].document);
11416 if(doc && doc.body){
11417 r.responseText = doc.body.innerHTML;
11419 if(doc && doc.XMLDocument){
11420 r.responseXML = doc.XMLDocument;
11422 r.responseXML = doc;
11430 Roo.EventManager.removeListener(I, 'load', cb, this);
11432 this.fireEvent("requestcomplete", this, r, o);
11433 Roo.callback(o.success, o.scope, [r, o]);
11434 Roo.callback(o.callback, o.scope, [o, true, r]);
11436 setTimeout(function(){document.body.removeChild(I);}, 100);
11440 Roo.EventManager.on(I, 'load', cb, this);
11443 if(K){ // remove dynamic params
11444 for(var i = 0, len = K.length; i < len; i++){
11445 J.removeChild(K[i]);
11453 * @extends Roo.data.Connection
11454 * Global Ajax request class.
11458 Roo.Ajax = new Roo.data.Connection({
11461 * @cfg {String} url @hide
11464 * @cfg {Object} extraParams @hide
11467 * @cfg {Object} defaultHeaders @hide
11470 * @cfg {String} method (Optional) @hide
11473 * @cfg {Number} timeout (Optional) @hide
11476 * @cfg {Boolean} autoAbort (Optional) @hide
11480 * @cfg {Boolean} disableCaching (Optional) @hide
11484 * @property disableCaching
11485 * True to add a unique cache-buster param to GET requests. (defaults to true)
11490 * The default URL to be used for requests to the server. (defaults to undefined)
11494 * @property extraParams
11495 * An object containing properties which are used as
11496 * extra parameters to each request made by this object. (defaults to undefined)
11500 * @property defaultHeaders
11501 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11506 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11510 * @property timeout
11511 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11516 * @property autoAbort
11517 * Whether a new request should abort any pending requests. (defaults to false)
11523 * Serialize the passed form into a url encoded string
11524 * @param {String/HTMLElement} form
11527 serializeForm : function(L){
11528 return Roo.lib.Ajax.serializeForm(L);
11533 * Ext JS Library 1.1.1
11534 * Copyright(c) 2006-2007, Ext JS, LLC.
11536 * Originally Released Under LGPL - original licence link has changed is not relivant.
11539 * <script type="text/javascript">
11544 * @extends Roo.data.Connection
11545 * Global Ajax request class.
11547 * @instanceOf Roo.data.Connection
11549 Roo.Ajax = new Roo.data.Connection({
11558 * @cfg {String} url @hide
11561 * @cfg {Object} extraParams @hide
11564 * @cfg {Object} defaultHeaders @hide
11567 * @cfg {String} method (Optional) @hide
11570 * @cfg {Number} timeout (Optional) @hide
11573 * @cfg {Boolean} autoAbort (Optional) @hide
11577 * @cfg {Boolean} disableCaching (Optional) @hide
11581 * @property disableCaching
11582 * True to add a unique cache-buster param to GET requests. (defaults to true)
11587 * The default URL to be used for requests to the server. (defaults to undefined)
11591 * @property extraParams
11592 * An object containing properties which are used as
11593 * extra parameters to each request made by this object. (defaults to undefined)
11597 * @property defaultHeaders
11598 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11603 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11607 * @property timeout
11608 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11613 * @property autoAbort
11614 * Whether a new request should abort any pending requests. (defaults to false)
11620 * Serialize the passed form into a url encoded string
11621 * @param {String/HTMLElement} form
11624 serializeForm : function(A){
11625 return Roo.lib.Ajax.serializeForm(A);
11630 * Ext JS Library 1.1.1
11631 * Copyright(c) 2006-2007, Ext JS, LLC.
11633 * Originally Released Under LGPL - original licence link has changed is not relivant.
11636 * <script type="text/javascript">
11641 * @class Roo.UpdateManager
11642 * @extends Roo.util.Observable
11643 * Provides AJAX-style update for Element object.<br><br>
11646 * // Get it from a Roo.Element object
11647 * var el = Roo.get("foo");
11648 * var mgr = el.getUpdateManager();
11649 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11651 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11653 * // or directly (returns the same UpdateManager instance)
11654 * var mgr = new Roo.UpdateManager("myElementId");
11655 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11656 * mgr.on("update", myFcnNeedsToKnow);
11658 // short handed call directly from the element object
11659 Roo.get("foo").load({
11663 text: "Loading Foo..."
11667 * Create new UpdateManager directly.
11668 * @param {String/HTMLElement/Roo.Element} el The element to update
11669 * @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).
11671 Roo.UpdateManager = function(el, A){
11673 if(!A && el.updateManager){
11674 return el.updateManager;
11678 * The Element object
11679 * @type Roo.Element
11683 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11686 this.defaultUrl = null;
11690 * @event beforeupdate
11691 * Fired before an update is made, return false from your handler and the update is cancelled.
11692 * @param {Roo.Element} el
11693 * @param {String/Object/Function} url
11694 * @param {String/Object} params
11696 "beforeupdate": true,
11699 * Fired after successful update is made.
11700 * @param {Roo.Element} el
11701 * @param {Object} oResponseObject The response Object
11706 * Fired on update failure.
11707 * @param {Roo.Element} el
11708 * @param {Object} oResponseObject The response Object
11712 var d = Roo.UpdateManager.defaults;
11714 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11717 this.sslBlankUrl = d.sslBlankUrl;
11719 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11722 this.disableCaching = d.disableCaching;
11724 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11727 this.indicatorText = d.indicatorText;
11729 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11732 this.showLoadIndicator = d.showLoadIndicator;
11734 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11737 this.timeout = d.timeout;
11740 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11743 this.loadScripts = d.loadScripts;
11746 * Transaction object of current executing transaction
11748 this.transaction = null;
11753 this.autoRefreshProcId = null;
11755 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11758 this.refreshDelegate = this.refresh.createDelegate(this);
11760 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11763 this.updateDelegate = this.update.createDelegate(this);
11765 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11768 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11772 this.successDelegate = this.processSuccess.createDelegate(this);
11776 this.failureDelegate = this.processFailure.createDelegate(this);
11778 if(!this.renderer){
11780 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11782 this.renderer = new Roo.UpdateManager.BasicRenderer();
11786 Roo.UpdateManager.superclass.constructor.call(this);
11789 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11791 * Get the Element this UpdateManager is bound to
11792 * @return {Roo.Element} The element
11794 getEl : function(){
11798 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11799 * @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:
11802 url: "your-url.php",<br/>
11803 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11804 callback: yourFunction,<br/>
11805 scope: yourObject, //(optional scope) <br/>
11806 discardUrl: false, <br/>
11807 nocache: false,<br/>
11808 text: "Loading...",<br/>
11810 scripts: false<br/>
11813 * The only required property is url. The optional properties nocache, text and scripts
11814 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11815 * @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}
11816 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11817 * @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.
11819 update : function(B, C, D, E){
11820 if(this.fireEvent("beforeupdate", this.el, B, C) !== false){
11821 var method = this.method, cfg;
11822 if(typeof B == "object"){ // must be config object
11825 C = C || cfg.params;
11826 D = D || cfg.callback;
11827 E = E || cfg.discardUrl;
11828 if(D && cfg.scope){
11829 D = D.createDelegate(cfg.scope);
11831 if(typeof cfg.method != "undefined"){method = cfg.method;};
11832 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11833 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11834 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11835 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11838 this.showLoading();
11840 this.defaultUrl = B;
11842 if(typeof B == "function"){
11847 method = method || (C ? "POST" : "GET");
11848 if(method == "GET"){
11849 B = this.prepareUrl(B);
11852 var o = Roo.apply(cfg ||{}, {
11855 success: this.successDelegate,
11856 failure: this.failureDelegate,
11857 callback: undefined,
11858 timeout: (this.timeout*1000),
11859 argument: {"url": B, "form": null, "callback": D, "params": C}
11862 this.transaction = Roo.Ajax.request(o);
11867 * 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.
11868 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11869 * @param {String/HTMLElement} form The form Id or form element
11870 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11871 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11872 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11874 formUpdate : function(F, G, H, I){
11875 if(this.fireEvent("beforeupdate", this.el, F, G) !== false){
11876 if(typeof G == "function"){
11881 this.transaction = Roo.Ajax.request({
11884 success: this.successDelegate,
11885 failure: this.failureDelegate,
11886 timeout: (this.timeout*1000),
11887 argument: {"url": G, "form": F, "callback": I, "reset": H}
11889 this.showLoading.defer(1, this);
11894 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11895 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11897 refresh : function(J){
11898 if(this.defaultUrl == null){
11902 this.update(this.defaultUrl, null, J, true);
11906 * Set this element to auto refresh.
11907 * @param {Number} interval How often to update (in seconds).
11908 * @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)
11909 * @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}
11910 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11911 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11913 startAutoRefresh : function(K, L, M, N, O){
11915 this.update(L || this.defaultUrl, M, N, true);
11917 if(this.autoRefreshProcId){
11918 clearInterval(this.autoRefreshProcId);
11921 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [L || this.defaultUrl, M, N, true]), K*1000);
11925 * Stop auto refresh on this element.
11927 stopAutoRefresh : function(){
11928 if(this.autoRefreshProcId){
11929 clearInterval(this.autoRefreshProcId);
11930 delete this.autoRefreshProcId;
11934 isAutoRefreshing : function(){
11935 return this.autoRefreshProcId ? true : false;
11938 * Called to update the element to "Loading" state. Override to perform custom action.
11940 showLoading : function(){
11941 if(this.showLoadIndicator){
11942 this.el.update(this.indicatorText);
11947 * Adds unique parameter to query string if disableCaching = true
11950 prepareUrl : function(P){
11951 if(this.disableCaching){
11952 var append = "_dc=" + (new Date().getTime());
11953 if(P.indexOf("?") !== -1){
11965 processSuccess : function(Q){
11966 this.transaction = null;
11967 if(Q.argument.form && Q.argument.reset){
11968 try{ // put in try/catch since some older FF releases had problems with this
11969 Q.argument.form.reset();
11972 if(this.loadScripts){
11973 this.renderer.render(this.el, Q, this,
11974 this.updateComplete.createDelegate(this, [Q]));
11976 this.renderer.render(this.el, Q, this);
11977 this.updateComplete(Q);
11981 updateComplete : function(R){
11982 this.fireEvent("update", this.el, R);
11983 if(typeof R.argument.callback == "function"){
11984 R.argument.callback(this.el, true, R);
11991 processFailure : function(S){
11992 this.transaction = null;
11993 this.fireEvent("failure", this.el, S);
11994 if(typeof S.argument.callback == "function"){
11995 S.argument.callback(this.el, false, S);
12000 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12001 * @param {Object} renderer The object implementing the render() method
12003 setRenderer : function(T){
12007 getRenderer : function(){
12008 return this.renderer;
12012 * Set the defaultUrl used for updates
12013 * @param {String/Function} defaultUrl The url or a function to call to get the url
12015 setDefaultUrl : function(U){
12016 this.defaultUrl = U;
12020 * Aborts the executing transaction
12022 abort : function(){
12023 if(this.transaction){
12024 Roo.Ajax.abort(this.transaction);
12029 * Returns true if an update is in progress
12030 * @return {Boolean}
12032 isUpdating : function(){
12033 if(this.transaction){
12034 return Roo.Ajax.isLoading(this.transaction);
12041 * @class Roo.UpdateManager.defaults
12042 * @static (not really - but it helps the doc tool)
12043 * The defaults collection enables customizing the default properties of UpdateManager
12045 Roo.UpdateManager.defaults = {
12047 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12053 * True to process scripts by default (Defaults to false).
12056 loadScripts : false,
12059 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12062 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12064 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12067 disableCaching : false,
12069 * Whether to show indicatorText when loading (Defaults to true).
12072 showLoadIndicator : true,
12074 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12077 indicatorText : '<div class="loading-indicator">Loading...</div>'
12081 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12083 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12084 * @param {String/HTMLElement/Roo.Element} el The element to update
12085 * @param {String} url The url
12086 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12087 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12090 * @member Roo.UpdateManager
12092 Roo.UpdateManager.updateElement = function(el, V, W, X){
12093 var um = Roo.get(el, true).getUpdateManager();
12095 um.update(V, W, X ? X.callback : null);
12097 // alias for backwards compat
12098 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12100 * @class Roo.UpdateManager.BasicRenderer
12101 * Default Content renderer. Updates the elements innerHTML with the responseText.
12103 Roo.UpdateManager.BasicRenderer = function(){};
12105 Roo.UpdateManager.BasicRenderer.prototype = {
12107 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12108 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12109 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12110 * @param {Roo.Element} el The element being rendered
12111 * @param {Object} response The YUI Connect response object
12112 * @param {UpdateManager} updateManager The calling update manager
12113 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12115 render : function(el, Y, Z, a){
12116 el.update(Y.responseText, Z.loadScripts, a);
12122 * Ext JS Library 1.1.1
12123 * Copyright(c) 2006-2007, Ext JS, LLC.
12125 * Originally Released Under LGPL - original licence link has changed is not relivant.
12128 * <script type="text/javascript">
12132 * @class Roo.util.DelayedTask
12133 * Provides a convenient method of performing setTimeout where a new
12134 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12135 * You can use this class to buffer
12136 * the keypress events for a certain number of milliseconds, and perform only if they stop
12137 * for that amount of time.
12138 * @constructor The parameters to this constructor serve as defaults and are not required.
12139 * @param {Function} fn (optional) The default function to timeout
12140 * @param {Object} scope (optional) The default scope of that timeout
12141 * @param {Array} args (optional) The default Array of arguments
12143 Roo.util.DelayedTask = function(fn, A, B){
12144 var id = null, d, t;
12146 var C = function(){
12147 var D = new Date().getTime();
12151 fn.apply(A, B || []);
12155 * Cancels any pending timeout and queues a new one
12156 * @param {Number} delay The milliseconds to delay
12157 * @param {Function} newFn (optional) Overrides function passed to constructor
12158 * @param {Object} newScope (optional) Overrides scope passed to constructor
12159 * @param {Array} newArgs (optional) Overrides args passed to constructor
12161 this.delay = function(D, E, F, G){
12167 t = new Date().getTime();
12172 id = setInterval(C, d);
12177 * Cancel the last queued timeout
12179 this.cancel = function(){
12188 * Ext JS Library 1.1.1
12189 * Copyright(c) 2006-2007, Ext JS, LLC.
12191 * Originally Released Under LGPL - original licence link has changed is not relivant.
12194 * <script type="text/javascript">
12198 Roo.util.TaskRunner = function(A){
12200 var B = [], C = [];
12204 var E = function(){
12210 var F = function(){
12213 id = setInterval(H, A);
12217 var G = function(I){
12224 var H = function(){
12226 for(var i = 0, len = C.length; i < len; i++){
12236 var I = new Date().getTime();
12237 for(var i = 0, len = B.length; i < len; ++i){
12239 var itime = I - t.taskRunTime;
12240 if(t.interval <= itime){
12241 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12243 if(rt === false || t.taskRunCount === t.repeat){
12248 if(t.duration && t.duration <= (I - t.taskStartTime)){
12255 * Queues a new task.
12256 * @param {Object} task
12258 this.start = function(I){
12260 I.taskStartTime = new Date().getTime();
12262 I.taskRunCount = 0;
12267 this.stop = function(I){
12272 this.stopAll = function(){
12274 for(var i = 0, len = B.length; i < len; i++){
12285 Roo.TaskMgr = new Roo.util.TaskRunner();
12288 * Ext JS Library 1.1.1
12289 * Copyright(c) 2006-2007, Ext JS, LLC.
12291 * Originally Released Under LGPL - original licence link has changed is not relivant.
12294 * <script type="text/javascript">
12299 * @class Roo.util.MixedCollection
12300 * @extends Roo.util.Observable
12301 * A Collection class that maintains both numeric indexes and keys and exposes events.
12303 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12304 * collection (defaults to false)
12305 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12306 * and return the key value for that item. This is used when available to look up the key on items that
12307 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12308 * equivalent to providing an implementation for the {@link #getKey} method.
12310 Roo.util.MixedCollection = function(A, B){
12318 * Fires when the collection is cleared.
12323 * Fires when an item is added to the collection.
12324 * @param {Number} index The index at which the item was added.
12325 * @param {Object} o The item added.
12326 * @param {String} key The key associated with the added item.
12331 * Fires when an item is replaced in the collection.
12332 * @param {String} key he key associated with the new added.
12333 * @param {Object} old The item being replaced.
12334 * @param {Object} new The new item.
12339 * Fires when an item is removed from the collection.
12340 * @param {Object} o The item being removed.
12341 * @param {String} key (optional) The key associated with the removed item.
12346 this.allowFunctions = A === true;
12351 Roo.util.MixedCollection.superclass.constructor.call(this);
12354 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12355 allowFunctions : false,
12358 * Adds an item to the collection.
12359 * @param {String} key The key to associate with the item
12360 * @param {Object} o The item to add.
12361 * @return {Object} The item added.
12363 add : function(C, o){
12364 if(arguments.length == 1){
12366 C = this.getKey(o);
12368 if(typeof C == "undefined" || C === null){
12370 this.items.push(o);
12371 this.keys.push(null);
12373 var old = this.map[C];
12375 return this.replace(C, o);
12379 this.items.push(o);
12384 this.fireEvent("add", this.length-1, o, C);
12389 * MixedCollection has a generic way to fetch keys if you implement getKey.
12392 var mc = new Roo.util.MixedCollection();
12393 mc.add(someEl.dom.id, someEl);
12394 mc.add(otherEl.dom.id, otherEl);
12398 var mc = new Roo.util.MixedCollection();
12399 mc.getKey = function(el){
12405 // or via the constructor
12406 var mc = new Roo.util.MixedCollection(false, function(el){
12412 * @param o {Object} The item for which to find the key.
12413 * @return {Object} The key for the passed item.
12415 getKey : function(o){
12420 * Replaces an item in the collection.
12421 * @param {String} key The key associated with the item to replace, or the item to replace.
12422 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12423 * @return {Object} The new item.
12425 replace : function(D, o){
12426 if(arguments.length == 1){
12428 D = this.getKey(o);
12430 var E = this.item(D);
12431 if(typeof D == "undefined" || D === null || typeof E == "undefined"){
12432 return this.add(D, o);
12434 var F = this.indexOfKey(D);
12437 this.fireEvent("replace", D, E, o);
12442 * Adds all elements of an Array or an Object to the collection.
12443 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12444 * an Array of values, each of which are added to the collection.
12446 addAll : function(G){
12447 if(arguments.length > 1 || G instanceof Array){
12448 var args = arguments.length > 1 ? arguments : G;
12449 for(var i = 0, len = args.length; i < len; i++){
12454 if(this.allowFunctions || typeof G[D] != "function"){
12462 * Executes the specified function once for every item in the collection, passing each
12463 * item as the first and only parameter. returning false from the function will stop the iteration.
12464 * @param {Function} fn The function to execute for each item.
12465 * @param {Object} scope (optional) The scope in which to execute the function.
12467 each : function(fn, H){
12468 var I = [].concat(this.items); // each safe for removal
12469 for(var i = 0, len = I.length; i < len; i++){
12470 if(fn.call(H || I[i], I[i], i, len) === false){
12477 * Executes the specified function once for every key in the collection, passing each
12478 * key, and its associated item as the first two parameters.
12479 * @param {Function} fn The function to execute for each item.
12480 * @param {Object} scope (optional) The scope in which to execute the function.
12482 eachKey : function(fn, J){
12483 for(var i = 0, len = this.keys.length; i < len; i++){
12484 fn.call(J || window, this.keys[i], this.items[i], i, len);
12489 * Returns the first item in the collection which elicits a true return value from the
12490 * passed selection function.
12491 * @param {Function} fn The selection function to execute for each item.
12492 * @param {Object} scope (optional) The scope in which to execute the function.
12493 * @return {Object} The first item in the collection which returned true from the selection function.
12495 find : function(fn, K){
12496 for(var i = 0, len = this.items.length; i < len; i++){
12497 if(fn.call(K || window, this.items[i], this.keys[i])){
12498 return this.items[i];
12505 * Inserts an item at the specified index in the collection.
12506 * @param {Number} index The index to insert the item at.
12507 * @param {String} key The key to associate with the new item, or the item itself.
12508 * @param {Object} o (optional) If the second parameter was a key, the new item.
12509 * @return {Object} The item inserted.
12511 insert : function(L, M, o){
12512 if(arguments.length == 2){
12514 M = this.getKey(o);
12516 if(L >= this.length){
12517 return this.add(M, o);
12521 this.items.splice(L, 0, o);
12522 if(typeof M != "undefined" && M != null){
12526 this.keys.splice(L, 0, M);
12527 this.fireEvent("add", L, o, M);
12532 * Removed an item from the collection.
12533 * @param {Object} o The item to remove.
12534 * @return {Object} The item removed.
12536 remove : function(o){
12537 return this.removeAt(this.indexOf(o));
12541 * Remove an item from a specified index in the collection.
12542 * @param {Number} index The index within the collection of the item to remove.
12544 removeAt : function(N){
12545 if(N < this.length && N >= 0){
12547 var o = this.items[N];
12548 this.items.splice(N, 1);
12549 var M = this.keys[N];
12550 if(typeof M != "undefined"){
12551 delete this.map[M];
12554 this.keys.splice(N, 1);
12555 this.fireEvent("remove", o, M);
12560 * Removed an item associated with the passed key fom the collection.
12561 * @param {String} key The key of the item to remove.
12563 removeKey : function(O){
12564 return this.removeAt(this.indexOfKey(O));
12568 * Returns the number of items in the collection.
12569 * @return {Number} the number of items in the collection.
12571 getCount : function(){
12572 return this.length;
12576 * Returns index within the collection of the passed Object.
12577 * @param {Object} o The item to find the index of.
12578 * @return {Number} index of the item.
12580 indexOf : function(o){
12581 if(!this.items.indexOf){
12582 for(var i = 0, len = this.items.length; i < len; i++){
12583 if(this.items[i] == o) return i;
12587 return this.items.indexOf(o);
12592 * Returns index within the collection of the passed key.
12593 * @param {String} key The key to find the index of.
12594 * @return {Number} index of the key.
12596 indexOfKey : function(P){
12597 if(!this.keys.indexOf){
12598 for(var i = 0, len = this.keys.length; i < len; i++){
12599 if(this.keys[i] == P) return i;
12603 return this.keys.indexOf(P);
12608 * Returns the item associated with the passed key OR index. Key has priority over index.
12609 * @param {String/Number} key The key or index of the item.
12610 * @return {Object} The item associated with the passed key.
12612 item : function(Q){
12613 var R = typeof this.map[Q] != "undefined" ? this.map[Q] : this.items[Q];
12614 return typeof R != 'function' || this.allowFunctions ? R : null; // for prototype!
12618 * Returns the item at the specified index.
12619 * @param {Number} index The index of the item.
12622 itemAt : function(S){
12623 return this.items[S];
12627 * Returns the item associated with the passed key.
12628 * @param {String/Number} key The key of the item.
12629 * @return {Object} The item associated with the passed key.
12632 return this.map[T];
12636 * Returns true if the collection contains the passed Object as an item.
12637 * @param {Object} o The Object to look for in the collection.
12638 * @return {Boolean} True if the collection contains the Object as an item.
12640 contains : function(o){
12641 return this.indexOf(o) != -1;
12645 * Returns true if the collection contains the passed Object as a key.
12646 * @param {String} key The key to look for in the collection.
12647 * @return {Boolean} True if the collection contains the Object as a key.
12649 containsKey : function(U){
12650 return typeof this.map[U] != "undefined";
12654 * Removes all items from the collection.
12656 clear : function(){
12661 this.fireEvent("clear");
12665 * Returns the first item in the collection.
12666 * @return {Object} the first item in the collection..
12668 first : function(){
12669 return this.items[0];
12673 * Returns the last item in the collection.
12674 * @return {Object} the last item in the collection..
12677 return this.items[this.length-1];
12680 _sort : function(V, W, fn){
12681 var X = String(W).toUpperCase() == "DESC" ? -1 : 1;
12682 fn = fn || function(a, b){
12685 var c = [], k = this.keys, Y = this.items;
12686 for(var i = 0, len = Y.length; i < len; i++){
12687 c[c.length] = {key: k[i], value: Y[i], index: i};
12690 c.sort(function(a, b){
12691 var v = fn(a[V], b[V]) * X;
12693 v = (a.index < b.index ? -1 : 1);
12697 for(var i = 0, len = c.length; i < len; i++){
12702 this.fireEvent("sort", this);
12706 * Sorts this collection with the passed comparison function
12707 * @param {String} direction (optional) "ASC" or "DESC"
12708 * @param {Function} fn (optional) comparison function
12710 sort : function(Z, fn){
12711 this._sort("value", Z, fn);
12715 * Sorts this collection by keys
12716 * @param {String} direction (optional) "ASC" or "DESC"
12717 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12719 keySort : function(a, fn){
12720 this._sort("key", a, fn || function(a, b){
12721 return String(a).toUpperCase()-String(b).toUpperCase();
12726 * Returns a range of items in this collection
12727 * @param {Number} startIndex (optional) defaults to 0
12728 * @param {Number} endIndex (optional) default to the last item
12729 * @return {Array} An array of items
12731 getRange : function(b, d){
12732 var e = this.items;
12738 d = Math.min(typeof d == "undefined" ? this.length-1 : d, this.length-1);
12741 for(var i = b; i <= d; i++) {
12742 r[r.length] = e[i];
12745 for(var i = b; i >= d; i--) {
12746 r[r.length] = e[i];
12753 * Filter the <i>objects</i> in this collection by a specific property.
12754 * Returns a new collection that has been filtered.
12755 * @param {String} property A property on your objects
12756 * @param {String/RegExp} value Either string that the property values
12757 * should start with or a RegExp to test against the property
12758 * @return {MixedCollection} The new filtered collection
12760 filter : function(f, g){
12761 if(!g.exec){ // not a regex
12764 return this.clone();
12767 g = new RegExp("^" + Roo.escapeRe(g), "i");
12769 return this.filterBy(function(o){
12770 return o && g.test(o[f]);
12775 * Filter by a function. * Returns a new collection that has been filtered.
12776 * The passed function will be called with each
12777 * object in the collection. If the function returns true, the value is included
12778 * otherwise it is filtered.
12779 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12780 * @param {Object} scope (optional) The scope of the function (defaults to this)
12781 * @return {MixedCollection} The new filtered collection
12783 filterBy : function(fn, h){
12784 var r = new Roo.util.MixedCollection();
12785 r.getKey = this.getKey;
12786 var k = this.keys, it = this.items;
12787 for(var i = 0, len = it.length; i < len; i++){
12788 if(fn.call(h||this, it[i], k[i])){
12789 r.add(k[i], it[i]);
12796 * Creates a duplicate of this collection
12797 * @return {MixedCollection}
12799 clone : function(){
12800 var r = new Roo.util.MixedCollection();
12801 var k = this.keys, it = this.items;
12802 for(var i = 0, len = it.length; i < len; i++){
12803 r.add(k[i], it[i]);
12806 r.getKey = this.getKey;
12811 * Returns the item associated with the passed key or index.
12813 * @param {String/Number} key The key or index of the item.
12814 * @return {Object} The item associated with the passed key.
12816 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;
12819 * Ext JS Library 1.1.1
12820 * Copyright(c) 2006-2007, Ext JS, LLC.
12822 * Originally Released Under LGPL - original licence link has changed is not relivant.
12825 * <script type="text/javascript">
12828 * @class Roo.util.JSON
12829 * Modified version of Douglas Crockford"s json.js that doesn"t
12830 * mess with the Object prototype
12831 * http://www.json.org/js.html
12834 Roo.util.JSON = new (function(){
12835 var A = {}.hasOwnProperty ? true : false;
12837 // crashes Safari in some instances
12838 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12840 var B = function(n) {
12841 return n < 10 ? "0" + n : n;
12854 var C = function(s){
12855 if (/["\\\x00-\x1f]/.test(s)) {
12856 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12862 c = b.charCodeAt();
12864 Math.floor(c / 16).toString(16) +
12865 (c % 16).toString(16);
12868 return '"' + s + '"';
12871 var D = function(o){
12872 var a = ["["], b, i, l = o.length, v;
12873 for (i = 0; i < l; i += 1) {
12875 switch (typeof v) {
12885 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12894 var E = function(o){
12895 return '"' + o.getFullYear() + "-" +
12896 B(o.getMonth() + 1) + "-" +
12897 B(o.getDate()) + "T" +
12898 B(o.getHours()) + ":" +
12899 B(o.getMinutes()) + ":" +
12900 B(o.getSeconds()) + '"';
12904 * Encodes an Object, Array or other value
12905 * @param {Mixed} o The variable to encode
12906 * @return {String} The JSON string
12908 this.encode = function(o){
12909 if(typeof o == "undefined" || o === null){
12911 }else if(o instanceof Array){
12913 }else if(o instanceof Date){
12915 }else if(typeof o == "string"){
12917 }else if(typeof o == "number"){
12918 return isFinite(o) ? String(o) : "null";
12919 }else if(typeof o == "boolean"){
12922 var a = ["{"], b, i, v;
12924 if(!A || o.hasOwnProperty(i)) {
12926 switch (typeof v) {
12936 a.push(this.encode(i), ":",
12937 v === null ? "null" : this.encode(v));
12949 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12950 * @param {String} json The JSON string
12951 * @return {Object} The resulting object
12953 this.decode = function(F){
12957 return eval("(" + F + ')');
12961 * Shorthand for {@link Roo.util.JSON#encode}
12962 * @member Roo encode
12964 Roo.encode = Roo.util.JSON.encode;
12966 * Shorthand for {@link Roo.util.JSON#decode}
12967 * @member Roo decode
12969 Roo.decode = Roo.util.JSON.decode;
12973 * Ext JS Library 1.1.1
12974 * Copyright(c) 2006-2007, Ext JS, LLC.
12976 * Originally Released Under LGPL - original licence link has changed is not relivant.
12979 * <script type="text/javascript">
12983 * @class Roo.util.Format
12984 * Reusable data formatting functions
12987 Roo.util.Format = function(){
12988 var A = /^\s+|\s+$/g;
12991 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12992 * @param {String} value The string to truncate
12993 * @param {Number} length The maximum length to allow before truncating
12994 * @return {String} The converted text
12996 ellipsis : function(S, T){
12997 if(S && S.length > T){
12998 return S.substr(0, T-3)+"...";
13004 * Checks a reference and converts it to empty string if it is undefined
13005 * @param {Mixed} value Reference to check
13006 * @return {Mixed} Empty string if converted, otherwise the original value
13008 undef : function(U){
13009 return typeof U != "undefined" ? U : "";
13013 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13014 * @param {String} value The string to encode
13015 * @return {String} The encoded text
13017 htmlEncode : function(V){
13018 return !V ? V : String(V).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13022 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13023 * @param {String} value The string to decode
13024 * @return {String} The decoded text
13026 htmlDecode : function(W){
13027 return !W ? W : String(W).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13031 * Trims any whitespace from either side of a string
13032 * @param {String} value The text to trim
13033 * @return {String} The trimmed text
13035 trim : function(X){
13036 return String(X).replace(A, "");
13040 * Returns a substring from within an original string
13041 * @param {String} value The original text
13042 * @param {Number} start The start index of the substring
13043 * @param {Number} length The length of the substring
13044 * @return {String} The substring
13046 substr : function(Y, Z, a){
13047 return String(Y).substr(Z, a);
13051 * Converts a string to all lower case letters
13052 * @param {String} value The text to convert
13053 * @return {String} The converted text
13055 lowercase : function(b){
13056 return String(b).toLowerCase();
13060 * Converts a string to all upper case letters
13061 * @param {String} value The text to convert
13062 * @return {String} The converted text
13064 uppercase : function(c){
13065 return String(c).toUpperCase();
13069 * Converts the first character only of a string to upper case
13070 * @param {String} value The text to convert
13071 * @return {String} The converted text
13073 capitalize : function(d){
13074 return !d ? d : d.charAt(0).toUpperCase() + d.substr(1).toLowerCase();
13078 call : function(e, fn){
13079 if(arguments.length > 2){
13080 var args = Array.prototype.slice.call(arguments, 2);
13083 return /** eval:var:value */ eval(fn).apply(window, args);
13085 /** eval:var:value */
13086 return /** eval:var:value */ eval(fn).call(window, e);
13091 * Format a number as US currency
13092 * @param {Number/String} value The numeric value to format
13093 * @return {String} The formatted currency string
13095 usMoney : function(v){
13096 v = (Math.round((v-0)*100))/100;
13097 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13099 var ps = v.split('.');
13101 var g = ps[1] ? '.'+ ps[1] : '.00';
13102 var r = /(\d+)(\d{3})/;
13103 while (r.test(f)) {
13104 f = f.replace(r, '$1' + ',' + '$2');
13106 return "$" + f + g ;
13110 * Parse a value into a formatted date using the specified format pattern.
13111 * @param {Mixed} value The value to format
13112 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13113 * @return {String} The formatted date string
13115 date : function(v, h){
13119 if(!(v instanceof Date)){
13120 v = new Date(Date.parse(v));
13122 return v.dateFormat(h || "m/d/Y");
13126 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13127 * @param {String} format Any valid date format string
13128 * @return {Function} The date formatting function
13130 dateRenderer : function(i){
13131 return function(v){
13132 return Roo.util.Format.date(v, i);
13137 stripTagsRE : /<\/?[^>]+>/gi,
13140 * Strips all HTML tags
13141 * @param {Mixed} value The text from which to strip tags
13142 * @return {String} The stripped text
13144 stripTags : function(v){
13145 return !v ? v : String(v).replace(this.stripTagsRE, "");
13151 * Ext JS Library 1.1.1
13152 * Copyright(c) 2006-2007, Ext JS, LLC.
13154 * Originally Released Under LGPL - original licence link has changed is not relivant.
13157 * <script type="text/javascript">
13164 * @class Roo.MasterTemplate
13165 * @extends Roo.Template
13166 * Provides a template that can have child templates. The syntax is:
13168 var t = new Roo.MasterTemplate(
13169 '<select name="{name}">',
13170 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13173 t.add('options', {value: 'foo', text: 'bar'});
13174 // or you can add multiple child elements in one shot
13175 t.addAll('options', [
13176 {value: 'foo', text: 'bar'},
13177 {value: 'foo2', text: 'bar2'},
13178 {value: 'foo3', text: 'bar3'}
13180 // then append, applying the master template values
13181 t.append('my-form', {name: 'my-select'});
13183 * A name attribute for the child template is not required if you have only one child
13184 * template or you want to refer to them by index.
13186 Roo.MasterTemplate = function(){
13187 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13188 this.originalHtml = this.html;
13190 var m, re = this.subTemplateRe;
13193 while(m = re.exec(this.html)){
13194 var name = m[1], content = m[2];
13199 tpl : new Roo.Template(content)
13205 st[A].tpl.compile();
13206 st[A].tpl.call = this.call.createDelegate(this);
13213 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13215 * The regular expression used to match sub templates
13219 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13222 * Applies the passed values to a child template.
13223 * @param {String/Number} name (optional) The name or index of the child template
13224 * @param {Array/Object} values The values to be applied to the template
13225 * @return {MasterTemplate} this
13227 add : function(B, C){
13228 if(arguments.length == 1){
13232 var s = this.subs[B];
13233 s.buffer[s.buffer.length] = s.tpl.apply(C);
13238 * Applies all the passed values to a child template.
13239 * @param {String/Number} name (optional) The name or index of the child template
13240 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13241 * @param {Boolean} reset (optional) True to reset the template first
13242 * @return {MasterTemplate} this
13244 fill : function(D, E, F){
13246 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13254 for(var i = 0, len = E.length; i < len; i++){
13261 * Resets the template for reuse
13262 * @return {MasterTemplate} this
13264 reset : function(){
13266 for(var i = 0; i < this.subCount; i++){
13272 applyTemplate : function(G){
13275 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, I){
13276 return s[++H].buffer.join("");
13278 return Roo.MasterTemplate.superclass.applyTemplate.call(this, G);
13281 apply : function(){
13282 return this.applyTemplate.apply(this, arguments);
13285 compile : function(){return this;}
13289 * Alias for fill().
13292 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13294 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13295 * var tpl = Roo.MasterTemplate.from('element-id');
13296 * @param {String/HTMLElement} el
13297 * @param {Object} config
13300 Roo.MasterTemplate.from = function(el, I){
13301 el = Roo.getDom(el);
13302 return new Roo.MasterTemplate(el.value || el.innerHTML, I || '');
13306 * Ext JS Library 1.1.1
13307 * Copyright(c) 2006-2007, Ext JS, LLC.
13309 * Originally Released Under LGPL - original licence link has changed is not relivant.
13312 * <script type="text/javascript">
13317 * @class Roo.util.CSS
13318 * Utility class for manipulating CSS rules
13321 Roo.util.CSS = function(){
13325 var C = /(-[a-z])/gi;
13326 var D = function(m, a){ return a.charAt(1).toUpperCase(); };
13330 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13331 * tag and appended to the HEAD of the document.
13332 * @param {String} cssText The text containing the css rules
13333 * @param {String} id An id to add to the stylesheet for later removal
13334 * @return {StyleSheet}
13336 createStyleSheet : function(P, id){
13338 var Q = B.getElementsByTagName("head")[0];
13339 var R = B.createElement("style");
13340 R.setAttribute("type", "text/css");
13342 R.setAttribute("id", id);
13350 R.appendChild(B.createTextNode(P));
13356 ss = R.styleSheet ? R.styleSheet : (R.sheet || B.styleSheets[B.styleSheets.length-1]);
13359 this.cacheStyleSheet(ss);
13364 * Removes a style or link tag by id
13365 * @param {String} id The id of the tag
13367 removeStyleSheet : function(id){
13368 var S = B.getElementById(id);
13370 S.parentNode.removeChild(S);
13375 * Dynamically swaps an existing stylesheet reference for a new one
13376 * @param {String} id The id of an existing link tag to remove
13377 * @param {String} url The href of the new stylesheet to include
13379 swapStyleSheet : function(id, T){
13380 this.removeStyleSheet(id);
13381 var ss = B.createElement("link");
13382 ss.setAttribute("rel", "stylesheet");
13383 ss.setAttribute("type", "text/css");
13384 ss.setAttribute("id", id);
13385 ss.setAttribute("href", T);
13386 B.getElementsByTagName("head")[0].appendChild(ss);
13390 * Refresh the rule cache if you have dynamically added stylesheets
13391 * @return {Object} An object (hash) of rules indexed by selector
13393 refreshCache : function(){
13394 return this.getRules(true);
13398 cacheStyleSheet : function(ss){
13402 try{// try catch for cross domain access issue
13403 var ssRules = ss.cssRules || ss.rules;
13404 for(var j = ssRules.length-1; j >= 0; --j){
13405 R[ssRules[j].selectorText] = ssRules[j];
13411 * Gets all css rules for the document
13412 * @param {Boolean} refreshCache true to refresh the internal cache
13413 * @return {Object} An object (hash) of rules indexed by selector
13415 getRules : function(U){
13416 if(R == null || U){
13418 var ds = B.styleSheets;
13419 for(var i =0, len = ds.length; i < len; i++){
13421 this.cacheStyleSheet(ds[i]);
13429 * Gets an an individual CSS rule by selector(s)
13430 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13431 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13432 * @return {CSSRule} The CSS rule or null if one is not found
13434 getRule : function(V, W){
13435 var rs = this.getRules(W);
13436 if(!(V instanceof Array)){
13439 for(var i = 0; i < V.length; i++){
13449 * Updates a rule property
13450 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13451 * @param {String} property The css property
13452 * @param {String} value The new value for the property
13453 * @return {Boolean} true If a rule was found and updated
13455 updateRule : function(X, Y, Z){
13456 if(!(X instanceof Array)){
13457 var rule = this.getRule(X);
13459 rule.style[Y.replace(C, D)] = Z;
13463 for(var i = 0; i < X.length; i++){
13464 if(this.updateRule(X[i], Y, Z)){
13475 * Ext JS Library 1.1.1
13476 * Copyright(c) 2006-2007, Ext JS, LLC.
13478 * Originally Released Under LGPL - original licence link has changed is not relivant.
13481 * <script type="text/javascript">
13487 * @class Roo.util.ClickRepeater
13488 * @extends Roo.util.Observable
13490 * A wrapper class which can be applied to any element. Fires a "click" event while the
13491 * mouse is pressed. The interval between firings may be specified in the config but
13492 * defaults to 10 milliseconds.
13494 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13496 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13497 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13498 * Similar to an autorepeat key delay.
13499 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13500 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13501 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13502 * "interval" and "delay" are ignored. "immediate" is honored.
13503 * @cfg {Boolean} preventDefault True to prevent the default click event
13504 * @cfg {Boolean} stopDefault True to stop the default click event
13507 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13508 * 2007-02-02 jvs Renamed to ClickRepeater
13509 * 2007-02-03 jvs Modifications for FF Mac and Safari
13512 * @param {String/HTMLElement/Element} el The element to listen on
13513 * @param {Object} config
13515 Roo.util.ClickRepeater = function(el, A)
13517 this.el = Roo.get(el);
13518 this.el.unselectable();
13520 Roo.apply(this, A);
13525 * Fires when the mouse button is depressed.
13526 * @param {Roo.util.ClickRepeater} this
13528 "mousedown" : true,
13531 * Fires on a specified interval during the time the element is pressed.
13532 * @param {Roo.util.ClickRepeater} this
13537 * Fires when the mouse key is released.
13538 * @param {Roo.util.ClickRepeater} this
13543 this.el.on("mousedown", this.handleMouseDown, this);
13544 if(this.preventDefault || this.stopDefault){
13545 this.el.on("click", function(e){
13546 if(this.preventDefault){
13547 e.preventDefault();
13549 if(this.stopDefault){
13555 // allow inline handler
13557 this.on("click", this.handler, this.scope || this);
13561 Roo.util.ClickRepeater.superclass.constructor.call(this);
13564 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13567 preventDefault : true,
13568 stopDefault : false,
13572 handleMouseDown : function(){
13573 clearTimeout(this.timer);
13575 if(this.pressClass){
13576 this.el.addClass(this.pressClass);
13579 this.mousedownTime = new Date();
13581 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13582 this.el.on("mouseout", this.handleMouseOut, this);
13584 this.fireEvent("mousedown", this);
13585 this.fireEvent("click", this);
13587 this.timer = this.click.defer(this.delay || this.interval, this);
13591 click : function(){
13592 this.fireEvent("click", this);
13593 this.timer = this.click.defer(this.getInterval(), this);
13597 getInterval: function(){
13598 if(!this.accelerate){
13599 return this.interval;
13601 var B = this.mousedownTime.getElapsed();
13604 }else if(B < 1700){
13606 }else if(B < 2600){
13608 }else if(B < 3500){
13610 }else if(B < 4400){
13612 }else if(B < 5300){
13614 }else if(B < 6200){
13622 handleMouseOut : function(){
13623 clearTimeout(this.timer);
13624 if(this.pressClass){
13625 this.el.removeClass(this.pressClass);
13628 this.el.on("mouseover", this.handleMouseReturn, this);
13632 handleMouseReturn : function(){
13633 this.el.un("mouseover", this.handleMouseReturn);
13634 if(this.pressClass){
13635 this.el.addClass(this.pressClass);
13642 handleMouseUp : function(){
13643 clearTimeout(this.timer);
13644 this.el.un("mouseover", this.handleMouseReturn);
13645 this.el.un("mouseout", this.handleMouseOut);
13646 Roo.get(document).un("mouseup", this.handleMouseUp);
13647 this.el.removeClass(this.pressClass);
13648 this.fireEvent("mouseup", this);
13653 * Ext JS Library 1.1.1
13654 * Copyright(c) 2006-2007, Ext JS, LLC.
13656 * Originally Released Under LGPL - original licence link has changed is not relivant.
13659 * <script type="text/javascript">
13664 * @class Roo.KeyNav
13665 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13666 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13667 * way to implement custom navigation schemes for any UI component.</p>
13668 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13669 * pageUp, pageDown, del, home, end. Usage:</p>
13671 var nav = new Roo.KeyNav("my-element", {
13672 "left" : function(e){
13673 this.moveLeft(e.ctrlKey);
13675 "right" : function(e){
13676 this.moveRight(e.ctrlKey);
13678 "enter" : function(e){
13685 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13686 * @param {Object} config The config
13688 Roo.KeyNav = function(el, A){
13689 this.el = Roo.get(el);
13690 Roo.apply(this, A);
13691 if(!this.disabled){
13692 this.disabled = true;
13697 Roo.KeyNav.prototype = {
13699 * @cfg {Boolean} disabled
13700 * True to disable this KeyNav instance (defaults to false)
13704 * @cfg {String} defaultEventAction
13705 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13706 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13707 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13709 defaultEventAction: "stopEvent",
13711 * @cfg {Boolean} forceKeyDown
13712 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13713 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13714 * handle keydown instead of keypress.
13716 forceKeyDown : false,
13719 prepareEvent : function(e){
13720 var k = e.getKey();
13721 var h = this.keyToHandler[k];
13722 //if(h && this[h]){
13723 // e.stopPropagation();
13725 if(Roo.isSafari && h && k >= 37 && k <= 40){
13731 relay : function(e){
13732 var k = e.getKey();
13733 var h = this.keyToHandler[k];
13735 if(this.doRelay(e, this[h], h) !== true){
13736 e[this.defaultEventAction]();
13742 doRelay : function(e, h, B){
13743 return h.call(this.scope || this, e);
13746 // possible handlers
13760 // quick lookup hash
13777 * Enable this KeyNav
13779 enable: function(){
13781 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13782 // the EventObject will normalize Safari automatically
13783 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13784 this.el.on("keydown", this.relay, this);
13786 this.el.on("keydown", this.prepareEvent, this);
13787 this.el.on("keypress", this.relay, this);
13790 this.disabled = false;
13795 * Disable this KeyNav
13797 disable: function(){
13798 if(!this.disabled){
13799 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13800 this.el.un("keydown", this.relay);
13802 this.el.un("keydown", this.prepareEvent);
13803 this.el.un("keypress", this.relay);
13806 this.disabled = true;
13812 * Ext JS Library 1.1.1
13813 * Copyright(c) 2006-2007, Ext JS, LLC.
13815 * Originally Released Under LGPL - original licence link has changed is not relivant.
13818 * <script type="text/javascript">
13823 * @class Roo.KeyMap
13824 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13825 * The constructor accepts the same config object as defined by {@link #addBinding}.
13826 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13827 * combination it will call the function with this signature (if the match is a multi-key
13828 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13829 * A KeyMap can also handle a string representation of keys.<br />
13832 // map one key by key code
13833 var map = new Roo.KeyMap("my-element", {
13834 key: 13, // or Roo.EventObject.ENTER
13839 // map multiple keys to one action by string
13840 var map = new Roo.KeyMap("my-element", {
13846 // map multiple keys to multiple actions by strings and array of codes
13847 var map = new Roo.KeyMap("my-element", [
13850 fn: function(){ alert("Return was pressed"); }
13853 fn: function(){ alert('a, b or c was pressed'); }
13858 fn: function(){ alert('Control + shift + tab was pressed.'); }
13862 * <b>Note: A KeyMap starts enabled</b>
13864 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13865 * @param {Object} config The config (see {@link #addBinding})
13866 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13868 Roo.KeyMap = function(el, A, B){
13869 this.el = Roo.get(el);
13870 this.eventName = B || "keydown";
13871 this.bindings = [];
13873 this.addBinding(A);
13879 Roo.KeyMap.prototype = {
13881 * True to stop the event from bubbling and prevent the default browser action if the
13882 * key was handled by the KeyMap (defaults to false)
13888 * Add a new binding to this KeyMap. The following config object properties are supported:
13890 Property Type Description
13891 ---------- --------------- ----------------------------------------------------------------------
13892 key String/Array A single keycode or an array of keycodes to handle
13893 shift Boolean True to handle key only when shift is pressed (defaults to false)
13894 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13895 alt Boolean True to handle key only when alt is pressed (defaults to false)
13896 fn Function The function to call when KeyMap finds the expected key combination
13897 scope Object The scope of the callback function
13903 var map = new Roo.KeyMap(document, {
13904 key: Roo.EventObject.ENTER,
13909 //Add a new binding to the existing KeyMap later
13917 * @param {Object/Array} config A single KeyMap config or an array of configs
13919 addBinding : function(C){
13920 if(C instanceof Array){
13921 for(var i = 0, len = C.length; i < len; i++){
13922 this.addBinding(C[i]);
13932 if(typeof D == "string"){
13934 var keyString = D.toUpperCase();
13935 for(var j = 0, len = keyString.length; j < len; j++){
13936 ks.push(keyString.charCodeAt(j));
13941 var I = D instanceof Array;
13942 var J = function(e){
13943 if((!E || e.shiftKey) && (!F || e.ctrlKey) && (!G || e.altKey)){
13944 var k = e.getKey();
13946 for(var i = 0, len = D.length; i < len; i++){
13948 if(this.stopEvent){
13952 fn.call(H || window, k, e);
13958 if(this.stopEvent){
13962 fn.call(H || window, k, e);
13967 this.bindings.push(J);
13971 * Shorthand for adding a single key listener
13972 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13973 * following options:
13974 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13975 * @param {Function} fn The function to call
13976 * @param {Object} scope (optional) The scope of the function
13978 on : function(K, fn, L){
13980 if(typeof K == "object" && !(K instanceof Array)){
14000 handleKeyDown : function(e){
14001 if(this.enabled){ //just in case
14002 var b = this.bindings;
14003 for(var i = 0, len = b.length; i < len; i++){
14004 b[i].call(this, e);
14010 * Returns true if this KeyMap is enabled
14011 * @return {Boolean}
14013 isEnabled : function(){
14014 return this.enabled;
14018 * Enables this KeyMap
14020 enable: function(){
14022 this.el.on(this.eventName, this.handleKeyDown, this);
14023 this.enabled = true;
14028 * Disable this KeyMap
14030 disable: function(){
14032 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14033 this.enabled = false;
14039 * Ext JS Library 1.1.1
14040 * Copyright(c) 2006-2007, Ext JS, LLC.
14042 * Originally Released Under LGPL - original licence link has changed is not relivant.
14045 * <script type="text/javascript">
14050 * @class Roo.util.TextMetrics
14051 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14052 * wide, in pixels, a given block of text will be.
14055 Roo.util.TextMetrics = function(){
14059 * Measures the size of the specified text
14060 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14061 * that can affect the size of the rendered text
14062 * @param {String} text The text to measure
14063 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14064 * in order to accurately measure the text height
14065 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14067 measure : function(el, E, F){
14069 A = Roo.util.TextMetrics.Instance(el, F);
14073 A.setFixedWidth(F || 'auto');
14074 return A.getSize(E);
14078 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14079 * the overhead of multiple calls to initialize the style properties on each measurement.
14080 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14081 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14082 * in order to accurately measure the text height
14083 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14085 createInstance : function(el, G){
14086 return Roo.util.TextMetrics.Instance(el, G);
14091 Roo.util.TextMetrics.Instance = function(B, C){
14092 var ml = new Roo.Element(document.createElement('div'));
14093 document.body.appendChild(ml.dom);
14094 ml.position('absolute');
14095 ml.setLeftTop(-1000, -1000);
14104 * Returns the size of the specified text based on the internal element's style and width properties
14105 * @param {String} text The text to measure
14106 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14108 getSize : function(E){
14110 var s = ml.getSize();
14116 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14117 * that can affect the size of the rendered text
14118 * @param {String/HTMLElement} el The element, dom node or id
14120 bind : function(el){
14122 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14127 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14128 * to set a fixed width in order to accurately measure the text height.
14129 * @param {Number} width The width to set on the element
14131 setFixedWidth : function(F){
14136 * Returns the measured width of the specified text
14137 * @param {String} text The text to measure
14138 * @return {Number} width The width in pixels
14140 getWidth : function(G){
14141 ml.dom.style.width = 'auto';
14142 return this.getSize(G).width;
14146 * Returns the measured height of the specified text. For multiline text, be sure to call
14147 * {@link #setFixedWidth} if necessary.
14148 * @param {String} text The text to measure
14149 * @return {Number} height The height in pixels
14151 getHeight : function(H){
14152 return this.getSize(H).height;
14161 // backwards compat
14162 Roo.Element.measureText = Roo.util.TextMetrics.measure;
14165 * Ext JS Library 1.1.1
14166 * Copyright(c) 2006-2007, Ext JS, LLC.
14168 * Originally Released Under LGPL - original licence link has changed is not relivant.
14171 * <script type="text/javascript">
14175 * @class Roo.state.Provider
14176 * Abstract base class for state provider implementations. This class provides methods
14177 * for encoding and decoding <b>typed</b> variables including dates and defines the
14178 * Provider interface.
14180 Roo.state.Provider = function(){
14182 * @event statechange
14183 * Fires when a state change occurs.
14184 * @param {Provider} this This state provider
14185 * @param {String} key The state key which was changed
14186 * @param {String} value The encoded value for the state
14189 "statechange": true
14192 Roo.state.Provider.superclass.constructor.call(this);
14194 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14196 * Returns the current value for a key
14197 * @param {String} name The key name
14198 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14199 * @return {Mixed} The state data
14201 get : function(A, B){
14202 return typeof this.state[A] == "undefined" ?
14207 * Clears a value from the state
14208 * @param {String} name The key name
14210 clear : function(C){
14211 delete this.state[C];
14212 this.fireEvent("statechange", this, C, null);
14216 * Sets the value for a key
14217 * @param {String} name The key name
14218 * @param {Mixed} value The value to set
14220 set : function(D, E){
14222 this.fireEvent("statechange", this, D, E);
14226 * Decodes a string previously encoded with {@link #encodeValue}.
14227 * @param {String} value The value to decode
14228 * @return {Mixed} The decoded value
14230 decodeValue : function(F){
14231 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14232 var G = re.exec(unescape(F));
14233 if(!G || !G[1]) return; // non state cookie
14238 return parseFloat(v);
14240 return new Date(Date.parse(v));
14245 var values = v.split("^");
14246 for(var i = 0, len = values.length; i < len; i++){
14247 all.push(this.decodeValue(values[i]));
14252 var values = v.split("^");
14253 for(var i = 0, len = values.length; i < len; i++){
14254 var kv = values[i].split("=");
14255 all[kv[0]] = this.decodeValue(kv[1]);
14264 * Encodes a value including type information. Decode with {@link #decodeValue}.
14265 * @param {Mixed} value The value to encode
14266 * @return {String} The encoded value
14268 encodeValue : function(v){
14270 if(typeof v == "number"){
14272 }else if(typeof v == "boolean"){
14273 I = "b:" + (v ? "1" : "0");
14274 }else if(v instanceof Date){
14275 I = "d:" + v.toGMTString();
14276 }else if(v instanceof Array){
14278 for(var i = 0, len = v.length; i < len; i++){
14279 flat += this.encodeValue(v[i]);
14280 if(i != len-1) flat += "^";
14284 }else if(typeof v == "object"){
14287 if(typeof v[key] != "function"){
14288 flat += key + "=" + this.encodeValue(v[key]) + "^";
14292 I = "o:" + flat.substring(0, flat.length-1);
14303 * Ext JS Library 1.1.1
14304 * Copyright(c) 2006-2007, Ext JS, LLC.
14306 * Originally Released Under LGPL - original licence link has changed is not relivant.
14309 * <script type="text/javascript">
14312 * @class Roo.state.Manager
14313 * This is the global state manager. By default all components that are "state aware" check this class
14314 * for state information if you don't pass them a custom state provider. In order for this class
14315 * to be useful, it must be initialized with a provider when your application initializes.
14317 // in your initialization function
14319 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14321 // supposed you have a {@link Roo.BorderLayout}
14322 var layout = new Roo.BorderLayout(...);
14323 layout.restoreState();
14324 // or a {Roo.BasicDialog}
14325 var dialog = new Roo.BasicDialog(...);
14326 dialog.restoreState();
14330 Roo.state.Manager = function(){
14331 var A = new Roo.state.Provider();
14335 * Configures the default state provider for your application
14336 * @param {Provider} stateProvider The state provider to set
14338 setProvider : function(H){
14343 * Returns the current value for a key
14344 * @param {String} name The key name
14345 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14346 * @return {Mixed} The state data
14348 get : function(I, J){
14349 return A.get(I, J);
14353 * Sets the value for a key
14354 * @param {String} name The key name
14355 * @param {Mixed} value The state data
14357 set : function(K, L){
14362 * Clears a value from the state
14363 * @param {String} name The key name
14365 clear : function(M){
14370 * Gets the currently configured state provider
14371 * @return {Provider} The state provider
14373 getProvider : function(){
14381 * Ext JS Library 1.1.1
14382 * Copyright(c) 2006-2007, Ext JS, LLC.
14384 * Originally Released Under LGPL - original licence link has changed is not relivant.
14387 * <script type="text/javascript">
14390 * @class Roo.state.CookieProvider
14391 * @extends Roo.state.Provider
14392 * The default Provider implementation which saves state via cookies.
14395 var cp = new Roo.state.CookieProvider({
14397 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14398 domain: "roojs.com"
14400 Roo.state.Manager.setProvider(cp);
14402 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14403 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14404 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14405 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14406 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14407 * domain the page is running on including the 'www' like 'www.roojs.com')
14408 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14410 * Create a new CookieProvider
14411 * @param {Object} config The configuration object
14413 Roo.state.CookieProvider = function(A){
14414 Roo.state.CookieProvider.superclass.constructor.call(this);
14416 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14417 this.domain = null;
14418 this.secure = false;
14419 Roo.apply(this, A);
14420 this.state = this.readCookies();
14423 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14425 set : function(B, C){
14426 if(typeof C == "undefined" || C === null){
14431 this.setCookie(B, C);
14432 Roo.state.CookieProvider.superclass.set.call(this, B, C);
14436 clear : function(D){
14437 this.clearCookie(D);
14438 Roo.state.CookieProvider.superclass.clear.call(this, D);
14442 readCookies : function(){
14444 var c = document.cookie + ";";
14445 var re = /\s?(.*?)=(.*?);/g;
14447 while((F = re.exec(c)) != null){
14450 if(D && D.substring(0,3) == "ys-"){
14451 E[D.substr(3)] = this.decodeValue(C);
14458 setCookie : function(G, H){
14459 document.cookie = "ys-"+ G + "=" + this.encodeValue(H) +
14460 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14461 ((this.path == null) ? "" : ("; path=" + this.path)) +
14462 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14463 ((this.secure == true) ? "; secure" : "");
14467 clearCookie : function(I){
14468 document.cookie = "ys-" + I + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14469 ((this.path == null) ? "" : ("; path=" + this.path)) +
14470 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14471 ((this.secure == true) ? "; secure" : "");
14476 * Ext JS Library 1.1.1
14477 * Copyright(c) 2006-2007, Ext JS, LLC.
14479 * Originally Released Under LGPL - original licence link has changed is not relivant.
14482 * <script type="text/javascript">
14488 * These classes are derivatives of the similarly named classes in the YUI Library.
14489 * The original license:
14490 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
14491 * Code licensed under the BSD License:
14492 * http://developer.yahoo.net/yui/license.txt
14497 var A=Roo.EventManager;
14501 * @class Roo.dd.DragDrop
14502 * Defines the interface and base operation of items that that can be
14503 * dragged or can be drop targets. It was designed to be extended, overriding
14504 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
14505 * Up to three html elements can be associated with a DragDrop instance:
14507 * <li>linked element: the element that is passed into the constructor.
14508 * This is the element which defines the boundaries for interaction with
14509 * other DragDrop objects.</li>
14510 * <li>handle element(s): The drag operation only occurs if the element that
14511 * was clicked matches a handle element. By default this is the linked
14512 * element, but there are times that you will want only a portion of the
14513 * linked element to initiate the drag operation, and the setHandleElId()
14514 * method provides a way to define this.</li>
14515 * <li>drag element: this represents the element that would be moved along
14516 * with the cursor during a drag operation. By default, this is the linked
14517 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
14518 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
14521 * This class should not be instantiated until the onload event to ensure that
14522 * the associated elements are available.
14523 * The following would define a DragDrop obj that would interact with any
14524 * other DragDrop obj in the "group1" group:
14526 * dd = new Roo.dd.DragDrop("div1", "group1");
14528 * Since none of the event handlers have been implemented, nothing would
14529 * actually happen if you were to run the code above. Normally you would
14530 * override this class or one of the default implementations, but you can
14531 * also override the methods you want on an instance of the class...
14533 * dd.onDragDrop = function(e, id) {
14534 * alert("dd was dropped on " + id);
14538 * @param {String} id of the element that is linked to this instance
14539 * @param {String} sGroup the group of related DragDrop objects
14540 * @param {object} config an object containing configurable attributes
14541 * Valid properties for DragDrop:
14542 * padding, isTarget, maintainOffset, primaryButtonOnly
14544 Roo.dd.DragDrop = function(id, C, D) {
14546 this.init(id, C, D);
14550 Roo.dd.DragDrop.prototype = {
14553 * The id of the element associated with this object. This is what we
14554 * refer to as the "linked element" because the size and position of
14555 * this element is used to determine when the drag and drop objects have
14563 * Configuration attributes passed into the constructor
14570 * The id of the element that will be dragged. By default this is same
14571 * as the linked element , but could be changed to another element. Ex:
14573 * @property dragElId
14580 * the id of the element that initiates the drag operation. By default
14581 * this is the linked element, but could be changed to be a child of this
14582 * element. This lets us do things like only starting the drag when the
14583 * header element within the linked html element is clicked.
14584 * @property handleElId
14591 * An associative array of HTML tags that will be ignored if clicked.
14592 * @property invalidHandleTypes
14593 * @type {string: string}
14595 invalidHandleTypes: null,
14598 * An associative array of ids for elements that will be ignored if clicked
14599 * @property invalidHandleIds
14600 * @type {string: string}
14602 invalidHandleIds: null,
14605 * An indexted array of css class names for elements that will be ignored
14607 * @property invalidHandleClasses
14610 invalidHandleClasses: null,
14613 * The linked element's absolute X position at the time the drag was
14615 * @property startPageX
14622 * The linked element's absolute X position at the time the drag was
14624 * @property startPageY
14631 * The group defines a logical collection of DragDrop objects that are
14632 * related. Instances only get events when interacting with other
14633 * DragDrop object in the same group. This lets us define multiple
14634 * groups using a single DragDrop subclass if we want.
14636 * @type {string: string}
14641 * Individual drag/drop instances can be locked. This will prevent
14642 * onmousedown start drag.
14650 * Lock this instance
14653 lock: function() { this.locked = true; },
14656 * Unlock this instace
14659 unlock: function() { this.locked = false; },
14662 * By default, all insances can be a drop target. This can be disabled by
14663 * setting isTarget to false.
14670 * The padding configured for this drag and drop object for calculating
14671 * the drop zone intersection with this object.
14678 * Cached reference to the linked element
14679 * @property _domRef
14685 * Internal typeof flag
14686 * @property __ygDragDrop
14689 __ygDragDrop: true,
14692 * Set to true when horizontal contraints are applied
14693 * @property constrainX
14700 * Set to true when vertical contraints are applied
14701 * @property constrainY
14708 * The left constraint
14716 * The right constraint
14724 * The up constraint
14733 * The down constraint
14741 * Maintain offsets when we resetconstraints. Set to true when you want
14742 * the position of the element relative to its parent to stay the same
14743 * when the page changes
14745 * @property maintainOffset
14748 maintainOffset: false,
14751 * Array of pixel locations the element will snap to if we specified a
14752 * horizontal graduation/interval. This array is generated automatically
14753 * when you define a tick interval.
14760 * Array of pixel locations the element will snap to if we specified a
14761 * vertical graduation/interval. This array is generated automatically
14762 * when you define a tick interval.
14769 * By default the drag and drop instance will only respond to the primary
14770 * button click (left button for a right-handed mouse). Set to true to
14771 * allow drag and drop to start with any mouse click that is propogated
14773 * @property primaryButtonOnly
14776 primaryButtonOnly: true,
14779 * The availabe property is false until the linked dom element is accessible.
14780 * @property available
14786 * By default, drags can only be initiated if the mousedown occurs in the
14787 * region the linked element is. This is done in part to work around a
14788 * bug in some browsers that mis-report the mousedown if the previous
14789 * mouseup happened outside of the window. This property is set to true
14790 * if outer handles are defined.
14792 * @property hasOuterHandles
14796 hasOuterHandles: false,
14799 * Code that executes immediately before the startDrag event
14800 * @method b4StartDrag
14803 b4StartDrag: function(x, y) { },
14806 * Abstract method called after a drag/drop object is clicked
14807 * and the drag or mousedown time thresholds have beeen met.
14808 * @method startDrag
14809 * @param {int} X click location
14810 * @param {int} Y click location
14812 startDrag: function(x, y) { /* override this */ },
14815 * Code that executes immediately before the onDrag event
14819 b4Drag: function(e) { },
14822 * Abstract method called during the onMouseMove event while dragging an
14825 * @param {Event} e the mousemove event
14827 onDrag: function(e) { /* override this */ },
14830 * Abstract method called when this element fist begins hovering over
14831 * another DragDrop obj
14832 * @method onDragEnter
14833 * @param {Event} e the mousemove event
14834 * @param {String|DragDrop[]} id In POINT mode, the element
14835 * id this is hovering over. In INTERSECT mode, an array of one or more
14836 * dragdrop items being hovered over.
14838 onDragEnter: function(e, id) { /* override this */ },
14841 * Code that executes immediately before the onDragOver event
14842 * @method b4DragOver
14845 b4DragOver: function(e) { },
14848 * Abstract method called when this element is hovering over another
14850 * @method onDragOver
14851 * @param {Event} e the mousemove event
14852 * @param {String|DragDrop[]} id In POINT mode, the element
14853 * id this is hovering over. In INTERSECT mode, an array of dd items
14854 * being hovered over.
14856 onDragOver: function(e, id) { /* override this */ },
14859 * Code that executes immediately before the onDragOut event
14860 * @method b4DragOut
14863 b4DragOut: function(e) { },
14866 * Abstract method called when we are no longer hovering over an element
14867 * @method onDragOut
14868 * @param {Event} e the mousemove event
14869 * @param {String|DragDrop[]} id In POINT mode, the element
14870 * id this was hovering over. In INTERSECT mode, an array of dd items
14871 * that the mouse is no longer over.
14873 onDragOut: function(e, id) { /* override this */ },
14876 * Code that executes immediately before the onDragDrop event
14877 * @method b4DragDrop
14880 b4DragDrop: function(e) { },
14883 * Abstract method called when this item is dropped on another DragDrop
14885 * @method onDragDrop
14886 * @param {Event} e the mouseup event
14887 * @param {String|DragDrop[]} id In POINT mode, the element
14888 * id this was dropped on. In INTERSECT mode, an array of dd items this
14891 onDragDrop: function(e, id) { /* override this */ },
14894 * Abstract method called when this item is dropped on an area with no
14896 * @method onInvalidDrop
14897 * @param {Event} e the mouseup event
14899 onInvalidDrop: function(e) { /* override this */ },
14902 * Code that executes immediately before the endDrag event
14903 * @method b4EndDrag
14906 b4EndDrag: function(e) { },
14909 * Fired when we are done dragging the object
14911 * @param {Event} e the mouseup event
14913 endDrag: function(e) { /* override this */ },
14916 * Code executed immediately before the onMouseDown event
14917 * @method b4MouseDown
14918 * @param {Event} e the mousedown event
14921 b4MouseDown: function(e) { },
14924 * Event handler that fires when a drag/drop obj gets a mousedown
14925 * @method onMouseDown
14926 * @param {Event} e the mousedown event
14928 onMouseDown: function(e) { /* override this */ },
14931 * Event handler that fires when a drag/drop obj gets a mouseup
14932 * @method onMouseUp
14933 * @param {Event} e the mouseup event
14935 onMouseUp: function(e) { /* override this */ },
14938 * Override the onAvailable method to do what is needed after the initial
14939 * position was determined.
14940 * @method onAvailable
14942 onAvailable: function () {
14946 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
14949 defaultPadding : {left:0, right:0, top:0, bottom:0},
14952 * Initializes the drag drop object's constraints to restrict movement to a certain element.
14956 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
14957 { dragElId: "existingProxyDiv" });
14958 dd.startDrag = function(){
14959 this.constrainTo("parent-id");
14962 * Or you can initalize it using the {@link Roo.Element} object:
14964 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
14965 startDrag : function(){
14966 this.constrainTo("parent-id");
14970 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
14971 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
14972 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
14973 * an object containing the sides to pad. For example: {right:10, bottom:10}
14974 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
14976 constrainTo : function(C, D, E){
14977 if(typeof D == "number"){
14978 D = {left: D, right:D, top:D, bottom:D};
14981 D = D || this.defaultPadding;
14982 var b = Roo.get(this.getEl()).getBox();
14983 var ce = Roo.get(C);
14984 var s = ce.getScroll();
14985 var c, cd = ce.dom;
14986 if(cd == document.body){
14987 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
14990 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
14997 this.resetConstraints();
14998 this.setXConstraint(G - (D.left||0), // left
14999 c.width - G - b.width - (D.right||0) //right
15001 this.setYConstraint(F - (D.top||0), //top
15002 c.height - F - b.height - (D.bottom||0) //bottom
15007 * Returns a reference to the linked element
15009 * @return {HTMLElement} the html element
15011 getEl: function() {
15012 if (!this._domRef) {
15013 this._domRef = Roo.getDom(this.id);
15016 return this._domRef;
15020 * Returns a reference to the actual element to drag. By default this is
15021 * the same as the html element, but it can be assigned to another
15022 * element. An example of this can be found in Roo.dd.DDProxy
15023 * @method getDragEl
15024 * @return {HTMLElement} the html element
15026 getDragEl: function() {
15027 return Roo.getDom(this.dragElId);
15031 * Sets up the DragDrop object. Must be called in the constructor of any
15032 * Roo.dd.DragDrop subclass
15034 * @param id the id of the linked element
15035 * @param {String} sGroup the group of related items
15036 * @param {object} config configuration attributes
15038 init: function(id, H, I) {
15039 this.initTarget(id, H, I);
15040 A.on(this.id, "mousedown", this.handleMouseDown, this);
15041 // Event.on(this.id, "selectstart", Event.preventDefault);
15045 * Initializes Targeting functionality only... the object does not
15046 * get a mousedown handler.
15047 * @method initTarget
15048 * @param id the id of the linked element
15049 * @param {String} sGroup the group of related items
15050 * @param {object} config configuration attributes
15052 initTarget: function(id, J, K) {
15054 // configuration attributes
15055 this.config = K || {};
15057 // create a local reference to the drag and drop manager
15058 this.DDM = Roo.dd.DDM;
15059 // initialize the groups array
15062 // assume that we have an element reference instead of an id if the
15063 // parameter is not a string
15064 if (typeof id !== "string") {
15072 // add to an interaction group
15073 this.addToGroup((J) ? J : "default");
15075 // We don't want to register this as the handle with the manager
15076 // so we just set the id rather than calling the setter.
15077 this.handleElId = id;
15079 // the linked element is the element that gets dragged by default
15080 this.setDragElId(id);
15082 // by default, clicked anchors will not start drag operations.
15083 this.invalidHandleTypes = { A: "A" };
15084 this.invalidHandleIds = {};
15085 this.invalidHandleClasses = [];
15087 this.applyConfig();
15089 this.handleOnAvailable();
15093 * Applies the configuration parameters that were passed into the constructor.
15094 * This is supposed to happen at each level through the inheritance chain. So
15095 * a DDProxy implentation will execute apply config on DDProxy, DD, and
15096 * DragDrop in order to get all of the parameters that are available in
15098 * @method applyConfig
15100 applyConfig: function() {
15102 // configurable properties:
15103 // padding, isTarget, maintainOffset, primaryButtonOnly
15104 this.padding = this.config.padding || [0, 0, 0, 0];
15105 this.isTarget = (this.config.isTarget !== false);
15106 this.maintainOffset = (this.config.maintainOffset);
15107 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
15112 * Executed when the linked element is available
15113 * @method handleOnAvailable
15116 handleOnAvailable: function() {
15117 this.available = true;
15118 this.resetConstraints();
15119 this.onAvailable();
15123 * Configures the padding for the target zone in px. Effectively expands
15124 * (or reduces) the virtual object size for targeting calculations.
15125 * Supports css-style shorthand; if only one parameter is passed, all sides
15126 * will have that padding, and if only two are passed, the top and bottom
15127 * will have the first param, the left and right the second.
15128 * @method setPadding
15129 * @param {int} iTop Top pad
15130 * @param {int} iRight Right pad
15131 * @param {int} iBot Bot pad
15132 * @param {int} iLeft Left pad
15134 setPadding: function(L, M, N, O) {
15135 // this.padding = [iLeft, iRight, iTop, iBot];
15136 if (!M && 0 !== M) {
15137 this.padding = [L, L, L, L];
15138 } else if (!N && 0 !== N) {
15139 this.padding = [L, M, L, M];
15141 this.padding = [L, M, N, O];
15146 * Stores the initial placement of the linked element.
15147 * @method setInitialPosition
15148 * @param {int} diffX the X offset, default 0
15149 * @param {int} diffY the Y offset, default 0
15151 setInitPosition: function(P, Q) {
15152 var el = this.getEl();
15154 if (!this.DDM.verifyEl(el)) {
15161 var p = B.getXY( el );
15163 this.initPageX = p[0] - dx;
15164 this.initPageY = p[1] - dy;
15166 this.lastPageX = p[0];
15167 this.lastPageY = p[1];
15170 this.setStartPosition(p);
15174 * Sets the start position of the element. This is set when the obj
15175 * is initialized, the reset when a drag is started.
15176 * @method setStartPosition
15177 * @param pos current position (from previous lookup)
15180 setStartPosition: function(R) {
15181 var p = R || B.getXY( this.getEl() );
15182 this.deltaSetXY = null;
15184 this.startPageX = p[0];
15185 this.startPageY = p[1];
15189 * Add this instance to a group of related drag/drop objects. All
15190 * instances belong to at least one group, and can belong to as many
15191 * groups as needed.
15192 * @method addToGroup
15193 * @param sGroup {string} the name of the group
15195 addToGroup: function(S) {
15196 this.groups[S] = true;
15197 this.DDM.regDragDrop(this, S);
15201 * Remove's this instance from the supplied interaction group
15202 * @method removeFromGroup
15203 * @param {string} sGroup The group to drop
15205 removeFromGroup: function(T) {
15206 if (this.groups[T]) {
15207 delete this.groups[T];
15211 this.DDM.removeDDFromGroup(this, T);
15215 * Allows you to specify that an element other than the linked element
15216 * will be moved with the cursor during a drag
15217 * @method setDragElId
15218 * @param id {string} the id of the element that will be used to initiate the drag
15220 setDragElId: function(id) {
15221 this.dragElId = id;
15225 * Allows you to specify a child of the linked element that should be
15226 * used to initiate the drag operation. An example of this would be if
15227 * you have a content div with text and links. Clicking anywhere in the
15228 * content area would normally start the drag operation. Use this method
15229 * to specify that an element inside of the content div is the element
15230 * that starts the drag operation.
15231 * @method setHandleElId
15232 * @param id {string} the id of the element that will be used to
15233 * initiate the drag.
15235 setHandleElId: function(id) {
15236 if (typeof id !== "string") {
15240 this.handleElId = id;
15241 this.DDM.regHandle(this.id, id);
15245 * Allows you to set an element outside of the linked element as a drag
15247 * @method setOuterHandleElId
15248 * @param id the id of the element that will be used to initiate the drag
15250 setOuterHandleElId: function(id) {
15251 if (typeof id !== "string") {
15255 A.on(id, "mousedown",
15256 this.handleMouseDown, this);
15257 this.setHandleElId(id);
15259 this.hasOuterHandles = true;
15263 * Remove all drag and drop hooks for this element
15266 unreg: function() {
15267 A.un(this.id, "mousedown",
15268 this.handleMouseDown);
15269 this._domRef = null;
15270 this.DDM._remove(this);
15273 destroy : function(){
15278 * Returns true if this instance is locked, or the drag drop mgr is locked
15279 * (meaning that all drag/drop is disabled on the page.)
15281 * @return {boolean} true if this obj or all drag/drop is locked, else
15284 isLocked: function() {
15285 return (this.DDM.isLocked() || this.locked);
15289 * Fired when this object is clicked
15290 * @method handleMouseDown
15292 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
15295 handleMouseDown: function(e, U){
15296 if (this.primaryButtonOnly && e.button != 0) {
15300 if (this.isLocked()) {
15305 this.DDM.refreshCache(this.groups);
15307 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
15308 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
15310 if (this.clickValidator(e)) {
15312 // set the initial element position
15313 this.setStartPosition();
15316 this.b4MouseDown(e);
15317 this.onMouseDown(e);
15319 this.DDM.handleMouseDown(e, this);
15321 this.DDM.stopEvent(e);
15329 clickValidator: function(e) {
15330 var V = e.getTarget();
15331 return ( this.isValidHandleChild(V) &&
15332 (this.id == this.handleElId ||
15333 this.DDM.handleWasClicked(V, this.id)) );
15337 * Allows you to specify a tag name that should not start a drag operation
15338 * when clicked. This is designed to facilitate embedding links within a
15339 * drag handle that do something other than start the drag.
15340 * @method addInvalidHandleType
15341 * @param {string} tagName the type of element to exclude
15343 addInvalidHandleType: function(W) {
15344 var X = W.toUpperCase();
15345 this.invalidHandleTypes[X] = X;
15349 * Lets you to specify an element id for a child of a drag handle
15350 * that should not initiate a drag
15351 * @method addInvalidHandleId
15352 * @param {string} id the element id of the element you wish to ignore
15354 addInvalidHandleId: function(id) {
15355 if (typeof id !== "string") {
15359 this.invalidHandleIds[id] = id;
15363 * Lets you specify a css class of elements that will not initiate a drag
15364 * @method addInvalidHandleClass
15365 * @param {string} cssClass the class of the elements you wish to ignore
15367 addInvalidHandleClass: function(Y) {
15368 this.invalidHandleClasses.push(Y);
15372 * Unsets an excluded tag name set by addInvalidHandleType
15373 * @method removeInvalidHandleType
15374 * @param {string} tagName the type of element to unexclude
15376 removeInvalidHandleType: function(Z) {
15377 var a = Z.toUpperCase();
15378 // this.invalidHandleTypes[type] = null;
15379 delete this.invalidHandleTypes[a];
15383 * Unsets an invalid handle id
15384 * @method removeInvalidHandleId
15385 * @param {string} id the id of the element to re-enable
15387 removeInvalidHandleId: function(id) {
15388 if (typeof id !== "string") {
15391 delete this.invalidHandleIds[id];
15395 * Unsets an invalid css class
15396 * @method removeInvalidHandleClass
15397 * @param {string} cssClass the class of the element(s) you wish to
15400 removeInvalidHandleClass: function(d) {
15401 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
15402 if (this.invalidHandleClasses[i] == d) {
15403 delete this.invalidHandleClasses[i];
15409 * Checks the tag exclusion list to see if this click should be ignored
15410 * @method isValidHandleChild
15411 * @param {HTMLElement} node the HTMLElement to evaluate
15412 * @return {boolean} true if this is a valid tag type, false if not
15414 isValidHandleChild: function(f) {
15417 // var n = (node.nodeName == "#text") ? node.parentNode : node;
15420 h = f.nodeName.toUpperCase();
15422 nodeName = node.nodeName;
15425 g = g && !this.invalidHandleTypes[h];
15426 g = g && !this.invalidHandleIds[f.id];
15428 for (var i=0, len=this.invalidHandleClasses.length; g && i<len; ++i) {
15429 g = !B.hasClass(f, this.invalidHandleClasses[i]);
15438 * Create the array of horizontal tick marks if an interval was specified
15439 * in setXConstraint().
15440 * @method setXTicks
15443 setXTicks: function(j, k) {
15445 this.xTickSize = k;
15449 for (var i = this.initPageX; i >= this.minX; i = i - k) {
15451 this.xTicks[this.xTicks.length] = i;
15456 for (i = this.initPageX; i <= this.maxX; i = i + k) {
15458 this.xTicks[this.xTicks.length] = i;
15464 this.xTicks.sort(this.DDM.numericSort) ;
15468 * Create the array of vertical tick marks if an interval was specified in
15469 * setYConstraint().
15470 * @method setYTicks
15473 setYTicks: function(m, n) {
15475 this.yTickSize = n;
15479 for (var i = this.initPageY; i >= this.minY; i = i - n) {
15481 this.yTicks[this.yTicks.length] = i;
15486 for (i = this.initPageY; i <= this.maxY; i = i + n) {
15488 this.yTicks[this.yTicks.length] = i;
15494 this.yTicks.sort(this.DDM.numericSort) ;
15498 * By default, the element can be dragged any place on the screen. Use
15499 * this method to limit the horizontal travel of the element. Pass in
15500 * 0,0 for the parameters if you want to lock the drag to the y axis.
15501 * @method setXConstraint
15502 * @param {int} iLeft the number of pixels the element can move to the left
15503 * @param {int} iRight the number of pixels the element can move to the
15505 * @param {int} iTickSize optional parameter for specifying that the
15507 * should move iTickSize pixels at a time.
15509 setXConstraint: function(q, r, t) {
15510 this.leftConstraint = q;
15511 this.rightConstraint = r;
15513 this.minX = this.initPageX - q;
15514 this.maxX = this.initPageX + r;
15515 if (t) { this.setXTicks(this.initPageX, t); }
15518 this.constrainX = true;
15522 * Clears any constraints applied to this instance. Also clears ticks
15523 * since they can't exist independent of a constraint at this time.
15524 * @method clearConstraints
15526 clearConstraints: function() {
15527 this.constrainX = false;
15528 this.constrainY = false;
15533 * Clears any tick interval defined for this instance
15534 * @method clearTicks
15536 clearTicks: function() {
15537 this.xTicks = null;
15538 this.yTicks = null;
15539 this.xTickSize = 0;
15540 this.yTickSize = 0;
15544 * By default, the element can be dragged any place on the screen. Set
15545 * this to limit the vertical travel of the element. Pass in 0,0 for the
15546 * parameters if you want to lock the drag to the x axis.
15547 * @method setYConstraint
15548 * @param {int} iUp the number of pixels the element can move up
15549 * @param {int} iDown the number of pixels the element can move down
15550 * @param {int} iTickSize optional parameter for specifying that the
15551 * element should move iTickSize pixels at a time.
15553 setYConstraint: function(u, v, w) {
15554 this.topConstraint = u;
15555 this.bottomConstraint = v;
15557 this.minY = this.initPageY - u;
15558 this.maxY = this.initPageY + v;
15559 if (w) { this.setYTicks(this.initPageY, w); }
15562 this.constrainY = true;
15567 * resetConstraints must be called if you manually reposition a dd element.
15568 * @method resetConstraints
15569 * @param {boolean} maintainOffset
15571 resetConstraints: function() {
15574 // Maintain offsets if necessary
15575 if (this.initPageX || this.initPageX === 0) {
15576 // figure out how much this thing has moved
15577 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
15578 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
15580 this.setInitPosition(dx, dy);
15582 // This is the first time we have detected the element's position
15584 this.setInitPosition();
15587 if (this.constrainX) {
15588 this.setXConstraint( this.leftConstraint,
15589 this.rightConstraint,
15593 if (this.constrainY) {
15594 this.setYConstraint( this.topConstraint,
15595 this.bottomConstraint,
15601 * Normally the drag element is moved pixel by pixel, but we can specify
15602 * that it move a number of pixels at a time. This method resolves the
15603 * location when we have it set up like this.
15605 * @param {int} val where we want to place the object
15606 * @param {int[]} tickArray sorted array of valid points
15607 * @return {int} the closest tick
15610 getTick: function(z, AA) {
15613 // If tick interval is not defined, it is effectively 1 pixel,
15614 // so we return the value passed to us.
15616 } else if (AA[0] >= z) {
15617 // The value is lower than the first tick, so we return the first
15621 for (var i=0, len=AA.length; i<len; ++i) {
15623 if (AA[next] && AA[next] >= z) {
15624 var diff1 = z - AA[i];
15625 var diff2 = AA[next] - z;
15626 return (diff2 > diff1) ? AA[i] : AA[next];
15630 // The value is larger than the last tick, so we return the last
15632 return AA[AA.length - 1];
15639 * @return {string} string representation of the dd obj
15641 toString: function() {
15642 return ("DragDrop " + this.id);
15651 * Ext JS Library 1.1.1
15652 * Copyright(c) 2006-2007, Ext JS, LLC.
15654 * Originally Released Under LGPL - original licence link has changed is not relivant.
15657 * <script type="text/javascript">
15662 * The drag and drop utility provides a framework for building drag and drop
15663 * applications. In addition to enabling drag and drop for specific elements,
15664 * the drag and drop elements are tracked by the manager class, and the
15665 * interactions between the various elements are tracked during the drag and
15666 * the implementing code is notified about these important moments.
15669 // Only load the library once. Rewriting the manager class would orphan
15670 // existing drag and drop instances.
15671 if (!Roo.dd.DragDropMgr) {
15674 * @class Roo.dd.DragDropMgr
15675 * DragDropMgr is a singleton that tracks the element interaction for
15676 * all DragDrop items in the window. Generally, you will not call
15677 * this class directly, but it does have helper methods that could
15678 * be useful in your DragDrop implementations.
15681 Roo.dd.DragDropMgr = function() {
15683 var A = Roo.EventManager;
15688 * Two dimensional Array of registered DragDrop objects. The first
15689 * dimension is the DragDrop item group, the second the DragDrop
15692 * @type {string: string}
15699 * Array of element ids defined as drag handles. Used to determine
15700 * if the element that generated the mousedown event is actually the
15701 * handle and not the html element itself.
15702 * @property handleIds
15703 * @type {string: string}
15710 * the DragDrop object that is currently being dragged
15711 * @property dragCurrent
15719 * the DragDrop object(s) that are being hovered over
15720 * @property dragOvers
15728 * the X distance between the cursor and the object being dragged
15737 * the Y distance between the cursor and the object being dragged
15746 * Flag to determine if we should prevent the default behavior of the
15747 * events we define. By default this is true, but this can be set to
15748 * false if you need the default behavior (not recommended)
15749 * @property preventDefault
15753 preventDefault: true,
15756 * Flag to determine if we should stop the propagation of the events
15757 * we generate. This is true by default but you may want to set it to
15758 * false if the html element contains other features that require the
15760 * @property stopPropagation
15764 stopPropagation: true,
15767 * Internal flag that is set to true when drag and drop has been
15769 * @property initialized
15776 * All drag and drop can be disabled.
15784 * Called the first time an element is registered.
15790 this.initialized = true;
15794 * In point mode, drag and drop interaction is defined by the
15795 * location of the cursor during the drag/drop
15803 * In intersect mode, drag and drop interactio nis defined by the
15804 * overlap of two or more drag and drop objects.
15805 * @property INTERSECT
15812 * The current drag and drop mode. Default: POINT
15820 * Runs method on all drag and drop objects
15821 * @method _execOnAll
15825 _execOnAll: function(AG, AH) {
15826 for (var i in this.ids) {
15827 for (var j in this.ids[i]) {
15828 var h = this.ids[i][j];
15829 if (! this.isTypeOfDD(h)) {
15833 h[AG].apply(h, AH);
15839 * Drag and drop initialization. Sets up the global event handlers
15844 _onLoad: function() {
15849 A.on(document, "mouseup", this.handleMouseUp, this, true);
15850 A.on(document, "mousemove", this.handleMouseMove, this, true);
15851 A.on(window, "unload", this._onUnload, this, true);
15852 A.on(window, "resize", this._onResize, this, true);
15853 // Event.on(window, "mouseout", this._test);
15858 * Reset constraints on all drag and drop objs
15859 * @method _onResize
15863 _onResize: function(e) {
15864 this._execOnAll("resetConstraints", []);
15868 * Lock all drag and drop functionality
15872 lock: function() { this.locked = true; },
15875 * Unlock all drag and drop functionality
15879 unlock: function() { this.locked = false; },
15882 * Is drag and drop locked?
15884 * @return {boolean} True if drag and drop is locked, false otherwise.
15887 isLocked: function() { return this.locked; },
15890 * Location cache that is set for all drag drop objects when a drag is
15891 * initiated, cleared when the drag is finished.
15892 * @property locationCache
15899 * Set useCache to false if you want to force object the lookup of each
15900 * drag and drop linked element constantly during a drag.
15901 * @property useCache
15908 * The number of pixels that the mouse needs to move after the
15909 * mousedown before the drag is initiated. Default=3;
15910 * @property clickPixelThresh
15914 clickPixelThresh: 3,
15917 * The number of milliseconds after the mousedown event to initiate the
15918 * drag if we don't get a mouseup event. Default=1000
15919 * @property clickTimeThresh
15923 clickTimeThresh: 350,
15926 * Flag that indicates that either the drag pixel threshold or the
15927 * mousdown time threshold has been met
15928 * @property dragThreshMet
15933 dragThreshMet: false,
15936 * Timeout used for the click time threshold
15937 * @property clickTimeout
15942 clickTimeout: null,
15945 * The X position of the mousedown event stored for later use when a
15946 * drag threshold is met.
15955 * The Y position of the mousedown event stored for later use when a
15956 * drag threshold is met.
15965 * Each DragDrop instance must be registered with the DragDropMgr.
15966 * This is executed in DragDrop.init()
15967 * @method regDragDrop
15968 * @param {DragDrop} oDD the DragDrop object to register
15969 * @param {String} sGroup the name of the group this element belongs to
15972 regDragDrop: function(AI, AJ) {
15973 if (!this.initialized) { this.init(); }
15975 if (!this.ids[AJ]) {
15979 this.ids[AJ][AI.id] = AI;
15983 * Removes the supplied dd instance from the supplied group. Executed
15984 * by DragDrop.removeFromGroup, so don't call this function directly.
15985 * @method removeDDFromGroup
15989 removeDDFromGroup: function(AK, AL) {
15990 if (!this.ids[AL]) {
15994 var AM = this.ids[AL];
15995 if (AM && AM[AK.id]) {
16001 * Unregisters a drag and drop item. This is executed in
16002 * DragDrop.unreg, use that method instead of calling this directly.
16007 _remove: function(AN) {
16008 for (var g in AN.groups) {
16009 if (g && this.ids[g][AN.id]) {
16010 delete this.ids[g][AN.id];
16013 delete this.handleIds[AN.id];
16017 * Each DragDrop handle element must be registered. This is done
16018 * automatically when executing DragDrop.setHandleElId()
16019 * @method regHandle
16020 * @param {String} sDDId the DragDrop id this element is a handle for
16021 * @param {String} sHandleId the id of the element that is the drag
16025 regHandle: function(AO, AP) {
16026 if (!this.handleIds[AO]) {
16027 this.handleIds[AO] = {};
16030 this.handleIds[AO][AP] = AP;
16034 * Utility function to determine if a given element has been
16035 * registered as a drag drop item.
16036 * @method isDragDrop
16037 * @param {String} id the element id to check
16038 * @return {boolean} true if this element is a DragDrop item,
16042 isDragDrop: function(id) {
16043 return ( this.getDDById(id) ) ? true : false;
16047 * Returns the drag and drop instances that are in all groups the
16048 * passed in instance belongs to.
16049 * @method getRelated
16050 * @param {DragDrop} p_oDD the obj to get related data for
16051 * @param {boolean} bTargetsOnly if true, only return targetable objs
16052 * @return {DragDrop[]} the related instances
16055 getRelated: function(AQ, AR) {
16057 for (var i in AQ.groups) {
16058 for (j in this.ids[i]) {
16059 var dd = this.ids[i][j];
16060 if (! this.isTypeOfDD(dd)) {
16063 if (!AR || dd.isTarget) {
16064 AS[AS.length] = dd;
16073 * Returns true if the specified dd target is a legal target for
16074 * the specifice drag obj
16075 * @method isLegalTarget
16076 * @param {DragDrop} the drag obj
16077 * @param {DragDrop} the target
16078 * @return {boolean} true if the target is a legal target for the
16082 isLegalTarget: function (AT, AU) {
16083 var AV = this.getRelated(AT, true);
16084 for (var i=0, d=AV.length;i<d;++i) {
16085 if (AV[i].id == AU.id) {
16094 * My goal is to be able to transparently determine if an object is
16095 * typeof DragDrop, and the exact subclass of DragDrop. typeof
16096 * returns "object", oDD.constructor.toString() always returns
16097 * "DragDrop" and not the name of the subclass. So for now it just
16098 * evaluates a well-known variable in DragDrop.
16099 * @method isTypeOfDD
16100 * @param {Object} the object to evaluate
16101 * @return {boolean} true if typeof oDD = DragDrop
16104 isTypeOfDD: function (AW) {
16105 return (AW && AW.__ygDragDrop);
16109 * Utility function to determine if a given element has been
16110 * registered as a drag drop handle for the given Drag Drop object.
16112 * @param {String} id the element id to check
16113 * @return {boolean} true if this element is a DragDrop handle, false
16117 isHandle: function(AX, AY) {
16118 return ( this.handleIds[AX] &&
16119 this.handleIds[AX][AY] );
16123 * Returns the DragDrop instance for a given id
16124 * @method getDDById
16125 * @param {String} id the id of the DragDrop object
16126 * @return {DragDrop} the drag drop object, null if it is not found
16129 getDDById: function(id) {
16130 for (var i in this.ids) {
16131 if (this.ids[i][id]) {
16132 return this.ids[i][id];
16139 * Fired after a registered DragDrop object gets the mousedown event.
16140 * Sets up the events required to track the object being dragged
16141 * @method handleMouseDown
16142 * @param {Event} e the event
16143 * @param oDD the DragDrop object being dragged
16147 handleMouseDown: function(e, AZ) {
16149 Roo.QuickTips.disable();
16152 this.currentTarget = e.getTarget();
16154 this.dragCurrent = AZ;
16156 var el = AZ.getEl();
16158 // track start position
16159 this.startX = e.getPageX();
16160 this.startY = e.getPageY();
16162 this.deltaX = this.startX - el.offsetLeft;
16163 this.deltaY = this.startY - el.offsetTop;
16165 this.dragThreshMet = false;
16167 this.clickTimeout = setTimeout(
16169 var Aa = Roo.dd.DDM;
16170 Aa.startDrag(Aa.startX, Aa.startY);
16172 this.clickTimeThresh );
16176 * Fired when either the drag pixel threshol or the mousedown hold
16177 * time threshold has been met.
16178 * @method startDrag
16179 * @param x {int} the X position of the original mousedown
16180 * @param y {int} the Y position of the original mousedown
16183 startDrag: function(x, y) {
16184 clearTimeout(this.clickTimeout);
16185 if (this.dragCurrent) {
16186 this.dragCurrent.b4StartDrag(x, y);
16187 this.dragCurrent.startDrag(x, y);
16190 this.dragThreshMet = true;
16194 * Internal function to handle the mouseup event. Will be invoked
16195 * from the context of the document.
16196 * @method handleMouseUp
16197 * @param {Event} e the event
16201 handleMouseUp: function(e) {
16204 Roo.QuickTips.enable();
16206 if (! this.dragCurrent) {
16211 clearTimeout(this.clickTimeout);
16213 if (this.dragThreshMet) {
16214 this.fireEvents(e, true);
16225 * Utility to stop event propagation and event default, if these
16226 * features are turned on.
16227 * @method stopEvent
16228 * @param {Event} e the event as returned by this.getEvent()
16231 stopEvent: function(e){
16232 if(this.stopPropagation) {
16233 e.stopPropagation();
16236 if (this.preventDefault) {
16237 e.preventDefault();
16242 * Internal function to clean up event handlers after the drag
16243 * operation is complete
16245 * @param {Event} e the event
16249 stopDrag: function(e) {
16250 // Fire the drag end event for the item that was dragged
16251 if (this.dragCurrent) {
16252 if (this.dragThreshMet) {
16253 this.dragCurrent.b4EndDrag(e);
16254 this.dragCurrent.endDrag(e);
16258 this.dragCurrent.onMouseUp(e);
16262 this.dragCurrent = null;
16263 this.dragOvers = {};
16267 * Internal function to handle the mousemove event. Will be invoked
16268 * from the context of the html element.
16270 * @TODO figure out what we can do about mouse events lost when the
16271 * user drags objects beyond the window boundary. Currently we can
16272 * detect this in internet explorer by verifying that the mouse is
16273 * down during the mousemove event. Firefox doesn't give us the
16274 * button state on the mousemove event.
16275 * @method handleMouseMove
16276 * @param {Event} e the event
16280 handleMouseMove: function(e) {
16281 if (! this.dragCurrent) {
16285 // var button = e.which || e.button;
16287 // check for IE mouseup outside of page boundary
16288 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
16290 return this.handleMouseUp(e);
16293 if (!this.dragThreshMet) {
16294 var diffX = Math.abs(this.startX - e.getPageX());
16295 var diffY = Math.abs(this.startY - e.getPageY());
16296 if (diffX > this.clickPixelThresh ||
16297 diffY > this.clickPixelThresh) {
16298 this.startDrag(this.startX, this.startY);
16302 if (this.dragThreshMet) {
16303 this.dragCurrent.b4Drag(e);
16304 this.dragCurrent.onDrag(e);
16305 if(!this.dragCurrent.moveOnly){
16306 this.fireEvents(e, false);
16317 * Iterates over all of the DragDrop elements to find ones we are
16318 * hovering over or dropping on
16319 * @method fireEvents
16320 * @param {Event} e the event
16321 * @param {boolean} isDrop is this a drop op or a mouseover op?
16325 fireEvents: function(e, Aa) {
16326 var dc = this.dragCurrent;
16328 // If the user did the mouse up outside of the window, we could
16329 // get here even though we have ended the drag.
16330 if (!dc || dc.isLocked()) {
16334 var pt = e.getPoint();
16336 // cache the previous dragOver array
16344 // Check to see if the object(s) we were hovering over is no longer
16345 // being hovered over so we can fire the onDragOut event
16346 for (var i in this.dragOvers) {
16348 var ddo = this.dragOvers[i];
16350 if (! this.isTypeOfDD(ddo)) {
16354 if (! this.isOverTarget(pt, ddo, this.mode)) {
16360 delete this.dragOvers[i];
16363 for (var AL in dc.groups) {
16365 if ("string" != typeof AL) {
16369 for (i in this.ids[AL]) {
16370 var AZ = this.ids[AL][i];
16371 if (! this.isTypeOfDD(AZ)) {
16375 if (AZ.isTarget && !AZ.isLocked() && AZ != dc) {
16376 if (this.isOverTarget(pt, AZ, this.mode)) {
16377 // look for drop interactions
16380 // look for drag enter and drag over interactions
16383 // initial drag over: dragEnter fires
16386 // subsequent drag overs: dragOver fires
16392 this.dragOvers[AZ.id] = AZ;
16401 dc.b4DragOut(e, Ac);
16402 dc.onDragOut(e, Ac);
16406 dc.onDragEnter(e, Af);
16410 dc.b4DragOver(e, Ad);
16411 dc.onDragOver(e, Ad);
16415 dc.b4DragDrop(e, Ae);
16416 dc.onDragDrop(e, Ae);
16420 // fire dragout events
16422 for (i=0, d=Ac.length; i<d; ++i) {
16423 dc.b4DragOut(e, Ac[i].id);
16424 dc.onDragOut(e, Ac[i].id);
16427 // fire enter events
16428 for (i=0,d=Af.length; i<d; ++i) {
16429 // dc.b4DragEnter(e, oDD.id);
16430 dc.onDragEnter(e, Af[i].id);
16433 // fire over events
16434 for (i=0,d=Ad.length; i<d; ++i) {
16435 dc.b4DragOver(e, Ad[i].id);
16436 dc.onDragOver(e, Ad[i].id);
16439 // fire drop events
16440 for (i=0, d=Ae.length; i<d; ++i) {
16441 dc.b4DragDrop(e, Ae[i].id);
16442 dc.onDragDrop(e, Ae[i].id);
16447 // notify about a drop that did not find a target
16448 if (Aa && !Ae.length) {
16449 dc.onInvalidDrop(e);
16455 * Helper function for getting the best match from the list of drag
16456 * and drop objects returned by the drag and drop events when we are
16457 * in INTERSECT mode. It returns either the first object that the
16458 * cursor is over, or the object that has the greatest overlap with
16459 * the dragged element.
16460 * @method getBestMatch
16461 * @param {DragDrop[]} dds The array of drag and drop objects
16463 * @return {DragDrop} The best single match
16466 getBestMatch: function(Ag) {
16468 // Return null if the input is not what we expect
16469 //if (!dds || !dds.length || dds.length == 0) {
16471 // If there is only one item, it wins
16472 //} else if (dds.length == 1) {
16474 var Ai = Ag.length;
16479 // Loop through the targeted items
16480 for (var i=0; i<Ai; ++i) {
16482 // If the cursor is over the object, it wins. If the
16483 // cursor is over multiple matches, the first one we come
16485 if (dd.cursorIsOver) {
16488 // Otherwise the object with the most overlap wins
16491 Ah.overlap.getArea() < dd.overlap.getArea()) {
16502 * Refreshes the cache of the top-left and bottom-right points of the
16503 * drag and drop objects in the specified group(s). This is in the
16504 * format that is stored in the drag and drop instance, so typical
16507 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
16511 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
16513 * @TODO this really should be an indexed array. Alternatively this
16514 * method could accept both.
16515 * @method refreshCache
16516 * @param {Object} groups an associative array of groups to refresh
16519 refreshCache: function(Aj) {
16520 for (var AL in Aj) {
16521 if ("string" != typeof AL) {
16524 for (var i in this.ids[AL]) {
16525 var AZ = this.ids[AL][i];
16527 if (this.isTypeOfDD(AZ)) {
16528 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
16529 var o = this.getLocation(AZ);
16531 this.locationCache[AZ.id] = o;
16533 delete this.locationCache[AZ.id];
16534 // this will unregister the drag and drop object if
16535 // the element is not in a usable state
16544 * This checks to make sure an element exists and is in the DOM. The
16545 * main purpose is to handle cases where innerHTML is used to remove
16546 * drag and drop objects from the DOM. IE provides an 'unspecified
16547 * error' when trying to access the offsetParent of such an element
16549 * @param {HTMLElement} el the element to check
16550 * @return {boolean} true if the element looks usable
16553 verifyEl: function(el) {
16558 parent = el.offsetParent;
16561 parent = el.offsetParent;
16572 * Returns a Region object containing the drag and drop element's position
16573 * and size, including the padding configured for it
16574 * @method getLocation
16575 * @param {DragDrop} oDD the drag and drop object to get the
16577 * @return {Roo.lib.Region} a Region object representing the total area
16578 * the element occupies, including any padding
16579 * the instance is configured for.
16582 getLocation: function(Ak) {
16583 if (! this.isTypeOfDD(Ak)) {
16587 var el = Ak.getEl(), Al, x1, x2, y1, y2, t, r, b, l;
16590 Al= Roo.lib.Dom.getXY(el);
16599 x2 = x1 + el.offsetWidth;
16601 y2 = y1 + el.offsetHeight;
16603 t = y1 - Ak.padding[0];
16604 r = x2 + Ak.padding[1];
16605 b = y2 + Ak.padding[2];
16606 l = x1 - Ak.padding[3];
16608 return new Roo.lib.Region( t, r, b, l );
16612 * Checks the cursor location to see if it over the target
16613 * @method isOverTarget
16614 * @param {Roo.lib.Point} pt The point to evaluate
16615 * @param {DragDrop} oTarget the DragDrop object we are inspecting
16616 * @return {boolean} true if the mouse is over the target
16620 isOverTarget: function(pt, Am, An) {
16621 // use cache if available
16622 var Ao = this.locationCache[Am.id];
16623 if (!Ao || !this.useCache) {
16624 Ao = this.getLocation(Am);
16625 this.locationCache[Am.id] = Ao;
16634 Am.cursorIsOver = Ao.contains( pt );
16636 // DragDrop is using this as a sanity check for the initial mousedown
16637 // in this case we are done. In POINT mode, if the drag obj has no
16638 // contraints, we are also done. Otherwise we need to evaluate the
16639 // location of the target as related to the actual location of the
16640 // dragged element.
16641 var dc = this.dragCurrent;
16642 if (!dc || !dc.getTargetCoord ||
16643 (!An && !dc.constrainX && !dc.constrainY)) {
16644 return Am.cursorIsOver;
16650 // Get the current location of the drag element, this is the
16651 // location of the mouse event less the delta that represents
16652 // where the original mousedown happened on the element. We
16653 // need to consider constraints and ticks as well.
16654 var Ap = dc.getTargetCoord(pt.x, pt.y);
16656 var el = dc.getDragEl();
16657 var Aq = new Roo.lib.Region( Ap.y,
16658 Ap.x + el.offsetWidth,
16659 Ap.y + el.offsetHeight,
16662 var Ar = Aq.intersect(Ao);
16666 return (An) ? true : Am.cursorIsOver;
16673 * unload event handler
16674 * @method _onUnload
16678 _onUnload: function(e, me) {
16679 Roo.dd.DragDropMgr.unregAll();
16683 * Cleans up the drag and drop events and objects.
16688 unregAll: function() {
16690 if (this.dragCurrent) {
16692 this.dragCurrent = null;
16696 this._execOnAll("unreg", []);
16698 for (i in this.elementCache) {
16699 delete this.elementCache[i];
16703 this.elementCache = {};
16708 * A cache of DOM elements
16709 * @property elementCache
16716 * Get the wrapper for the DOM element specified
16717 * @method getElWrapper
16718 * @param {String} id the id of the element to get
16719 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
16721 * @deprecated This wrapper isn't that useful
16724 getElWrapper: function(id) {
16725 var As = this.elementCache[id];
16726 if (!As || !As.el) {
16727 As = this.elementCache[id] =
16728 new this.ElementWrapper(Roo.getDom(id));
16734 * Returns the actual DOM element
16735 * @method getElement
16736 * @param {String} id the id of the elment to get
16737 * @return {Object} The element
16738 * @deprecated use Roo.getDom instead
16741 getElement: function(id) {
16742 return Roo.getDom(id);
16746 * Returns the style property for the DOM element (i.e.,
16747 * document.getElById(id).style)
16749 * @param {String} id the id of the elment to get
16750 * @return {Object} The style property of the element
16751 * @deprecated use Roo.getDom instead
16754 getCss: function(id) {
16755 var el = Roo.getDom(id);
16756 return (el) ? el.style : null;
16760 * Inner class for cached elements
16761 * @class DragDropMgr.ElementWrapper
16766 ElementWrapper: function(el) {
16771 this.el = el || null;
16776 this.id = this.el && el.id;
16778 * A reference to the style property
16781 this.css = this.el && el.style;
16785 * Returns the X position of an html element
16787 * @param el the element for which to get the position
16788 * @return {int} the X coordinate
16790 * @deprecated use Roo.lib.Dom.getX instead
16793 getPosX: function(el) {
16794 return Roo.lib.Dom.getX(el);
16798 * Returns the Y position of an html element
16800 * @param el the element for which to get the position
16801 * @return {int} the Y coordinate
16802 * @deprecated use Roo.lib.Dom.getY instead
16805 getPosY: function(el) {
16806 return Roo.lib.Dom.getY(el);
16810 * Swap two nodes. In IE, we use the native method, for others we
16811 * emulate the IE behavior
16813 * @param n1 the first node to swap
16814 * @param n2 the other node to swap
16817 swapNode: function(n1, n2) {
16821 var p = n2.parentNode;
16822 var s = n2.nextSibling;
16825 p.insertBefore(n1, n2);
16826 } else if (n2 == n1.nextSibling) {
16827 p.insertBefore(n2, n1);
16829 n1.parentNode.replaceChild(n2, n1);
16830 p.insertBefore(n1, s);
16836 * Returns the current scroll position
16837 * @method getScroll
16841 getScroll: function () {
16842 var t, l, At=document.documentElement, db=document.body;
16843 if (At && (At.scrollTop || At.scrollLeft)) {
16852 return { top: t, left: l };
16856 * Returns the specified element style property
16858 * @param {HTMLElement} el the element
16859 * @param {string} styleProp the style property
16860 * @return {string} The value of the style property
16861 * @deprecated use Roo.lib.Dom.getStyle
16864 getStyle: function(el, Au) {
16865 return Roo.fly(el).getStyle(Au);
16869 * Gets the scrollTop
16870 * @method getScrollTop
16871 * @return {int} the document's scrollTop
16874 getScrollTop: function () { return this.getScroll().top; },
16877 * Gets the scrollLeft
16878 * @method getScrollLeft
16879 * @return {int} the document's scrollTop
16882 getScrollLeft: function () { return this.getScroll().left; },
16885 * Sets the x/y position of an element to the location of the
16888 * @param {HTMLElement} moveEl The element to move
16889 * @param {HTMLElement} targetEl The position reference element
16892 moveToEl: function (Av, Aw) {
16893 var Ax = Roo.lib.Dom.getXY(Aw);
16894 Roo.lib.Dom.setXY(Av, Ax);
16898 * Numeric array sort function
16899 * @method numericSort
16902 numericSort: function(a, b) { return (a - b); },
16906 * @property _timeoutCount
16913 * Trying to make the load order less important. Without this we get
16914 * an error if this file is loaded before the Event Utility.
16915 * @method _addListeners
16919 _addListeners: function() {
16920 var Ay = Roo.dd.DDM;
16921 if ( Roo.lib.Event && document ) {
16924 if (Ay._timeoutCount > 2000) {
16926 setTimeout(Ay._addListeners, 10);
16927 if (document && document.body) {
16928 Ay._timeoutCount += 1;
16935 * Recursively searches the immediate parent and all child nodes for
16936 * the handle element in order to determine wheter or not it was
16938 * @method handleWasClicked
16939 * @param node the html element to inspect
16942 handleWasClicked: function(Az, id) {
16943 if (this.isHandle(id, Az.id)) {
16946 // check to see if this is a text node child of the one we want
16947 var p = Az.parentNode;
16950 if (this.isHandle(id, p.id)) {
16965 // shorter alias, save a few bytes
16966 Roo.dd.DDM = Roo.dd.DragDropMgr;
16967 Roo.dd.DDM._addListeners();
16972 * Ext JS Library 1.1.1
16973 * Copyright(c) 2006-2007, Ext JS, LLC.
16975 * Originally Released Under LGPL - original licence link has changed is not relivant.
16978 * <script type="text/javascript">
16983 * A DragDrop implementation where the linked element follows the
16984 * mouse cursor during a drag.
16985 * @extends Roo.dd.DragDrop
16987 * @param {String} id the id of the linked element
16988 * @param {String} sGroup the group of related DragDrop items
16989 * @param {object} config an object containing configurable attributes
16990 * Valid properties for DD:
16993 Roo.dd.DD = function(id, A, B) {
16995 this.init(id, A, B);
16999 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
17002 * When set to true, the utility automatically tries to scroll the browser
17003 * window wehn a drag and drop element is dragged near the viewport boundary.
17004 * Defaults to true.
17011 * Sets the pointer offset to the distance between the linked element's top
17012 * left corner and the location the element was clicked
17013 * @method autoOffset
17014 * @param {int} iPageX the X coordinate of the click
17015 * @param {int} iPageY the Y coordinate of the click
17017 autoOffset: function(C, D) {
17018 var x = C - this.startPageX;
17019 var y = D - this.startPageY;
17020 this.setDelta(x, y);
17024 * Sets the pointer offset. You can call this directly to force the
17025 * offset to be in a particular location (e.g., pass in 0,0 to set it
17026 * to the center of the object)
17028 * @param {int} iDeltaX the distance from the left
17029 * @param {int} iDeltaY the distance from the top
17031 setDelta: function(E, F) {
17037 * Sets the drag element to the location of the mousedown or click event,
17038 * maintaining the cursor location relative to the location on the element
17039 * that was clicked. Override this if you want to place the element in a
17040 * location other than where the cursor is.
17041 * @method setDragElPos
17042 * @param {int} iPageX the X coordinate of the mousedown or drag event
17043 * @param {int} iPageY the Y coordinate of the mousedown or drag event
17045 setDragElPos: function(G, H) {
17046 // the first time we do this, we are going to check to make sure
17047 // the element has css positioning
17049 var el = this.getDragEl();
17050 this.alignElWithMouse(el, G, H);
17054 * Sets the element to the location of the mousedown or click event,
17055 * maintaining the cursor location relative to the location on the element
17056 * that was clicked. Override this if you want to place the element in a
17057 * location other than where the cursor is.
17058 * @method alignElWithMouse
17059 * @param {HTMLElement} el the element to move
17060 * @param {int} iPageX the X coordinate of the mousedown or drag event
17061 * @param {int} iPageY the Y coordinate of the mousedown or drag event
17063 alignElWithMouse: function(el, I, J) {
17064 var K = this.getTargetCoord(I, J);
17065 var L = el.dom ? el : Roo.fly(el);
17066 if (!this.deltaSetXY) {
17067 var aCoord = [K.x, K.y];
17069 var newLeft = L.getLeft(true);
17070 var newTop = L.getTop(true);
17071 this.deltaSetXY = [ newLeft - K.x, newTop - K.y ];
17073 L.setLeftTop(K.x + this.deltaSetXY[0], K.y + this.deltaSetXY[1]);
17077 this.cachePosition(K.x, K.y);
17078 this.autoScroll(K.x, K.y, el.offsetHeight, el.offsetWidth);
17083 * Saves the most recent position so that we can reset the constraints and
17084 * tick marks on-demand. We need to know this so that we can calculate the
17085 * number of pixels the element is offset from its original position.
17086 * @method cachePosition
17087 * @param iPageX the current x position (optional, this just makes it so we
17088 * don't have to look it up again)
17089 * @param iPageY the current y position (optional, this just makes it so we
17090 * don't have to look it up again)
17092 cachePosition: function(M, N) {
17094 this.lastPageX = M;
17095 this.lastPageY = N;
17097 var aCoord = Roo.lib.Dom.getXY(this.getEl());
17098 this.lastPageX = aCoord[0];
17099 this.lastPageY = aCoord[1];
17104 * Auto-scroll the window if the dragged object has been moved beyond the
17105 * visible window boundary.
17106 * @method autoScroll
17107 * @param {int} x the drag element's x position
17108 * @param {int} y the drag element's y position
17109 * @param {int} h the height of the drag element
17110 * @param {int} w the width of the drag element
17113 autoScroll: function(x, y, h, w) {
17116 // The client height
17117 var clientH = Roo.lib.Dom.getViewWidth();
17119 // The client width
17120 var clientW = Roo.lib.Dom.getViewHeight();
17122 // The amt scrolled down
17123 var st = this.DDM.getScrollTop();
17125 // The amt scrolled right
17126 var sl = this.DDM.getScrollLeft();
17128 // Location of the bottom of the element
17131 // Location of the right of the element
17134 // The distance from the cursor to the bottom of the visible area,
17135 // adjusted so that we don't scroll if the cursor is beyond the
17136 // element drag constraints
17137 var toBot = (clientH + st - y - this.deltaY);
17139 // The distance from the cursor to the right of the visible area
17140 var toRight = (clientW + sl - x - this.deltaX);
17143 // How close to the edge the cursor must be before we scroll
17144 // var thresh = (document.all) ? 100 : 40;
17147 // How many pixels to scroll per autoscroll op. This helps to reduce
17148 // clunky scrolling. IE is more sensitive about this ... it needs this
17149 // value to be higher.
17150 var scrAmt = (document.all) ? 80 : 30;
17152 // Scroll down if we are near the bottom of the visible page and the
17153 // obj extends below the crease
17154 if ( bot > clientH && toBot < thresh ) {
17155 window.scrollTo(sl, st + scrAmt);
17158 // Scroll up if the window is scrolled down and the top of the object
17159 // goes above the top border
17160 if ( y < st && st > 0 && y - st < thresh ) {
17161 window.scrollTo(sl, st - scrAmt);
17164 // Scroll right if the obj is beyond the right border and the cursor is
17165 // near the border.
17166 if ( right > clientW && toRight < thresh ) {
17167 window.scrollTo(sl + scrAmt, st);
17170 // Scroll left if the window has been scrolled to the right and the obj
17171 // extends past the left border
17172 if ( x < sl && sl > 0 && x - sl < thresh ) {
17173 window.scrollTo(sl - scrAmt, st);
17179 * Finds the location the element should be placed if we want to move
17180 * it to where the mouse location less the click offset would place us.
17181 * @method getTargetCoord
17182 * @param {int} iPageX the X coordinate of the click
17183 * @param {int} iPageY the Y coordinate of the click
17184 * @return an object that contains the coordinates (Object.x and Object.y)
17187 getTargetCoord: function(O, P) {
17190 var x = O - this.deltaX;
17191 var y = P - this.deltaY;
17193 if (this.constrainX) {
17194 if (x < this.minX) { x = this.minX; }
17195 if (x > this.maxX) { x = this.maxX; }
17198 if (this.constrainY) {
17199 if (y < this.minY) { y = this.minY; }
17200 if (y > this.maxY) { y = this.maxY; }
17204 x = this.getTick(x, this.xTicks);
17205 y = this.getTick(y, this.yTicks);
17212 * Sets up config options specific to this class. Overrides
17213 * Roo.dd.DragDrop, but all versions of this method through the
17214 * inheritance chain are called
17216 applyConfig: function() {
17217 Roo.dd.DD.superclass.applyConfig.call(this);
17218 this.scroll = (this.config.scroll !== false);
17222 * Event that fires prior to the onMouseDown event. Overrides
17225 b4MouseDown: function(e) {
17226 // this.resetConstraints();
17227 this.autoOffset(e.getPageX(),
17232 * Event that fires prior to the onDrag event. Overrides
17235 b4Drag: function(e) {
17236 this.setDragElPos(e.getPageX(),
17240 toString: function() {
17241 return ("DD " + this.id);
17244 //////////////////////////////////////////////////////////////////////////
17245 // Debugging ygDragDrop events that can be overridden
17246 //////////////////////////////////////////////////////////////////////////
17248 startDrag: function(x, y) {
17251 onDrag: function(e) {
17254 onDragEnter: function(e, id) {
17257 onDragOver: function(e, id) {
17260 onDragOut: function(e, id) {
17263 onDragDrop: function(e, id) {
17266 endDrag: function(e) {
17274 * Ext JS Library 1.1.1
17275 * Copyright(c) 2006-2007, Ext JS, LLC.
17277 * Originally Released Under LGPL - original licence link has changed is not relivant.
17280 * <script type="text/javascript">
17284 * @class Roo.dd.DDProxy
17285 * A DragDrop implementation that inserts an empty, bordered div into
17286 * the document that follows the cursor during drag operations. At the time of
17287 * the click, the frame div is resized to the dimensions of the linked html
17288 * element, and moved to the exact location of the linked element.
17290 * References to the "frame" element refer to the single proxy element that
17291 * was created to be dragged in place of all DDProxy elements on the
17294 * @extends Roo.dd.DD
17296 * @param {String} id the id of the linked html element
17297 * @param {String} sGroup the group of related DragDrop objects
17298 * @param {object} config an object containing configurable attributes
17299 * Valid properties for DDProxy in addition to those in DragDrop:
17300 * resizeFrame, centerFrame, dragElId
17302 Roo.dd.DDProxy = function(id, A, B) {
17304 this.init(id, A, B);
17310 * The default drag frame div id
17311 * @property Roo.dd.DDProxy.dragElId
17315 Roo.dd.DDProxy.dragElId = "ygddfdiv";
17317 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
17320 * By default we resize the drag frame to be the same size as the element
17321 * we want to drag (this is to get the frame effect). We can turn it off
17322 * if we want a different behavior.
17323 * @property resizeFrame
17329 * By default the frame is positioned exactly where the drag element is, so
17330 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
17331 * you do not have constraints on the obj is to have the drag frame centered
17332 * around the cursor. Set centerFrame to true for this effect.
17333 * @property centerFrame
17336 centerFrame: false,
17339 * Creates the proxy element if it does not yet exist
17340 * @method createFrame
17342 createFrame: function() {
17344 var D = document.body;
17346 if (!D || !D.firstChild) {
17347 setTimeout( function() { C.createFrame(); }, 50 );
17351 var E = this.getDragEl();
17354 E = document.createElement("div");
17355 E.id = this.dragElId;
17358 s.position = "absolute";
17359 s.visibility = "hidden";
17361 s.border = "2px solid #aaa";
17364 // appendChild can blow up IE if invoked prior to the window load event
17365 // while rendering a table. It is possible there are other scenarios
17366 // that would cause this to happen as well.
17367 D.insertBefore(E, D.firstChild);
17372 * Initialization for the drag frame element. Must be called in the
17373 * constructor of all subclasses
17374 * @method initFrame
17376 initFrame: function() {
17377 this.createFrame();
17380 applyConfig: function() {
17381 Roo.dd.DDProxy.superclass.applyConfig.call(this);
17383 this.resizeFrame = (this.config.resizeFrame !== false);
17384 this.centerFrame = (this.config.centerFrame);
17385 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
17389 * Resizes the drag frame to the dimensions of the clicked object, positions
17390 * it over the object, and finally displays it
17391 * @method showFrame
17392 * @param {int} iPageX X click position
17393 * @param {int} iPageY Y click position
17396 showFrame: function(F, G) {
17397 var el = this.getEl();
17398 var H = this.getDragEl();
17401 this._resizeProxy();
17403 if (this.centerFrame) {
17404 this.setDelta( Math.round(parseInt(s.width, 10)/2),
17405 Math.round(parseInt(s.height, 10)/2) );
17409 this.setDragElPos(F, G);
17415 * The proxy is automatically resized to the dimensions of the linked
17416 * element when a drag is initiated, unless resizeFrame is set to false
17417 * @method _resizeProxy
17420 _resizeProxy: function() {
17421 if (this.resizeFrame) {
17422 var el = this.getEl();
17423 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
17427 // overrides Roo.dd.DragDrop
17428 b4MouseDown: function(e) {
17429 var x = e.getPageX();
17430 var y = e.getPageY();
17431 this.autoOffset(x, y);
17432 this.setDragElPos(x, y);
17435 // overrides Roo.dd.DragDrop
17436 b4StartDrag: function(x, y) {
17437 // show the drag frame
17438 this.showFrame(x, y);
17441 // overrides Roo.dd.DragDrop
17442 b4EndDrag: function(e) {
17443 Roo.fly(this.getDragEl()).hide();
17446 // overrides Roo.dd.DragDrop
17447 // By default we try to move the element to the last location of the frame.
17448 // This is so that the default behavior mirrors that of Roo.dd.DD.
17449 endDrag: function(e) {
17451 var I = this.getEl();
17452 var J = this.getDragEl();
17454 // Show the drag frame briefly so we can get its position
17455 J.style.visibility = "";
17458 // Hide the linked element before the move to get around a Safari
17460 I.style.visibility = "hidden";
17461 Roo.dd.DDM.moveToEl(I, J);
17462 J.style.visibility = "hidden";
17463 I.style.visibility = "";
17468 beforeMove : function(){
17472 afterDrag : function(){
17476 toString: function() {
17477 return ("DDProxy " + this.id);
17484 * Ext JS Library 1.1.1
17485 * Copyright(c) 2006-2007, Ext JS, LLC.
17487 * Originally Released Under LGPL - original licence link has changed is not relivant.
17490 * <script type="text/javascript">
17494 * @class Roo.dd.DDTarget
17495 * A DragDrop implementation that does not move, but can be a drop
17496 * target. You would get the same result by simply omitting implementation
17497 * for the event callbacks, but this way we reduce the processing cost of the
17498 * event listener and the callbacks.
17499 * @extends Roo.dd.DragDrop
17501 * @param {String} id the id of the element that is a drop target
17502 * @param {String} sGroup the group of related DragDrop objects
17503 * @param {object} config an object containing configurable attributes
17504 * Valid properties for DDTarget in addition to those in
17508 Roo.dd.DDTarget = function(id, A, B) {
17510 this.initTarget(id, A, B);
17514 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
17515 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
17516 toString: function() {
17517 return ("DDTarget " + this.id);
17523 * Ext JS Library 1.1.1
17524 * Copyright(c) 2006-2007, Ext JS, LLC.
17526 * Originally Released Under LGPL - original licence link has changed is not relivant.
17529 * <script type="text/javascript">
17534 * @class Roo.dd.ScrollManager
17535 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
17536 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
17539 Roo.dd.ScrollManager = function(){
17540 var A = Roo.dd.DragDropMgr;
17545 var E = function(e){
17550 var F = function(){
17552 A.refreshCache(A.dragCurrent.groups);
17556 var G = function(){
17558 var dds = Roo.dd.ScrollManager;
17560 if(D.el.scroll(D.dir, dds.increment)){
17564 D.el.scroll(D.dir, dds.increment, true, dds.animDuration, F);
17569 var H = function(){
17571 clearInterval(D.id);
17579 var I = function(el, K){
17583 D.id = setInterval(G, Roo.dd.ScrollManager.frequency);
17586 var J = function(e, K){
17587 if(K || !A.dragCurrent){ return; }
17588 var L = Roo.dd.ScrollManager;
17589 if(!C || C != A.dragCurrent){
17591 // refresh regions on drag start
17595 var xy = Roo.lib.Event.getXY(e);
17596 var pt = new Roo.lib.Point(xy[0], xy[1]);
17598 var el = B[id], r = el._region;
17599 if(r && r.contains(pt) && el.isScrollable()){
17600 if(r.bottom - pt.y <= L.thresh){
17605 }else if(r.right - pt.x <= L.thresh){
17610 }else if(pt.y - r.top <= L.thresh){
17615 }else if(pt.x - r.left <= L.thresh){
17627 A.fireEvents = A.fireEvents.createSequence(J, A);
17628 A.stopDrag = A.stopDrag.createSequence(E, A);
17632 * Registers new overflow element(s) to auto scroll
17633 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
17635 register : function(el){
17636 if(el instanceof Array){
17637 for(var i = 0, len = el.length; i < len; i++) {
17638 this.register(el[i]);
17647 * Unregisters overflow element(s) so they are no longer scrolled
17648 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
17650 unregister : function(el){
17651 if(el instanceof Array){
17652 for(var i = 0, len = el.length; i < len; i++) {
17653 this.unregister(el[i]);
17662 * The number of pixels from the edge of a container the pointer needs to be to
17663 * trigger scrolling (defaults to 25)
17669 * The number of pixels to scroll in each scroll increment (defaults to 50)
17675 * The frequency of scrolls in milliseconds (defaults to 500)
17681 * True to animate the scroll (defaults to true)
17687 * The animation duration in seconds -
17688 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
17694 * Manually trigger a cache refresh.
17696 refreshCache : function(){
17698 if(typeof B[id] == 'object'){ // for people extending the object prototype
17699 B[id]._region = B[id].getRegion();
17707 * Ext JS Library 1.1.1
17708 * Copyright(c) 2006-2007, Ext JS, LLC.
17710 * Originally Released Under LGPL - original licence link has changed is not relivant.
17713 * <script type="text/javascript">
17718 * @class Roo.dd.Registry
17719 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
17720 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
17723 Roo.dd.Registry = function(){
17728 var D = function(el, E){
17729 if(typeof el == "string"){
17733 if(!id && E !== false){
17734 id = "roodd-" + (++C);
17742 * Register a drag drop element
17743 * @param {String|HTMLElement} element The id or DOM node to register
17744 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
17745 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
17746 * knows how to interpret, plus there are some specific properties known to the Registry that should be
17747 * populated in the data object (if applicable):
17749 Value Description<br />
17750 --------- ------------------------------------------<br />
17751 handles Array of DOM nodes that trigger dragging<br />
17752 for the element being registered<br />
17753 isHandle True if the element passed in triggers<br />
17754 dragging itself, else false
17757 register : function(el, G){
17759 if(typeof el == "string"){
17760 el = document.getElementById(el);
17765 if(G.isHandle !== false){
17769 var hs = G.handles;
17770 for(var i = 0, len = hs.length; i < len; i++){
17777 * Unregister a drag drop element
17778 * @param {String|HTMLElement} element The id or DOM node to unregister
17780 unregister : function(el){
17781 var id = D(el, false);
17786 var hs = H.handles;
17787 for(var i = 0, len = hs.length; i < len; i++){
17788 delete B[D(hs[i], false)];
17795 * Returns the handle registered for a DOM Node by id
17796 * @param {String|HTMLElement} id The DOM node or id to look up
17797 * @return {Object} handle The custom handle data
17799 getHandle : function(id){
17800 if(typeof id != "string"){ // must be element?
17807 * Returns the handle that is registered for the DOM node that is the target of the event
17808 * @param {Event} e The event
17809 * @return {Object} handle The custom handle data
17811 getHandleFromEvent : function(e){
17812 var t = Roo.lib.Event.getTarget(e);
17813 return t ? B[t.id] : null;
17817 * Returns a custom data object that is registered for a DOM node by id
17818 * @param {String|HTMLElement} id The DOM node or id to look up
17819 * @return {Object} data The custom data
17821 getTarget : function(id){
17822 if(typeof id != "string"){ // must be element?
17829 * Returns a custom data object that is registered for the DOM node that is the target of the event
17830 * @param {Event} e The event
17831 * @return {Object} data The custom data
17833 getTargetFromEvent : function(e){
17834 var t = Roo.lib.Event.getTarget(e);
17835 return t ? A[t.id] || B[t.id] : null;
17841 * Ext JS Library 1.1.1
17842 * Copyright(c) 2006-2007, Ext JS, LLC.
17844 * Originally Released Under LGPL - original licence link has changed is not relivant.
17847 * <script type="text/javascript">
17852 * @class Roo.dd.StatusProxy
17853 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
17854 * default drag proxy used by all Roo.dd components.
17856 * @param {Object} config
17858 Roo.dd.StatusProxy = function(A){
17859 Roo.apply(this, A);
17860 this.id = this.id || Roo.id();
17861 this.el = new Roo.Layer({
17863 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
17864 {tag: "div", cls: "x-dd-drop-icon"},
17865 {tag: "div", cls: "x-dd-drag-ghost"}
17868 shadow: !A || A.shadow !== false
17870 this.ghost = Roo.get(this.el.dom.childNodes[1]);
17871 this.dropStatus = this.dropNotAllowed;
17874 Roo.dd.StatusProxy.prototype = {
17876 * @cfg {String} dropAllowed
17877 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
17879 dropAllowed : "x-dd-drop-ok",
17881 * @cfg {String} dropNotAllowed
17882 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
17884 dropNotAllowed : "x-dd-drop-nodrop",
17887 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
17888 * over the current target element.
17889 * @param {String} cssClass The css class for the new drop status indicator image
17891 setStatus : function(B){
17892 B = B || this.dropNotAllowed;
17893 if(this.dropStatus != B){
17894 this.el.replaceClass(this.dropStatus, B);
17895 this.dropStatus = B;
17900 * Resets the status indicator to the default dropNotAllowed value
17901 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
17903 reset : function(C){
17904 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
17905 this.dropStatus = this.dropNotAllowed;
17907 this.ghost.update("");
17912 * Updates the contents of the ghost element
17913 * @param {String} html The html that will replace the current innerHTML of the ghost element
17915 update : function(D){
17916 if(typeof D == "string"){
17917 this.ghost.update(D);
17919 this.ghost.update("");
17920 D.style.margin = "0";
17921 this.ghost.dom.appendChild(D);
17923 // ensure float = none set?? cant remember why though.
17924 var el = this.ghost.dom.firstChild;
17926 Roo.fly(el).setStyle('float', 'none');
17931 * Returns the underlying proxy {@link Roo.Layer}
17932 * @return {Roo.Layer} el
17934 getEl : function(){
17939 * Returns the ghost element
17940 * @return {Roo.Element} el
17942 getGhost : function(){
17948 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
17950 hide : function(E){
17958 * Stops the repair animation if it's currently running
17961 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
17967 * Displays this proxy
17974 * Force the Layer to sync its shadow and shim positions to the element
17981 * Causes the proxy to return to its position of origin via an animation. Should be called after an
17982 * invalid drop operation by the item being dragged.
17983 * @param {Array} xy The XY position of the element ([x, y])
17984 * @param {Function} callback The function to call after the repair is complete
17985 * @param {Object} scope The scope in which to execute the callback
17987 repair : function(xy, F, G){
17990 if(xy && this.animRepair !== false){
17991 this.el.addClass("x-dd-drag-repair");
17992 this.el.hideUnders(true);
17993 this.anim = this.el.shift({
17994 duration: this.repairDuration || .5,
17998 callback: this.afterRepair,
18002 this.afterRepair();
18007 afterRepair : function(){
18009 if(typeof this.callback == "function"){
18010 this.callback.call(this.scope || this);
18013 this.callback = null;
18019 * Ext JS Library 1.1.1
18020 * Copyright(c) 2006-2007, Ext JS, LLC.
18022 * Originally Released Under LGPL - original licence link has changed is not relivant.
18025 * <script type="text/javascript">
18029 * @class Roo.dd.DragSource
18030 * @extends Roo.dd.DDProxy
18031 * A simple class that provides the basic implementation needed to make any element draggable.
18033 * @param {String/HTMLElement/Element} el The container element
18034 * @param {Object} config
18036 Roo.dd.DragSource = function(el, A){
18037 this.el = Roo.get(el);
18038 this.dragData = {};
18040 Roo.apply(this, A);
18043 this.proxy = new Roo.dd.StatusProxy();
18047 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
18048 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
18050 this.dragging = false;
18053 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
18055 * @cfg {String} dropAllowed
18056 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
18058 dropAllowed : "x-dd-drop-ok",
18060 * @cfg {String} dropNotAllowed
18061 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
18063 dropNotAllowed : "x-dd-drop-nodrop",
18066 * Returns the data object associated with this drag source
18067 * @return {Object} data An object containing arbitrary data
18069 getDragData : function(e){
18070 return this.dragData;
18074 onDragEnter : function(e, id){
18075 var B = Roo.dd.DragDropMgr.getDDById(id);
18076 this.cachedTarget = B;
18077 if(this.beforeDragEnter(B, e, id) !== false){
18078 if(B.isNotifyTarget){
18079 var status = B.notifyEnter(this, e, this.dragData);
18080 this.proxy.setStatus(status);
18082 this.proxy.setStatus(this.dropAllowed);
18085 if(this.afterDragEnter){
18087 * An empty function by default, but provided so that you can perform a custom action
18088 * when the dragged item enters the drop target by providing an implementation.
18089 * @param {Roo.dd.DragDrop} target The drop target
18090 * @param {Event} e The event object
18091 * @param {String} id The id of the dragged element
18092 * @method afterDragEnter
18094 this.afterDragEnter(B, e, id);
18100 * An empty function by default, but provided so that you can perform a custom action
18101 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
18102 * @param {Roo.dd.DragDrop} target The drop target
18103 * @param {Event} e The event object
18104 * @param {String} id The id of the dragged element
18105 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
18107 beforeDragEnter : function(C, e, id){
18112 alignElWithMouse: function() {
18113 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
18118 onDragOver : function(e, id){
18119 var D = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
18120 if(this.beforeDragOver(D, e, id) !== false){
18121 if(D.isNotifyTarget){
18122 var status = D.notifyOver(this, e, this.dragData);
18123 this.proxy.setStatus(status);
18126 if(this.afterDragOver){
18128 * An empty function by default, but provided so that you can perform a custom action
18129 * while the dragged item is over the drop target by providing an implementation.
18130 * @param {Roo.dd.DragDrop} target The drop target
18131 * @param {Event} e The event object
18132 * @param {String} id The id of the dragged element
18133 * @method afterDragOver
18135 this.afterDragOver(D, e, id);
18141 * An empty function by default, but provided so that you can perform a custom action
18142 * while the dragged item is over the drop target and optionally cancel the onDragOver.
18143 * @param {Roo.dd.DragDrop} target The drop target
18144 * @param {Event} e The event object
18145 * @param {String} id The id of the dragged element
18146 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
18148 beforeDragOver : function(E, e, id){
18153 onDragOut : function(e, id){
18154 var F = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
18155 if(this.beforeDragOut(F, e, id) !== false){
18156 if(F.isNotifyTarget){
18157 F.notifyOut(this, e, this.dragData);
18160 this.proxy.reset();
18161 if(this.afterDragOut){
18163 * An empty function by default, but provided so that you can perform a custom action
18164 * after the dragged item is dragged out of the target without dropping.
18165 * @param {Roo.dd.DragDrop} target The drop target
18166 * @param {Event} e The event object
18167 * @param {String} id The id of the dragged element
18168 * @method afterDragOut
18170 this.afterDragOut(F, e, id);
18174 this.cachedTarget = null;
18178 * An empty function by default, but provided so that you can perform a custom action before the dragged
18179 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
18180 * @param {Roo.dd.DragDrop} target The drop target
18181 * @param {Event} e The event object
18182 * @param {String} id The id of the dragged element
18183 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
18185 beforeDragOut : function(G, e, id){
18190 onDragDrop : function(e, id){
18191 var H = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
18192 if(this.beforeDragDrop(H, e, id) !== false){
18193 if(H.isNotifyTarget){
18194 if(H.notifyDrop(this, e, this.dragData)){ // valid drop?
18195 this.onValidDrop(H, e, id);
18197 this.onInvalidDrop(H, e, id);
18200 this.onValidDrop(H, e, id);
18203 if(this.afterDragDrop){
18205 * An empty function by default, but provided so that you can perform a custom action
18206 * after a valid drag drop has occurred by providing an implementation.
18207 * @param {Roo.dd.DragDrop} target The drop target
18208 * @param {Event} e The event object
18209 * @param {String} id The id of the dropped element
18210 * @method afterDragDrop
18212 this.afterDragDrop(H, e, id);
18215 delete this.cachedTarget;
18219 * An empty function by default, but provided so that you can perform a custom action before the dragged
18220 * item is dropped onto the target and optionally cancel the onDragDrop.
18221 * @param {Roo.dd.DragDrop} target The drop target
18222 * @param {Event} e The event object
18223 * @param {String} id The id of the dragged element
18224 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
18226 beforeDragDrop : function(I, e, id){
18231 onValidDrop : function(J, e, id){
18233 if(this.afterValidDrop){
18235 * An empty function by default, but provided so that you can perform a custom action
18236 * after a valid drop has occurred by providing an implementation.
18237 * @param {Object} target The target DD
18238 * @param {Event} e The event object
18239 * @param {String} id The id of the dropped element
18240 * @method afterInvalidDrop
18242 this.afterValidDrop(J, e, id);
18247 getRepairXY : function(e, K){
18248 return this.el.getXY();
18252 onInvalidDrop : function(L, e, id){
18253 this.beforeInvalidDrop(L, e, id);
18254 if(this.cachedTarget){
18255 if(this.cachedTarget.isNotifyTarget){
18256 this.cachedTarget.notifyOut(this, e, this.dragData);
18259 this.cacheTarget = null;
18262 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
18264 if(this.afterInvalidDrop){
18266 * An empty function by default, but provided so that you can perform a custom action
18267 * after an invalid drop has occurred by providing an implementation.
18268 * @param {Event} e The event object
18269 * @param {String} id The id of the dropped element
18270 * @method afterInvalidDrop
18272 this.afterInvalidDrop(e, id);
18277 afterRepair : function(){
18279 this.el.highlight(this.hlColor || "c3daf9");
18282 this.dragging = false;
18286 * An empty function by default, but provided so that you can perform a custom action after an invalid
18287 * drop has occurred.
18288 * @param {Roo.dd.DragDrop} target The drop target
18289 * @param {Event} e The event object
18290 * @param {String} id The id of the dragged element
18291 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
18293 beforeInvalidDrop : function(M, e, id){
18298 handleMouseDown : function(e){
18299 if(this.dragging) {
18302 var N = this.getDragData(e);
18303 if(N && this.onBeforeDrag(N, e) !== false){
18306 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
18311 * An empty function by default, but provided so that you can perform a custom action before the initial
18312 * drag event begins and optionally cancel it.
18313 * @param {Object} data An object containing arbitrary data to be shared with drop targets
18314 * @param {Event} e The event object
18315 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
18317 onBeforeDrag : function(O, e){
18322 * An empty function by default, but provided so that you can perform a custom action once the initial
18323 * drag event has begun. The drag cannot be canceled from this function.
18324 * @param {Number} x The x position of the click on the dragged object
18325 * @param {Number} y The y position of the click on the dragged object
18327 onStartDrag : Roo.emptyFn,
18329 // private - YUI override
18330 startDrag : function(x, y){
18331 this.proxy.reset();
18332 this.dragging = true;
18333 this.proxy.update("");
18334 this.onInitDrag(x, y);
18339 onInitDrag : function(x, y){
18340 var P = this.el.dom.cloneNode(true);
18341 P.id = Roo.id(); // prevent duplicate ids
18342 this.proxy.update(P);
18343 this.onStartDrag(x, y);
18348 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
18349 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
18351 getProxy : function(){
18356 * Hides the drag source's {@link Roo.dd.StatusProxy}
18358 hideProxy : function(){
18360 this.proxy.reset(true);
18361 this.dragging = false;
18365 triggerCacheRefresh : function(){
18366 Roo.dd.DDM.refreshCache(this.groups);
18369 // private - override to prevent hiding
18370 b4EndDrag: function(e) {
18373 // private - override to prevent moving
18374 endDrag : function(e){
18375 this.onEndDrag(this.dragData, e);
18379 onEndDrag : function(Q, e){
18382 // private - pin to cursor
18383 autoOffset : function(x, y) {
18384 this.setDelta(-12, -20);
18389 * Ext JS Library 1.1.1
18390 * Copyright(c) 2006-2007, Ext JS, LLC.
18392 * Originally Released Under LGPL - original licence link has changed is not relivant.
18395 * <script type="text/javascript">
18400 * @class Roo.dd.DropTarget
18401 * @extends Roo.dd.DDTarget
18402 * A simple class that provides the basic implementation needed to make any element a drop target that can have
18403 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
18405 * @param {String/HTMLElement/Element} el The container element
18406 * @param {Object} config
18408 Roo.dd.DropTarget = function(el, A){
18409 this.el = Roo.get(el);
18411 Roo.apply(this, A);
18413 if(this.containerScroll){
18414 Roo.dd.ScrollManager.register(this.el);
18418 Roo.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
18423 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
18425 * @cfg {String} overClass
18426 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
18429 * @cfg {String} dropAllowed
18430 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
18432 dropAllowed : "x-dd-drop-ok",
18434 * @cfg {String} dropNotAllowed
18435 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
18437 dropNotAllowed : "x-dd-drop-nodrop",
18443 isNotifyTarget : true,
18446 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
18447 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
18448 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
18449 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18450 * @param {Event} e The event
18451 * @param {Object} data An object containing arbitrary data supplied by the drag source
18452 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18453 * underlying {@link Roo.dd.StatusProxy} can be updated
18455 notifyEnter : function(dd, e, B){
18456 if(this.overClass){
18457 this.el.addClass(this.overClass);
18459 return this.dropAllowed;
18463 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
18464 * This method will be called on every mouse movement while the drag source is over the drop target.
18465 * This default implementation simply returns the dropAllowed config value.
18466 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18467 * @param {Event} e The event
18468 * @param {Object} data An object containing arbitrary data supplied by the drag source
18469 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18470 * underlying {@link Roo.dd.StatusProxy} can be updated
18472 notifyOver : function(dd, e, C){
18473 return this.dropAllowed;
18477 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
18478 * out of the target without dropping. This default implementation simply removes the CSS class specified by
18479 * overClass (if any) from the drop element.
18480 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18481 * @param {Event} e The event
18482 * @param {Object} data An object containing arbitrary data supplied by the drag source
18484 notifyOut : function(dd, e, D){
18485 if(this.overClass){
18486 this.el.removeClass(this.overClass);
18491 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
18492 * been dropped on it. This method has no default implementation and returns false, so you must provide an
18493 * implementation that does something to process the drop event and returns true so that the drag source's
18494 * repair action does not run.
18495 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18496 * @param {Event} e The event
18497 * @param {Object} data An object containing arbitrary data supplied by the drag source
18498 * @return {Boolean} True if the drop was valid, else false
18500 notifyDrop : function(dd, e, E){
18506 * Ext JS Library 1.1.1
18507 * Copyright(c) 2006-2007, Ext JS, LLC.
18509 * Originally Released Under LGPL - original licence link has changed is not relivant.
18512 * <script type="text/javascript">
18517 * @class Roo.dd.DragZone
18518 * @extends Roo.dd.DragSource
18519 * This class provides a container DD instance that proxies for multiple child node sources.<br />
18520 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
18522 * @param {String/HTMLElement/Element} el The container element
18523 * @param {Object} config
18525 Roo.dd.DragZone = function(el, A){
18526 Roo.dd.DragZone.superclass.constructor.call(this, el, A);
18527 if(this.containerScroll){
18528 Roo.dd.ScrollManager.register(this.el);
18532 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
18534 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
18535 * for auto scrolling during drag operations.
18538 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
18539 * method after a failed drop (defaults to "c3daf9" - light blue)
18543 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
18544 * for a valid target to drag based on the mouse down. Override this method
18545 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
18546 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
18547 * @param {EventObject} e The mouse down event
18548 * @return {Object} The dragData
18550 getDragData : function(e){
18551 return Roo.dd.Registry.getHandleFromEvent(e);
18555 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
18556 * this.dragData.ddel
18557 * @param {Number} x The x position of the click on the dragged object
18558 * @param {Number} y The y position of the click on the dragged object
18559 * @return {Boolean} true to continue the drag, false to cancel
18561 onInitDrag : function(x, y){
18562 this.proxy.update(this.dragData.ddel.cloneNode(true));
18563 this.onStartDrag(x, y);
18568 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
18570 afterRepair : function(){
18572 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
18575 this.dragging = false;
18579 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
18580 * the XY of this.dragData.ddel
18581 * @param {EventObject} e The mouse up event
18582 * @return {Array} The xy location (e.g. [100, 200])
18584 getRepairXY : function(e){
18585 return Roo.Element.fly(this.dragData.ddel).getXY();
18590 * Ext JS Library 1.1.1
18591 * Copyright(c) 2006-2007, Ext JS, LLC.
18593 * Originally Released Under LGPL - original licence link has changed is not relivant.
18596 * <script type="text/javascript">
18599 * @class Roo.dd.DropZone
18600 * @extends Roo.dd.DropTarget
18601 * This class provides a container DD instance that proxies for multiple child node targets.<br />
18602 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
18604 * @param {String/HTMLElement/Element} el The container element
18605 * @param {Object} config
18607 Roo.dd.DropZone = function(el, A){
18608 Roo.dd.DropZone.superclass.constructor.call(this, el, A);
18611 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
18613 * Returns a custom data object associated with the DOM node that is the target of the event. By default
18614 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
18615 * provide your own custom lookup.
18616 * @param {Event} e The event
18617 * @return {Object} data The custom data
18619 getTargetFromEvent : function(e){
18620 return Roo.dd.Registry.getTargetFromEvent(e);
18624 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
18625 * that it has registered. This method has no default implementation and should be overridden to provide
18626 * node-specific processing if necessary.
18627 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18628 * {@link #getTargetFromEvent} for this node)
18629 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18630 * @param {Event} e The event
18631 * @param {Object} data An object containing arbitrary data supplied by the drag source
18633 onNodeEnter : function(n, dd, e, B){
18638 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
18639 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
18640 * overridden to provide the proper feedback.
18641 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18642 * {@link #getTargetFromEvent} for this node)
18643 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18644 * @param {Event} e The event
18645 * @param {Object} data An object containing arbitrary data supplied by the drag source
18646 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18647 * underlying {@link Roo.dd.StatusProxy} can be updated
18649 onNodeOver : function(n, dd, e, C){
18650 return this.dropAllowed;
18654 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
18655 * the drop node without dropping. This method has no default implementation and should be overridden to provide
18656 * node-specific processing if necessary.
18657 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18658 * {@link #getTargetFromEvent} for this node)
18659 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18660 * @param {Event} e The event
18661 * @param {Object} data An object containing arbitrary data supplied by the drag source
18663 onNodeOut : function(n, dd, e, D){
18668 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
18669 * the drop node. The default implementation returns false, so it should be overridden to provide the
18670 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
18671 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18672 * {@link #getTargetFromEvent} for this node)
18673 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18674 * @param {Event} e The event
18675 * @param {Object} data An object containing arbitrary data supplied by the drag source
18676 * @return {Boolean} True if the drop was valid, else false
18678 onNodeDrop : function(n, dd, e, E){
18683 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
18684 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
18685 * it should be overridden to provide the proper feedback if necessary.
18686 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18687 * @param {Event} e The event
18688 * @param {Object} data An object containing arbitrary data supplied by the drag source
18689 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18690 * underlying {@link Roo.dd.StatusProxy} can be updated
18692 onContainerOver : function(dd, e, F){
18693 return this.dropNotAllowed;
18697 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
18698 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
18699 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
18700 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
18701 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18702 * @param {Event} e The event
18703 * @param {Object} data An object containing arbitrary data supplied by the drag source
18704 * @return {Boolean} True if the drop was valid, else false
18706 onContainerDrop : function(dd, e, G){
18711 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
18712 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
18713 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
18714 * you should override this method and provide a custom implementation.
18715 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18716 * @param {Event} e The event
18717 * @param {Object} data An object containing arbitrary data supplied by the drag source
18718 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18719 * underlying {@link Roo.dd.StatusProxy} can be updated
18721 notifyEnter : function(dd, e, H){
18722 return this.dropNotAllowed;
18726 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
18727 * This method will be called on every mouse movement while the drag source is over the drop zone.
18728 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
18729 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
18730 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
18731 * registered node, it will call {@link #onContainerOver}.
18732 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18733 * @param {Event} e The event
18734 * @param {Object} data An object containing arbitrary data supplied by the drag source
18735 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18736 * underlying {@link Roo.dd.StatusProxy} can be updated
18738 notifyOver : function(dd, e, I){
18739 var n = this.getTargetFromEvent(e);
18740 if(!n){ // not over valid drop target
18741 if(this.lastOverNode){
18742 this.onNodeOut(this.lastOverNode, dd, e, I);
18743 this.lastOverNode = null;
18745 return this.onContainerOver(dd, e, I);
18747 if(this.lastOverNode != n){
18748 if(this.lastOverNode){
18749 this.onNodeOut(this.lastOverNode, dd, e, I);
18752 this.onNodeEnter(n, dd, e, I);
18753 this.lastOverNode = n;
18755 return this.onNodeOver(n, dd, e, I);
18759 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
18760 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
18761 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
18762 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18763 * @param {Event} e The event
18764 * @param {Object} data An object containing arbitrary data supplied by the drag zone
18766 notifyOut : function(dd, e, J){
18767 if(this.lastOverNode){
18768 this.onNodeOut(this.lastOverNode, dd, e, J);
18769 this.lastOverNode = null;
18774 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
18775 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
18776 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
18777 * otherwise it will call {@link #onContainerDrop}.
18778 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18779 * @param {Event} e The event
18780 * @param {Object} data An object containing arbitrary data supplied by the drag source
18781 * @return {Boolean} True if the drop was valid, else false
18783 notifyDrop : function(dd, e, K){
18784 if(this.lastOverNode){
18785 this.onNodeOut(this.lastOverNode, dd, e, K);
18786 this.lastOverNode = null;
18788 var n = this.getTargetFromEvent(e);
18790 this.onNodeDrop(n, dd, e, K) :
18791 this.onContainerDrop(dd, e, K);
18795 triggerCacheRefresh : function(){
18796 Roo.dd.DDM.refreshCache(this.groups);
18801 * Ext JS Library 1.1.1
18802 * Copyright(c) 2006-2007, Ext JS, LLC.
18804 * Originally Released Under LGPL - original licence link has changed is not relivant.
18807 * <script type="text/javascript">
18812 * @class Roo.data.SortTypes
18814 * Defines the default sorting (casting?) comparison functions used when sorting data.
18816 Roo.data.SortTypes = {
18818 * Default sort that does nothing
18819 * @param {Mixed} s The value being converted
18820 * @return {Mixed} The comparison value
18822 none : function(s){
18827 * The regular expression used to strip tags
18831 stripTagsRE : /<\/?[^>]+>/gi,
18834 * Strips all HTML tags to sort on text only
18835 * @param {Mixed} s The value being converted
18836 * @return {String} The comparison value
18838 asText : function(s){
18839 return String(s).replace(this.stripTagsRE, "");
18843 * Strips all HTML tags to sort on text only - Case insensitive
18844 * @param {Mixed} s The value being converted
18845 * @return {String} The comparison value
18847 asUCText : function(s){
18848 return String(s).toUpperCase().replace(this.stripTagsRE, "");
18852 * Case insensitive string
18853 * @param {Mixed} s The value being converted
18854 * @return {String} The comparison value
18856 asUCString : function(s) {
18857 return String(s).toUpperCase();
18862 * @param {Mixed} s The value being converted
18863 * @return {Number} The comparison value
18865 asDate : function(s) {
18869 if(s instanceof Date){
18870 return s.getTime();
18872 return Date.parse(String(s));
18877 * @param {Mixed} s The value being converted
18878 * @return {Float} The comparison value
18880 asFloat : function(s) {
18881 var A = parseFloat(String(s).replace(/,/g, ""));
18882 if(isNaN(A)) A = 0;
18888 * @param {Mixed} s The value being converted
18889 * @return {Number} The comparison value
18891 asInt : function(s) {
18892 var B = parseInt(String(s).replace(/,/g, ""));
18893 if(isNaN(B)) B = 0;
18899 * Ext JS Library 1.1.1
18900 * Copyright(c) 2006-2007, Ext JS, LLC.
18902 * Originally Released Under LGPL - original licence link has changed is not relivant.
18905 * <script type="text/javascript">
18909 * @class Roo.data.Record
18910 * Instances of this class encapsulate both record <em>definition</em> information, and record
18911 * <em>value</em> information for use in {@link Roo.data.Store} objects, or any code which needs
18912 * to access Records cached in an {@link Roo.data.Store} object.<br>
18914 * Constructors for this class are generated by passing an Array of field definition objects to {@link #create}.
18915 * Instances are usually only created by {@link Roo.data.Reader} implementations when processing unformatted data
18918 * Record objects generated by this constructor inherit all the methods of Roo.data.Record listed below.
18920 * This constructor should not be used to create Record objects. Instead, use the constructor generated by
18921 * {@link #create}. The parameters are the same.
18922 * @param {Array} data An associative Array of data values keyed by the field name.
18923 * @param {Object} id (Optional) The id of the record. This id should be unique, and is used by the
18924 * {@link Roo.data.Store} object which owns the Record to index its collection of Records. If
18925 * not specified an integer id is generated.
18927 Roo.data.Record = function(A, id){
18928 this.id = (id || id === 0) ? id : ++Roo.data.Record.AUTO_ID;
18933 * Generate a constructor for a specific record layout.
18934 * @param {Array} o An Array of field definition objects which specify field names, and optionally,
18935 * data types, and a mapping for an {@link Roo.data.Reader} to extract the field's value from a data object.
18936 * Each field definition object may contain the following properties: <ul>
18937 * <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,
18938 * for example the <em>dataIndex</em> property in column definition objects passed to {@link Roo.grid.ColumnModel}</p></li>
18939 * <li><b>mapping</b> : String<p style="margin-left:1em">(Optional) A path specification for use by the {@link Roo.data.Reader} implementation
18940 * that is creating the Record to access the data value from the data object. If an {@link Roo.data.JsonReader}
18941 * is being used, then this is a string containing the javascript expression to reference the data relative to
18942 * the record item's root. If an {@link Roo.data.XmlReader} is being used, this is an {@link Roo.DomQuery} path
18943 * to the data item relative to the record element. If the mapping expression is the same as the field name,
18944 * this may be omitted.</p></li>
18945 * <li><b>type</b> : String<p style="margin-left:1em">(Optional) The data type for conversion to displayable value. Possible values are
18946 * <ul><li>auto (Default, implies no conversion)</li>
18951 * <li>date</li></ul></p></li>
18952 * <li><b>sortType</b> : Mixed<p style="margin-left:1em">(Optional) A member of {@link Roo.data.SortTypes}.</p></li>
18953 * <li><b>sortDir</b> : String<p style="margin-left:1em">(Optional) Initial direction to sort. "ASC" or "DESC"</p></li>
18954 * <li><b>convert</b> : Function<p style="margin-left:1em">(Optional) A function which converts the value provided
18955 * by the Reader into an object that will be stored in the Record. It is passed the
18956 * following parameters:<ul>
18957 * <li><b>v</b> : Mixed<p style="margin-left:1em">The data value as read by the Reader.</p></li>
18959 * <li><b>dateFormat</b> : String<p style="margin-left:1em">(Optional) A format String for the Date.parseDate function.</p></li>
18961 * <br>usage:<br><pre><code>
18962 var TopicRecord = Roo.data.Record.create(
18963 {name: 'title', mapping: 'topic_title'},
18964 {name: 'author', mapping: 'username'},
18965 {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
18966 {name: 'lastPost', mapping: 'post_time', type: 'date'},
18967 {name: 'lastPoster', mapping: 'user2'},
18968 {name: 'excerpt', mapping: 'post_text'}
18971 var myNewRecord = new TopicRecord({
18972 title: 'Do my job please',
18975 lastPost: new Date(),
18976 lastPoster: 'Animal',
18977 excerpt: 'No way dude!'
18979 myStore.add(myNewRecord);
18984 Roo.data.Record.create = function(o){
18985 var f = function(){
18986 f.superclass.constructor.apply(this, arguments);
18988 Roo.extend(f, Roo.data.Record);
18989 var p = f.prototype;
18990 p.fields = new Roo.util.MixedCollection(false, function(B){
18993 for(var i = 0, len = o.length; i < len; i++){
18994 p.fields.add(new Roo.data.Field(o[i]));
18997 f.getField = function(B){
18998 return p.fields.get(B);
19003 Roo.data.Record.AUTO_ID = 1000;
19004 Roo.data.Record.EDIT = 'edit';
19005 Roo.data.Record.REJECT = 'reject';
19006 Roo.data.Record.COMMIT = 'commit';
19008 Roo.data.Record.prototype = {
19010 * Readonly flag - true if this record has been modified.
19019 join : function(B){
19024 * Set the named field to the specified value.
19025 * @param {String} name The name of the field to set.
19026 * @param {Object} value The value to set the field to.
19028 set : function(C, D){
19029 if(this.data[C] == D){
19034 if(!this.modified){
19035 this.modified = {};
19037 if(typeof this.modified[C] == 'undefined'){
19038 this.modified[C] = this.data[C];
19043 this.store.afterEdit(this);
19048 * Get the value of the named field.
19049 * @param {String} name The name of the field to get the value of.
19050 * @return {Object} The value of the field.
19053 return this.data[E];
19057 beginEdit : function(){
19058 this.editing = true;
19059 this.modified = {};
19063 cancelEdit : function(){
19064 this.editing = false;
19065 delete this.modified;
19069 endEdit : function(){
19070 this.editing = false;
19071 if(this.dirty && this.store){
19072 this.store.afterEdit(this);
19077 * Usually called by the {@link Roo.data.Store} which owns the Record.
19078 * Rejects all changes made to the Record since either creation, or the last commit operation.
19079 * Modified fields are reverted to their original values.
19081 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
19082 * of reject operations.
19084 reject : function(){
19085 var m = this.modified;
19087 if(typeof m[n] != "function"){
19088 this.data[n] = m[n];
19092 this.dirty = false;
19093 delete this.modified;
19094 this.editing = false;
19096 this.store.afterReject(this);
19101 * Usually called by the {@link Roo.data.Store} which owns the Record.
19102 * Commits all changes made to the Record since either creation, or the last commit operation.
19104 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
19105 * of commit operations.
19107 commit : function(){
19108 this.dirty = false;
19109 delete this.modified;
19110 this.editing = false;
19112 this.store.afterCommit(this);
19117 hasError : function(){
19118 return this.error != null;
19122 clearError : function(){
19127 * Creates a copy of this record.
19128 * @param {String} id (optional) A new record id if you don't want to use this record's id
19131 copy : function(F) {
19132 return new this.constructor(Roo.apply({}, this.data), F || this.id);
19137 * Ext JS Library 1.1.1
19138 * Copyright(c) 2006-2007, Ext JS, LLC.
19140 * Originally Released Under LGPL - original licence link has changed is not relivant.
19143 * <script type="text/javascript">
19149 * @class Roo.data.Store
19150 * @extends Roo.util.Observable
19151 * The Store class encapsulates a client side cache of {@link Roo.data.Record} objects which provide input data
19152 * for widgets such as the Roo.grid.Grid, or the Roo.form.ComboBox.<br>
19154 * 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
19155 * has no knowledge of the format of the data returned by the Proxy.<br>
19157 * A Store object uses its configured implementation of {@link Roo.data.DataReader} to create {@link Roo.data.Record}
19158 * instances from the data object. These records are cached and made available through accessor functions.
19160 * Creates a new Store.
19161 * @param {Object} config A config object containing the objects needed for the Store to access data,
19162 * and read the data into Records.
19164 Roo.data.Store = function(A){
19165 this.data = new Roo.util.MixedCollection(false);
19166 this.data.getKey = function(o){
19169 this.baseParams = {};
19171 this.paramNames = {
19179 this.inlineData = A.data;
19184 Roo.apply(this, A);
19186 if(this.reader){ // reader passed
19187 this.reader = Roo.factory(this.reader, Roo.data);
19188 this.reader.xmodule = this.xmodule || false;
19189 if(!this.recordType){
19190 this.recordType = this.reader.recordType;
19192 if(this.reader.onMetaChange){
19193 this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
19197 if(this.recordType){
19198 this.fields = this.recordType.prototype.fields;
19201 this.modified = [];
19205 * @event datachanged
19206 * Fires when the data cache has changed, and a widget which is using this Store
19207 * as a Record cache should refresh its view.
19208 * @param {Store} this
19210 datachanged : true,
19212 * @event metachange
19213 * Fires when this store's reader provides new metadata (fields). This is currently only support for JsonReaders.
19214 * @param {Store} this
19215 * @param {Object} meta The JSON metadata
19220 * Fires when Records have been added to the Store
19221 * @param {Store} this
19222 * @param {Roo.data.Record[]} records The array of Records added
19223 * @param {Number} index The index at which the record(s) were added
19228 * Fires when a Record has been removed from the Store
19229 * @param {Store} this
19230 * @param {Roo.data.Record} record The Record that was removed
19231 * @param {Number} index The index at which the record was removed
19236 * Fires when a Record has been updated
19237 * @param {Store} this
19238 * @param {Roo.data.Record} record The Record that was updated
19239 * @param {String} operation The update operation being performed. Value may be one of:
19241 Roo.data.Record.EDIT
19242 Roo.data.Record.REJECT
19243 Roo.data.Record.COMMIT
19249 * Fires when the data cache has been cleared.
19250 * @param {Store} this
19254 * @event beforeload
19255 * Fires before a request is made for a new data object. If the beforeload handler returns false
19256 * the load action will be canceled.
19257 * @param {Store} this
19258 * @param {Object} options The loading options that were specified (see {@link #load} for details)
19263 * Fires after a new set of Records has been loaded.
19264 * @param {Store} this
19265 * @param {Roo.data.Record[]} records The Records that were loaded
19266 * @param {Object} options The loading options that were specified (see {@link #load} for details)
19270 * @event loadexception
19271 * Fires if an exception occurs in the Proxy during loading.
19272 * Called with the signature of the Proxy's "loadexception" event.
19273 * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
19276 * @param {Object} return from JsonData.reader() - success, totalRecords, records
19277 * @param {Object} load options
19278 * @param {Object} jsonData from your request (normally this contains the Exception)
19280 loadexception : true
19284 this.proxy = Roo.factory(this.proxy, Roo.data);
19285 this.proxy.xmodule = this.xmodule || false;
19286 this.relayEvents(this.proxy, ["loadexception"]);
19289 this.sortToggle = {};
19291 Roo.data.Store.superclass.constructor.call(this);
19293 if(this.inlineData){
19294 this.loadData(this.inlineData);
19295 delete this.inlineData;
19298 Roo.extend(Roo.data.Store, Roo.util.Observable, {
19300 * @cfg {boolean} isLocal flag if data is locally available (and can be always looked up
19301 * without a remote query - used by combo/forms at present.
19305 * @cfg {Roo.data.DataProxy} proxy The Proxy object which provides access to a data object.
19308 * @cfg {Array} data Inline data to be loaded when the store is initialized.
19311 * @cfg {Roo.data.Reader} reader The Reader object which processes the data object and returns
19312 * an Array of Roo.data.record objects which are cached keyed by their <em>id</em> property.
19315 * @cfg {Object} baseParams An object containing properties which are to be sent as parameters
19316 * on any HTTP request
19319 * @cfg {Object} sortInfo A config object in the format: {field: "fieldName", direction: "ASC|DESC"}
19322 * @cfg {boolean} remoteSort True if sorting is to be handled by requesting the Proxy to provide a refreshed
19323 * version of the data object in sorted order, as opposed to sorting the Record cache in place (defaults to false).
19325 remoteSort : false,
19328 * @cfg {boolean} pruneModifiedRecords True to clear all modified record information each time the store is
19329 * loaded or when a record is removed. (defaults to false).
19331 pruneModifiedRecords : false,
19334 lastOptions : null,
19337 * Add Records to the Store and fires the add event.
19338 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
19342 for(var i = 0, len = B.length; i < len; i++){
19345 var C = this.data.length;
19346 this.data.addAll(B);
19347 this.fireEvent("add", this, B, C);
19351 * Remove a Record from the Store and fires the remove event.
19352 * @param {Ext.data.Record} record The Roo.data.Record object to remove from the cache.
19354 remove : function(D){
19355 var E = this.data.indexOf(D);
19356 this.data.removeAt(E);
19357 if(this.pruneModifiedRecords){
19358 this.modified.remove(D);
19361 this.fireEvent("remove", this, D, E);
19365 * Remove all Records from the Store and fires the clear event.
19367 removeAll : function(){
19369 if(this.pruneModifiedRecords){
19370 this.modified = [];
19373 this.fireEvent("clear", this);
19377 * Inserts Records to the Store at the given index and fires the add event.
19378 * @param {Number} index The start index at which to insert the passed Records.
19379 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
19381 insert : function(F, G){
19383 for(var i = 0, len = G.length; i < len; i++){
19384 this.data.insert(F, G[i]);
19388 this.fireEvent("add", this, G, F);
19392 * Get the index within the cache of the passed Record.
19393 * @param {Roo.data.Record} record The Roo.data.Record object to to find.
19394 * @return {Number} The index of the passed Record. Returns -1 if not found.
19396 indexOf : function(H){
19397 return this.data.indexOf(H);
19401 * Get the index within the cache of the Record with the passed id.
19402 * @param {String} id The id of the Record to find.
19403 * @return {Number} The index of the Record. Returns -1 if not found.
19405 indexOfId : function(id){
19406 return this.data.indexOfKey(id);
19410 * Get the Record with the specified id.
19411 * @param {String} id The id of the Record to find.
19412 * @return {Roo.data.Record} The Record with the passed id. Returns undefined if not found.
19414 getById : function(id){
19415 return this.data.key(id);
19419 * Get the Record at the specified index.
19420 * @param {Number} index The index of the Record to find.
19421 * @return {Roo.data.Record} The Record at the passed index. Returns undefined if not found.
19423 getAt : function(I){
19424 return this.data.itemAt(I);
19428 * Returns a range of Records between specified indices.
19429 * @param {Number} startIndex (optional) The starting index (defaults to 0)
19430 * @param {Number} endIndex (optional) The ending index (defaults to the last Record in the Store)
19431 * @return {Roo.data.Record[]} An array of Records
19433 getRange : function(J, K){
19434 return this.data.getRange(J, K);
19438 storeOptions : function(o){
19439 o = Roo.apply({}, o);
19442 this.lastOptions = o;
19446 * Loads the Record cache from the configured Proxy using the configured Reader.
19448 * If using remote paging, then the first load call must specify the <em>start</em>
19449 * and <em>limit</em> properties in the options.params property to establish the initial
19450 * position within the dataset, and the number of Records to cache on each read from the Proxy.
19452 * <strong>It is important to note that for remote data sources, loading is asynchronous,
19453 * and this call will return before the new data has been loaded. Perform any post-processing
19454 * in a callback function, or in a "load" event handler.</strong>
19456 * @param {Object} options An object containing properties which control loading options:<ul>
19457 * <li>params {Object} An object containing properties to pass as HTTP parameters to a remote data source.</li>
19458 * <li>callback {Function} A function to be called after the Records have been loaded. The callback is
19459 * passed the following arguments:<ul>
19460 * <li>r : Roo.data.Record[]</li>
19461 * <li>options: Options object from the load call</li>
19462 * <li>success: Boolean success indicator</li></ul></li>
19463 * <li>scope {Object} Scope with which to call the callback (defaults to the Store object)</li>
19464 * <li>add {Boolean} indicator to append loaded records rather than replace the current cache.</li>
19467 load : function(L){
19469 if(this.fireEvent("beforeload", this, L) !== false){
19470 this.storeOptions(L);
19471 var p = Roo.apply(L.params || {}, this.baseParams);
19472 if(this.sortInfo && this.remoteSort){
19473 var pn = this.paramNames;
19474 p[pn["sort"]] = this.sortInfo.field;
19475 p[pn["dir"]] = this.sortInfo.direction;
19478 this.proxy.load(p, this.reader, this.loadRecords, this, L);
19483 * Reloads the Record cache from the configured Proxy using the configured Reader and
19484 * the options from the last load operation performed.
19485 * @param {Object} options (optional) An object containing properties which may override the options
19486 * used in the last load operation. See {@link #load} for details (defaults to null, in which case
19487 * the most recently used options are reused).
19489 reload : function(M){
19490 this.load(Roo.applyIf(M||{}, this.lastOptions));
19494 // Called as a callback by the Reader during a load operation.
19495 loadRecords : function(o, N, O){
19496 if(!o || O === false){
19498 this.fireEvent("load", this, [], N);
19501 N.callback.call(N.scope || this, [], N, false);
19505 // if data returned failure - throw an exception.
19506 if (o.success === false) {
19507 this.fireEvent("loadexception", this, o, N, this.reader.jsonData);
19510 var r = o.records, t = o.totalRecords || r.length;
19511 if(!N || N.add !== true){
19512 if(this.pruneModifiedRecords){
19513 this.modified = [];
19515 for(var i = 0, len = r.length; i < len; i++){
19519 this.data = this.snapshot;
19520 delete this.snapshot;
19524 this.data.addAll(r);
19525 this.totalLength = t;
19527 this.fireEvent("datachanged", this);
19529 this.totalLength = Math.max(t, this.data.length+r.length);
19533 this.fireEvent("load", this, r, N);
19535 N.callback.call(N.scope || this, r, N, true);
19540 * Loads data from a passed data block. A Reader which understands the format of the data
19541 * must have been configured in the constructor.
19542 * @param {Object} data The data block from which to read the Records. The format of the data expected
19543 * is dependent on the type of Reader that is configured and should correspond to that Reader's readRecords parameter.
19544 * @param {Boolean} append (Optional) True to append the new Records rather than replace the existing cache.
19546 loadData : function(o, P){
19547 var r = this.reader.readRecords(o);
19548 this.loadRecords(r, {add: P}, true);
19552 * Gets the number of cached records.
19554 * <em>If using paging, this may not be the total size of the dataset. If the data object
19555 * used by the Reader contains the dataset size, then the getTotalCount() function returns
19556 * the data set size</em>
19558 getCount : function(){
19559 return this.data.length || 0;
19563 * Gets the total number of records in the dataset as returned by the server.
19565 * <em>If using paging, for this to be accurate, the data object used by the Reader must contain
19566 * the dataset size</em>
19568 getTotalCount : function(){
19569 return this.totalLength || 0;
19573 * Returns the sort state of the Store as an object with two properties:
19575 field {String} The name of the field by which the Records are sorted
19576 direction {String} The sort order, "ASC" or "DESC"
19579 getSortState : function(){
19580 return this.sortInfo;
19584 applySort : function(){
19585 if(this.sortInfo && !this.remoteSort){
19586 var s = this.sortInfo, f = s.field;
19587 var st = this.fields.get(f).sortType;
19588 var fn = function(r1, r2){
19589 var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
19590 return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
19592 this.data.sort(s.direction, fn);
19593 if(this.snapshot && this.snapshot != this.data){
19594 this.snapshot.sort(s.direction, fn);
19600 * Sets the default sort column and order to be used by the next load operation.
19601 * @param {String} fieldName The name of the field to sort by.
19602 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
19604 setDefaultSort : function(Q, R){
19605 this.sortInfo = {field: Q, direction: R ? R.toUpperCase() : "ASC"};
19609 * Sort the Records.
19610 * If remote sorting is used, the sort is performed on the server, and the cache is
19611 * reloaded. If local sorting is used, the cache is sorted internally.
19612 * @param {String} fieldName The name of the field to sort by.
19613 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
19615 sort : function(S, T){
19616 var f = this.fields.get(S);
19618 if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir
19619 T = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
19625 this.sortToggle[f.name] = T;
19626 this.sortInfo = {field: f.name, direction: T};
19627 if(!this.remoteSort){
19629 this.fireEvent("datachanged", this);
19631 this.load(this.lastOptions);
19636 * Calls the specified function for each of the Records in the cache.
19637 * @param {Function} fn The function to call. The Record is passed as the first parameter.
19638 * Returning <em>false</em> aborts and exits the iteration.
19639 * @param {Object} scope (optional) The scope in which to call the function (defaults to the Record).
19641 each : function(fn, U){
19642 this.data.each(fn, U);
19646 * Gets all records modified since the last commit. Modified records are persisted across load operations
19647 * (e.g., during paging).
19648 * @return {Roo.data.Record[]} An array of Records containing outstanding modifications.
19650 getModifiedRecords : function(){
19651 return this.modified;
19655 createFilterFn : function(V, W, X){
19656 if(!W.exec){ // not a regex
19662 W = new RegExp((X === true ? '' : '^') + Roo.escapeRe(W), "i");
19664 return function(r){
19665 return W.test(r.data[V]);
19670 * Sums the value of <i>property</i> for each record between start and end and returns the result.
19671 * @param {String} property A field on your records
19672 * @param {Number} start The record index to start at (defaults to 0)
19673 * @param {Number} end The last record index to include (defaults to length - 1)
19674 * @return {Number} The sum
19676 sum : function(Y, Z, a){
19677 var rs = this.data.items, v = 0;
19679 a = (a || a === 0) ? a : rs.length-1;
19681 for(var i = Z; i <= a; i++){
19682 v += (rs[i].data[Y] || 0);
19688 * Filter the records by a specified property.
19689 * @param {String} field A field on your records
19690 * @param {String/RegExp} value Either a string that the field
19691 * should start with or a RegExp to test against the field
19692 * @param {Boolean} anyMatch True to match any part not just the beginning
19694 filter : function(b, c, d){
19695 var fn = this.createFilterFn(b, c, d);
19696 return fn ? this.filterBy(fn) : this.clearFilter();
19700 * Filter by a function. The specified function will be called with each
19701 * record in this data source. If the function returns true the record is included,
19702 * otherwise it is filtered.
19703 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
19704 * @param {Object} scope (optional) The scope of the function (defaults to this)
19706 filterBy : function(fn, e){
19707 this.snapshot = this.snapshot || this.data;
19708 this.data = this.queryBy(fn, e||this);
19709 this.fireEvent("datachanged", this);
19713 * Query the records by a specified property.
19714 * @param {String} field A field on your records
19715 * @param {String/RegExp} value Either a string that the field
19716 * should start with or a RegExp to test against the field
19717 * @param {Boolean} anyMatch True to match any part not just the beginning
19718 * @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
19720 query : function(g, h, j){
19721 var fn = this.createFilterFn(g, h, j);
19722 return fn ? this.queryBy(fn) : this.data.clone();
19726 * Query by a function. The specified function will be called with each
19727 * record in this data source. If the function returns true the record is included
19729 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
19730 * @param {Object} scope (optional) The scope of the function (defaults to this)
19731 @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
19733 queryBy : function(fn, k){
19734 var l = this.snapshot || this.data;
19735 return l.filterBy(fn, k||this);
19739 * Collects unique values for a particular dataIndex from this store.
19740 * @param {String} dataIndex The property to collect
19741 * @param {Boolean} allowNull (optional) Pass true to allow null, undefined or empty string values
19742 * @param {Boolean} bypassFilter (optional) Pass true to collect from all records, even ones which are filtered
19743 * @return {Array} An array of the unique values
19745 collect : function(m, n, q){
19746 var d = (q === true && this.snapshot) ?
19747 this.snapshot.items : this.data.items;
19748 var v, sv, r = [], l = {};
19749 for(var i = 0, len = d.length; i < len; i++){
19752 if((n || !Roo.isEmpty(v)) && !l[sv]){
19761 * Revert to a view of the Record cache with no filtering applied.
19762 * @param {Boolean} suppressEvent If true the filter is cleared silently without notifying listeners
19764 clearFilter : function(u){
19765 if(this.snapshot && this.snapshot != this.data){
19766 this.data = this.snapshot;
19767 delete this.snapshot;
19769 this.fireEvent("datachanged", this);
19775 afterEdit : function(w){
19776 if(this.modified.indexOf(w) == -1){
19777 this.modified.push(w);
19780 this.fireEvent("update", this, w, Roo.data.Record.EDIT);
19784 afterReject : function(x){
19785 this.modified.remove(x);
19786 this.fireEvent("update", this, x, Roo.data.Record.REJECT);
19790 afterCommit : function(y){
19791 this.modified.remove(y);
19792 this.fireEvent("update", this, y, Roo.data.Record.COMMIT);
19796 * Commit all Records with outstanding changes. To handle updates for changes, subscribe to the
19797 * Store's "update" event, and perform updating when the third parameter is Roo.data.Record.COMMIT.
19799 commitChanges : function(){
19800 var m = this.modified.slice(0);
19801 this.modified = [];
19802 for(var i = 0, len = m.length; i < len; i++){
19808 * Cancel outstanding changes on all changed records.
19810 rejectChanges : function(){
19811 var m = this.modified.slice(0);
19812 this.modified = [];
19813 for(var i = 0, len = m.length; i < len; i++){
19818 onMetaChange : function(z, AA, o){
19819 this.recordType = AA;
19820 this.fields = AA.prototype.fields;
19821 delete this.snapshot;
19822 this.sortInfo = z.sortInfo;
19823 this.modified = [];
19824 this.fireEvent('metachange', this, this.reader.meta);
19829 * Ext JS Library 1.1.1
19830 * Copyright(c) 2006-2007, Ext JS, LLC.
19832 * Originally Released Under LGPL - original licence link has changed is not relivant.
19835 * <script type="text/javascript">
19839 * @class Roo.data.SimpleStore
19840 * @extends Roo.data.Store
19841 * Small helper class to make creating Stores from Array data easier.
19842 * @cfg {Number} id The array index of the record id. Leave blank to auto generate ids.
19843 * @cfg {Array} fields An array of field definition objects, or field name strings.
19844 * @cfg {Array} data The multi-dimensional array of data
19846 * @param {Object} config
19848 Roo.data.SimpleStore = function(A){
19849 Roo.data.SimpleStore.superclass.constructor.call(this, {
19851 reader: new Roo.data.ArrayReader({
19854 Roo.data.Record.create(A.fields)
19856 proxy : new Roo.data.MemoryProxy(A.data)
19860 Roo.extend(Roo.data.SimpleStore, Roo.data.Store);
19863 * Ext JS Library 1.1.1
19864 * Copyright(c) 2006-2007, Ext JS, LLC.
19866 * Originally Released Under LGPL - original licence link has changed is not relivant.
19869 * <script type="text/javascript">
19874 * @extends Roo.data.Store
19875 * @class Roo.data.JsonStore
19876 * Small helper class to make creating Stores for JSON data easier. <br/>
19878 var store = new Roo.data.JsonStore({
19879 url: 'get-images.php',
19881 fields: ['name', 'url', {name:'size', type: 'float'}, {name:'lastmod', type:'date'}]
19884 * <b>Note: Although they are not listed, this class inherits all of the config options of Store,
19885 * JsonReader and HttpProxy (unless inline data is provided).</b>
19886 * @cfg {Array} fields An array of field definition objects, or field name strings.
19888 * @param {Object} config
19890 Roo.data.JsonStore = function(c){
19891 Roo.data.JsonStore.superclass.constructor.call(this, Roo.apply(c, {
19892 proxy: !c.data ? new Roo.data.HttpProxy({url: c.url}) : undefined,
19893 reader: new Roo.data.JsonReader(c, c.fields)
19896 Roo.extend(Roo.data.JsonStore, Roo.data.Store);
19899 * Ext JS Library 1.1.1
19900 * Copyright(c) 2006-2007, Ext JS, LLC.
19902 * Originally Released Under LGPL - original licence link has changed is not relivant.
19905 * <script type="text/javascript">
19909 Roo.data.Field = function(A){
19910 if(typeof A == "string"){
19914 Roo.apply(this, A);
19917 this.type = "auto";
19920 var st = Roo.data.SortTypes;
19921 // named sortTypes are supported, here we look them up
19922 if(typeof this.sortType == "string"){
19923 this.sortType = st[this.sortType];
19926 // set default sortType for strings and dates
19927 if(!this.sortType){
19930 this.sortType = st.asUCString;
19933 this.sortType = st.asDate;
19936 this.sortType = st.none;
19943 // prebuilt conversion function for this field, instead of
19944 // switching every time we're reading a value
19946 var cv, dateFormat = this.dateFormat;
19951 cv = function(v){ return v; };
19954 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
19958 return v !== undefined && v !== null && v !== '' ?
19959 parseInt(String(v).replace(B, ""), 10) : '';
19964 return v !== undefined && v !== null && v !== '' ?
19965 parseFloat(String(v).replace(B, ""), 10) : '';
19970 cv = function(v){ return v === true || v === "true" || v == 1; };
19977 if(v instanceof Date){
19981 if(dateFormat == "timestamp"){
19982 return new Date(v*1000);
19984 return Date.parseDate(v, dateFormat);
19986 var C = Date.parse(v);
19987 return C ? new Date(C) : null;
19997 Roo.data.Field.prototype = {
20006 * Ext JS Library 1.1.1
20007 * Copyright(c) 2006-2007, Ext JS, LLC.
20009 * Originally Released Under LGPL - original licence link has changed is not relivant.
20012 * <script type="text/javascript">
20015 // Base class for reading structured data from a data source. This class is intended to be
20016 // extended (see ArrayReader, JsonReader and XmlReader) and should not be created directly.
20019 * @class Roo.data.DataReader
20020 * Base class for reading structured data from a data source. This class is intended to be
20021 * extended (see {Roo.data.ArrayReader}, {Roo.data.JsonReader} and {Roo.data.XmlReader}) and should not be created directly.
20024 Roo.data.DataReader = function(A, B){
20028 this.recordType = B instanceof Array ?
20029 Roo.data.Record.create(B) : B;
20032 Roo.data.DataReader.prototype = {
20034 * Create an empty record
20035 * @param {Object} data (optional) - overlay some values
20036 * @return {Roo.data.Record} record created.
20038 newRow : function(d) {
20040 this.recordType.prototype.fields.each(function(c) {
20042 case 'int' : da[c.name] = 0; break;
20043 case 'date' : da[c.name] = new Date(); break;
20044 case 'float' : da[c.name] = 0.0; break;
20045 case 'boolean' : da[c.name] = false; break;
20046 default : da[c.name] = ""; break;
20050 return new this.recordType(Roo.apply(da, d));
20056 * Ext JS Library 1.1.1
20057 * Copyright(c) 2006-2007, Ext JS, LLC.
20059 * Originally Released Under LGPL - original licence link has changed is not relivant.
20062 * <script type="text/javascript">
20066 * @class Roo.data.DataProxy
20067 * @extends Roo.data.Observable
20068 * This class is an abstract base class for implementations which provide retrieval of
20069 * unformatted data objects.<br>
20071 * DataProxy implementations are usually used in conjunction with an implementation of Roo.data.DataReader
20072 * (of the appropriate type which knows how to parse the data object) to provide a block of
20073 * {@link Roo.data.Records} to an {@link Roo.data.Store}.<br>
20075 * Custom implementations must implement the load method as described in
20076 * {@link Roo.data.HttpProxy#load}.
20078 Roo.data.DataProxy = function(){
20081 * @event beforeload
20082 * Fires before a network request is made to retrieve a data object.
20083 * @param {Object} This DataProxy object.
20084 * @param {Object} params The params parameter to the load function.
20089 * Fires before the load method's callback is called.
20090 * @param {Object} This DataProxy object.
20091 * @param {Object} o The data object.
20092 * @param {Object} arg The callback argument object passed to the load function.
20096 * @event loadexception
20097 * Fires if an Exception occurs during data retrieval.
20098 * @param {Object} This DataProxy object.
20099 * @param {Object} o The data object.
20100 * @param {Object} arg The callback argument object passed to the load function.
20101 * @param {Object} e The Exception.
20103 loadexception : true
20105 Roo.data.DataProxy.superclass.constructor.call(this);
20108 Roo.extend(Roo.data.DataProxy, Roo.util.Observable);
20111 * @cfg {void} listeners (Not available) Constructor blocks listeners from being set
20116 * Ext JS Library 1.1.1
20117 * Copyright(c) 2006-2007, Ext JS, LLC.
20119 * Originally Released Under LGPL - original licence link has changed is not relivant.
20122 * <script type="text/javascript">
20125 * @class Roo.data.MemoryProxy
20126 * An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
20127 * to the Reader when its load method is called.
20129 * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
20131 Roo.data.MemoryProxy = function(A){
20136 Roo.data.MemoryProxy.superclass.constructor.call(this);
20140 Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
20142 * Load data from the requested source (in this case an in-memory
20143 * data object passed to the constructor), read the data object into
20144 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
20145 * process that block using the passed callback.
20146 * @param {Object} params This parameter is not used by the MemoryProxy class.
20147 * @param {Roo.data.DataReader} reader The Reader object which converts the data
20148 * object into a block of Roo.data.Records.
20149 * @param {Function} callback The function into which to pass the block of Roo.data.records.
20150 * The function must be passed <ul>
20151 * <li>The Record block object</li>
20152 * <li>The "arg" argument from the load function</li>
20153 * <li>A boolean success indicator</li>
20155 * @param {Object} scope The scope in which to call the callback
20156 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
20158 load : function(B, C, D, E, F){
20162 G = C.readRecords(this.data);
20164 this.fireEvent("loadexception", this, arg, null, e);
20165 callback.call(scope, null, arg, false);
20169 D.call(E, G, F, true);
20173 update : function(H, I){
20179 * Ext JS Library 1.1.1
20180 * Copyright(c) 2006-2007, Ext JS, LLC.
20182 * Originally Released Under LGPL - original licence link has changed is not relivant.
20185 * <script type="text/javascript">
20188 * @class Roo.data.HttpProxy
20189 * @extends Roo.data.DataProxy
20190 * An implementation of {@link Roo.data.DataProxy} that reads a data object from an {@link Roo.data.Connection} object
20191 * configured to reference a certain URL.<br><br>
20193 * <em>Note that this class cannot be used to retrieve data from a domain other than the domain
20194 * from which the running page was served.<br><br>
20196 * For cross-domain access to remote data, use an {@link Roo.data.ScriptTagProxy}.</em><br><br>
20198 * Be aware that to enable the browser to parse an XML document, the server must set
20199 * the Content-Type header in the HTTP response to "text/xml".
20201 * @param {Object} conn Connection config options to add to each request (e.g. {url: 'foo.php'} or
20202 * an {@link Roo.data.Connection} object. If a Connection config is passed, the singleton {@link Roo.Ajax} object
20203 * will be used to make the request.
20205 Roo.data.HttpProxy = function(A){
20206 Roo.data.HttpProxy.superclass.constructor.call(this);
20207 // is conn a conn config or a real conn?
20209 this.useAjax = !A || !A.events;
20213 Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
20214 // thse are take from connection...
20217 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
20220 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
20221 * extra parameters to each request made by this object. (defaults to undefined)
20224 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
20225 * to each request made by this object. (defaults to undefined)
20228 * @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)
20231 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
20234 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
20240 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
20244 * Return the {@link Roo.data.Connection} object being used by this Proxy.
20245 * @return {Connection} The Connection object. This object may be used to subscribe to events on
20246 * a finer-grained basis than the DataProxy events.
20248 getConnection : function(){
20249 return this.useAjax ? Roo.Ajax : this.conn;
20253 * Load data from the configured {@link Roo.data.Connection}, read the data object into
20254 * a block of Roo.data.Records using the passed {@link Roo.data.DataReader} implementation, and
20255 * process that block using the passed callback.
20256 * @param {Object} params An object containing properties which are to be used as HTTP parameters
20257 * for the request to the remote server.
20258 * @param {Roo.data.DataReader} reader The Reader object which converts the data
20259 * object into a block of Roo.data.Records.
20260 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
20261 * The function must be passed <ul>
20262 * <li>The Record block object</li>
20263 * <li>The "arg" argument from the load function</li>
20264 * <li>A boolean success indicator</li>
20266 * @param {Object} scope The scope in which to call the callback
20267 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
20269 load : function(B, C, D, E, F){
20270 if(this.fireEvent("beforeload", this, B) !== false){
20279 callback : this.loadResponse,
20283 Roo.applyIf(o, this.conn);
20284 if(this.activeRequest){
20285 Roo.Ajax.abort(this.activeRequest);
20288 this.activeRequest = Roo.Ajax.request(o);
20290 this.conn.request(o);
20293 D.call(E||this, null, F, false);
20298 loadResponse : function(o, G, H){
20299 delete this.activeRequest;
20301 this.fireEvent("loadexception", this, o, H);
20302 o.request.callback.call(o.request.scope, null, o.request.arg, false);
20307 I = o.reader.read(H);
20309 this.fireEvent("loadexception", this, o, response, e);
20310 o.request.callback.call(o.request.scope, null, o.request.arg, false);
20315 this.fireEvent("load", this, o, o.request.arg);
20316 o.request.callback.call(o.request.scope, I, o.request.arg, true);
20320 update : function(J){
20325 updateResponse : function(K){
20331 * Ext JS Library 1.1.1
20332 * Copyright(c) 2006-2007, Ext JS, LLC.
20334 * Originally Released Under LGPL - original licence link has changed is not relivant.
20337 * <script type="text/javascript">
20341 * @class Roo.data.ScriptTagProxy
20342 * An implementation of Roo.data.DataProxy that reads a data object from a URL which may be in a domain
20343 * other than the originating domain of the running page.<br><br>
20345 * <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
20346 * of the running page, you must use this class, rather than DataProxy.</em><br><br>
20348 * The content passed back from a server resource requested by a ScriptTagProxy is executable JavaScript
20349 * source code that is used as the source inside a <script> tag.<br><br>
20351 * In order for the browser to process the returned data, the server must wrap the data object
20352 * with a call to a callback function, the name of which is passed as a parameter by the ScriptTagProxy.
20353 * Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy
20354 * depending on whether the callback name was passed:
20357 boolean scriptTag = false;
20358 String cb = request.getParameter("callback");
20361 response.setContentType("text/javascript");
20363 response.setContentType("application/x-json");
20365 Writer out = response.getWriter();
20367 out.write(cb + "(");
20369 out.print(dataBlock.toJsonString());
20376 * @param {Object} config A configuration object.
20378 Roo.data.ScriptTagProxy = function(A){
20379 Roo.data.ScriptTagProxy.superclass.constructor.call(this);
20380 Roo.apply(this, A);
20381 this.head = document.getElementsByTagName("head")[0];
20384 Roo.data.ScriptTagProxy.TRANS_ID = 1000;
20386 Roo.extend(Roo.data.ScriptTagProxy, Roo.data.DataProxy, {
20388 * @cfg {String} url The URL from which to request the data object.
20391 * @cfg {Number} timeout (Optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
20395 * @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells
20396 * the server the name of the callback function set up by the load call to process the returned data object.
20397 * Defaults to "callback".<p>The server-side processing must read this parameter value, and generate
20398 * javascript output which calls this named function passing the data object as its only parameter.
20400 callbackParam : "callback",
20402 * @cfg {Boolean} nocache (Optional) Defaults to true. Disable cacheing by adding a unique parameter
20403 * name to the request.
20408 * Load data from the configured URL, read the data object into
20409 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
20410 * process that block using the passed callback.
20411 * @param {Object} params An object containing properties which are to be used as HTTP parameters
20412 * for the request to the remote server.
20413 * @param {Roo.data.DataReader} reader The Reader object which converts the data
20414 * object into a block of Roo.data.Records.
20415 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
20416 * The function must be passed <ul>
20417 * <li>The Record block object</li>
20418 * <li>The "arg" argument from the load function</li>
20419 * <li>A boolean success indicator</li>
20421 * @param {Object} scope The scope in which to call the callback
20422 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
20424 load : function(B, C, D, E, F){
20425 if(this.fireEvent("beforeload", this, B) !== false){
20427 var p = Roo.urlEncode(Roo.apply(B, this.extraParams));
20429 var url = this.url;
20430 url += (url.indexOf("?") != -1 ? "&" : "?") + p;
20432 url += "&_dc=" + (new Date().getTime());
20434 var transId = ++Roo.data.ScriptTagProxy.TRANS_ID;
20437 cb : "stcCallback"+transId,
20438 scriptId : "stcScript"+transId,
20448 window[trans.cb] = function(o){
20449 conn.handleResponse(o, trans);
20452 url += String.format("&{0}={1}", this.callbackParam, trans.cb);
20454 if(this.autoAbort !== false){
20459 trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
20461 var script = document.createElement("script");
20462 script.setAttribute("src", url);
20463 script.setAttribute("type", "text/javascript");
20464 script.setAttribute("id", trans.scriptId);
20465 this.head.appendChild(script);
20467 this.trans = trans;
20469 D.call(E||this, null, F, false);
20474 isLoading : function(){
20475 return this.trans ? true : false;
20479 * Abort the current server request.
20481 abort : function(){
20482 if(this.isLoading()){
20483 this.destroyTrans(this.trans);
20488 destroyTrans : function(G, H){
20489 this.head.removeChild(document.getElementById(G.scriptId));
20490 clearTimeout(G.timeoutId);
20492 window[G.cb] = undefined;
20494 delete window[G.cb];
20497 // if hasn't been loaded, wait for load to remove it to prevent script error
20498 window[G.cb] = function(){
20499 window[G.cb] = undefined;
20501 delete window[G.cb];
20508 handleResponse : function(o, I){
20509 this.trans = false;
20510 this.destroyTrans(I, true);
20513 J = I.reader.readRecords(o);
20515 this.fireEvent("loadexception", this, o, trans.arg, e);
20516 trans.callback.call(trans.scope||window, null, trans.arg, false);
20520 this.fireEvent("load", this, o, I.arg);
20521 I.callback.call(I.scope||window, J, I.arg, true);
20525 handleFailure : function(K){
20526 this.trans = false;
20527 this.destroyTrans(K, false);
20528 this.fireEvent("loadexception", this, null, K.arg);
20529 K.callback.call(K.scope||window, null, K.arg, false);
20534 * Ext JS Library 1.1.1
20535 * Copyright(c) 2006-2007, Ext JS, LLC.
20537 * Originally Released Under LGPL - original licence link has changed is not relivant.
20540 * <script type="text/javascript">
20544 * @class Roo.data.JsonReader
20545 * @extends Roo.data.DataReader
20546 * Data reader class to create an Array of Roo.data.Record objects from a JSON response
20547 * based on mappings in a provided Roo.data.Record constructor.
20551 var RecordDef = Roo.data.Record.create([
20552 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
20553 {name: 'occupation'} // This field will use "occupation" as the mapping.
20555 var myReader = new Roo.data.JsonReader({
20556 totalProperty: "results", // The property which contains the total dataset size (optional)
20557 root: "rows", // The property which contains an Array of row objects
20558 id: "id" // The property within each row object that provides an ID for the record (optional)
20562 * This would consume a JSON file like this:
20564 { 'results': 2, 'rows': [
20565 { 'id': 1, 'name': 'Bill', occupation: 'Gardener' },
20566 { 'id': 2, 'name': 'Ben', occupation: 'Horticulturalist' } ]
20569 * @cfg {String} totalProperty Name of the property from which to retrieve the total number of records
20570 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
20571 * paged from the remote server.
20572 * @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
20573 * @cfg {String} root name of the property which contains the Array of row objects.
20574 * @cfg {String} id Name of the property within a row object that contains a record identifier value.
20576 * Create a new JsonReader
20577 * @param {Object} meta Metadata configuration options
20578 * @param {Object} recordType Either an Array of field definition objects,
20579 * or an {@link Roo.data.Record} object created using {@link Roo.data.Record#create}.
20581 Roo.data.JsonReader = function(A, B){
20584 // set some defaults:
20586 totalProperty: 'total',
20587 successProperty : 'success',
20592 Roo.data.JsonReader.superclass.constructor.call(this, A, B||A.fields);
20594 Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
20596 * This method is only used by a DataProxy which has retrieved data from a remote server.
20597 * @param {Object} response The XHR object which contains the JSON data in its responseText.
20598 * @return {Object} data A data block which is used by an Roo.data.Store object as
20599 * a cache of Roo.data.Records.
20601 read : function(C){
20602 var D = C.responseText;
20604 var o = eval("("+D+")");
20606 throw {message: "JsonReader.read: Json object not found"};
20611 this.meta = o.metaData;
20612 this.recordType = Roo.data.Record.create(o.metaData.fields);
20613 this.onMetaChange(this.meta, this.recordType, o);
20615 return this.readRecords(o);
20618 // private function a store will implement
20619 onMetaChange : function(E, F, o){
20626 simpleAccess: function(G, H) {
20633 getJsonAccessor: function(){
20635 return function(I) {
20637 return (re.test(I))
20638 ? new Function("obj", "return obj." + I)
20643 return Roo.emptyFn;
20648 * Create a data block containing Roo.data.Records from an XML document.
20649 * @param {Object} o An object which contains an Array of row objects in the property specified
20650 * in the config as 'root, and optionally a property, specified in the config as 'totalProperty'
20651 * which contains the total size of the dataset.
20652 * @return {Object} data A data block which is used by an Roo.data.Store object as
20653 * a cache of Roo.data.Records.
20655 readRecords : function(o){
20657 * After any data loads, the raw JSON data is available for further custom processing.
20661 var s = this.meta, I = this.recordType,
20662 f = I.prototype.fields, fi = f.items, fl = f.length;
20664 // Generate extraction functions for the totalProperty, the root, the id, and for each field
20666 if(s.totalProperty) {
20667 this.getTotal = this.getJsonAccessor(s.totalProperty);
20669 if(s.successProperty) {
20670 this.getSuccess = this.getJsonAccessor(s.successProperty);
20673 this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
20675 var g = this.getJsonAccessor(s.id);
20676 this.getId = function(N) {
20678 return (r === undefined || r === "") ? null : r;
20681 this.getId = function(){return null;};
20685 for(var i = 0; i < fl; i++){
20687 var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
20688 this.ef[i] = this.getJsonAccessor(map);
20692 var J = this.getRoot(o), c = J.length, K = c, L = true;
20693 if(s.totalProperty){
20694 var v = parseInt(this.getTotal(o), 10);
20699 if(s.successProperty){
20700 var v = this.getSuccess(o);
20701 if(v === false || v === 'false'){
20706 for(var i = 0; i < c; i++){
20709 var id = this.getId(n);
20710 for(var j = 0; j < fl; j++){
20712 var v = this.ef[j](n);
20713 values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
20715 var record = new I(values, id);
20728 * Ext JS Library 1.1.1
20729 * Copyright(c) 2006-2007, Ext JS, LLC.
20731 * Originally Released Under LGPL - original licence link has changed is not relivant.
20734 * <script type="text/javascript">
20738 * @class Roo.data.XmlReader
20739 * @extends Roo.data.DataReader
20740 * Data reader class to create an Array of {@link Roo.data.Record} objects from an XML document
20741 * based on mappings in a provided Roo.data.Record constructor.<br><br>
20743 * <em>Note that in order for the browser to parse a returned XML document, the Content-Type
20744 * header in the HTTP response must be set to "text/xml".</em>
20748 var RecordDef = Roo.data.Record.create([
20749 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
20750 {name: 'occupation'} // This field will use "occupation" as the mapping.
20752 var myReader = new Roo.data.XmlReader({
20753 totalRecords: "results", // The element which contains the total dataset size (optional)
20754 record: "row", // The repeated element which contains row information
20755 id: "id" // The element within the row that provides an ID for the record (optional)
20759 * This would consume an XML file like this:
20763 <results>2</results>
20766 <name>Bill</name>
20767 <occupation>Gardener</occupation>
20771 <name>Ben</name>
20772 <occupation>Horticulturalist</occupation>
20776 * @cfg {String} totalRecords The DomQuery path from which to retrieve the total number of records
20777 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
20778 * paged from the remote server.
20779 * @cfg {String} record The DomQuery path to the repeated element which contains record information.
20780 * @cfg {String} success The DomQuery path to the success attribute used by forms.
20781 * @cfg {String} id The DomQuery path relative from the record element to the element that contains
20782 * a record identifier value.
20784 * Create a new XmlReader
20785 * @param {Object} meta Metadata configuration options
20786 * @param {Mixed} recordType The definition of the data record type to produce. This can be either a valid
20787 * Record subclass created with {@link Roo.data.Record#create}, or an array of objects with which to call
20788 * Roo.data.Record.create. See the {@link Roo.data.Record} class for more details.
20790 Roo.data.XmlReader = function(A, B){
20792 Roo.data.XmlReader.superclass.constructor.call(this, A, B||A.fields);
20794 Roo.extend(Roo.data.XmlReader, Roo.data.DataReader, {
20796 * This method is only used by a DataProxy which has retrieved data from a remote server.
20797 * @param {Object} response The XHR object which contains the parsed XML document. The response is expected
20798 * to contain a method called 'responseXML' that returns an XML document object.
20799 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
20800 * a cache of Roo.data.Records.
20802 read : function(C){
20803 var D = C.responseXML;
20805 throw {message: "XmlReader.read: XML Document not available"};
20807 return this.readRecords(D);
20811 * Create a data block containing Roo.data.Records from an XML document.
20812 * @param {Object} doc A parsed XML document.
20813 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
20814 * a cache of Roo.data.Records.
20816 readRecords : function(E){
20818 * After any data loads/reads, the raw XML Document is available for further custom processing.
20819 * @type XMLDocument
20822 var F = E.documentElement || E;
20823 var q = Roo.DomQuery;
20824 var G = this.recordType, H = G.prototype.fields;
20825 var I = this.meta.id;
20826 var J = 0, K = true;
20827 if(this.meta.totalRecords){
20828 J = q.selectNumber(this.meta.totalRecords, F, 0);
20831 if(this.meta.success){
20832 var sv = q.selectValue(this.meta.success, F, true);
20833 K = sv !== false && sv !== 'false';
20836 var ns = q.select(this.meta.record, F);
20837 for(var i = 0, len = ns.length; i < len; i++) {
20840 var id = I ? q.selectValue(I, n) : undefined;
20841 for(var j = 0, jlen = H.length; j < jlen; j++){
20842 var f = H.items[j];
20843 var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
20845 values[f.name] = v;
20847 var record = new G(values, id);
20849 L[L.length] = record;
20855 totalRecords : J || L.length
20861 * Ext JS Library 1.1.1
20862 * Copyright(c) 2006-2007, Ext JS, LLC.
20864 * Originally Released Under LGPL - original licence link has changed is not relivant.
20867 * <script type="text/javascript">
20871 * @class Roo.data.ArrayReader
20872 * @extends Roo.data.DataReader
20873 * Data reader class to create an Array of Roo.data.Record objects from an Array.
20874 * Each element of that Array represents a row of data fields. The
20875 * fields are pulled into a Record object using as a subscript, the <em>mapping</em> property
20876 * of the field definition if it exists, or the field's ordinal position in the definition.<br>
20880 var RecordDef = Roo.data.Record.create([
20881 {name: 'name', mapping: 1}, // "mapping" only needed if an "id" field is present which
20882 {name: 'occupation', mapping: 2} // precludes using the ordinal position as the index.
20884 var myReader = new Roo.data.ArrayReader({
20885 id: 0 // The subscript within row Array that provides an ID for the Record (optional)
20889 * This would consume an Array like this:
20891 [ [1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist'] ]
20893 * @cfg {String} id (optional) The subscript within row Array that provides an ID for the Record
20895 * Create a new JsonReader
20896 * @param {Object} meta Metadata configuration options.
20897 * @param {Object} recordType Either an Array of field definition objects
20898 * as specified to {@link Roo.data.Record#create},
20899 * or an {@link Roo.data.Record} object
20900 * created using {@link Roo.data.Record#create}.
20902 Roo.data.ArrayReader = function(A, B){
20903 Roo.data.ArrayReader.superclass.constructor.call(this, A, B);
20906 Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
20908 * Create a data block containing Roo.data.Records from an XML document.
20909 * @param {Object} o An Array of row objects which represents the dataset.
20910 * @return {Object} data A data block which is used by an Roo.data.Store object as
20911 * a cache of Roo.data.Records.
20913 readRecords : function(o){
20914 var C = this.meta ? this.meta.id : null;
20915 var D = this.recordType, E = D.prototype.fields;
20918 for(var i = 0; i < G.length; i++){
20921 var id = ((C || C === 0) && n[C] !== undefined && n[C] !== "" ? n[C] : null);
20922 for(var j = 0, jlen = E.length; j < jlen; j++){
20923 var f = E.items[j];
20924 var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
20925 var v = n[k] !== undefined ? n[k] : f.defaultValue;
20927 values[f.name] = v;
20929 var record = new D(values, id);
20931 F[F.length] = record;
20935 totalRecords : F.length
20941 * Ext JS Library 1.1.1
20942 * Copyright(c) 2006-2007, Ext JS, LLC.
20944 * Originally Released Under LGPL - original licence link has changed is not relivant.
20947 * <script type="text/javascript">
20952 * @class Roo.data.Tree
20953 * @extends Roo.util.Observable
20954 * Represents a tree data structure and bubbles all the events for its nodes. The nodes
20955 * in the tree have most standard DOM functionality.
20957 * @param {Node} root (optional) The root node
20959 Roo.data.Tree = function(A){
20960 this.nodeHash = {};
20962 * The root node for this tree
20967 this.setRootNode(A);
20973 * Fires when a new child node is appended to a node in this tree.
20974 * @param {Tree} tree The owner tree
20975 * @param {Node} parent The parent node
20976 * @param {Node} node The newly appended node
20977 * @param {Number} index The index of the newly appended node
20982 * Fires when a child node is removed from a node in this tree.
20983 * @param {Tree} tree The owner tree
20984 * @param {Node} parent The parent node
20985 * @param {Node} node The child node removed
20990 * Fires when a node is moved to a new location in the tree
20991 * @param {Tree} tree The owner tree
20992 * @param {Node} node The node moved
20993 * @param {Node} oldParent The old parent of this node
20994 * @param {Node} newParent The new parent of this node
20995 * @param {Number} index The index it was moved to
21000 * Fires when a new child node is inserted in a node in this tree.
21001 * @param {Tree} tree The owner tree
21002 * @param {Node} parent The parent node
21003 * @param {Node} node The child node inserted
21004 * @param {Node} refNode The child node the node was inserted before
21008 * @event beforeappend
21009 * Fires before a new child is appended to a node in this tree, return false to cancel the append.
21010 * @param {Tree} tree The owner tree
21011 * @param {Node} parent The parent node
21012 * @param {Node} node The child node to be appended
21014 "beforeappend" : true,
21016 * @event beforeremove
21017 * Fires before a child is removed from a node in this tree, return false to cancel the remove.
21018 * @param {Tree} tree The owner tree
21019 * @param {Node} parent The parent node
21020 * @param {Node} node The child node to be removed
21022 "beforeremove" : true,
21024 * @event beforemove
21025 * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
21026 * @param {Tree} tree The owner tree
21027 * @param {Node} node The node being moved
21028 * @param {Node} oldParent The parent of the node
21029 * @param {Node} newParent The new parent the node is moving to
21030 * @param {Number} index The index it is being moved to
21032 "beforemove" : true,
21034 * @event beforeinsert
21035 * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
21036 * @param {Tree} tree The owner tree
21037 * @param {Node} parent The parent node
21038 * @param {Node} node The child node to be inserted
21039 * @param {Node} refNode The child node the node is being inserted before
21041 "beforeinsert" : true
21044 Roo.data.Tree.superclass.constructor.call(this);
21047 Roo.extend(Roo.data.Tree, Roo.util.Observable, {
21048 pathSeparator: "/",
21050 proxyNodeEvent : function(){
21051 return this.fireEvent.apply(this, arguments);
21055 * Returns the root node for this tree.
21058 getRootNode : function(){
21063 * Sets the root node for this tree.
21064 * @param {Node} node
21067 setRootNode : function(B){
21069 B.ownerTree = this;
21071 this.registerNode(B);
21076 * Gets a node in this tree by its id.
21077 * @param {String} id
21080 getNodeById : function(id){
21081 return this.nodeHash[id];
21084 registerNode : function(C){
21085 this.nodeHash[C.id] = C;
21088 unregisterNode : function(D){
21089 delete this.nodeHash[D.id];
21092 toString : function(){
21093 return "[Tree"+(this.id?" "+this.id:"")+"]";
21098 * @class Roo.data.Node
21099 * @extends Roo.util.Observable
21100 * @cfg {Boolean} leaf true if this node is a leaf and does not have children
21101 * @cfg {String} id The id for this node. If one is not specified, one is generated.
21103 * @param {Object} attributes The attributes/config for the node
21105 Roo.data.Node = function(E){
21107 * The attributes supplied for the node. You can use this property to access any custom attributes you supplied.
21110 this.attributes = E || {};
21111 this.leaf = this.attributes.leaf;
21113 * The node id. @type String
21115 this.id = this.attributes.id;
21117 this.id = Roo.id(null, "ynode-");
21118 this.attributes.id = this.id;
21122 * All child nodes of this node. @type Array
21124 this.childNodes = [];
21125 if(!this.childNodes.indexOf){ // indexOf is a must
21126 this.childNodes.indexOf = function(o){
21127 for(var i = 0, len = this.length; i < len; i++){
21128 if(this[i] == o) return i;
21135 * The parent node for this node. @type Node
21137 this.parentNode = null;
21139 * The first direct child node of this node, or null if this node has no child nodes. @type Node
21141 this.firstChild = null;
21143 * The last direct child node of this node, or null if this node has no child nodes. @type Node
21145 this.lastChild = null;
21147 * The node immediately preceding this node in the tree, or null if there is no sibling node. @type Node
21149 this.previousSibling = null;
21151 * The node immediately following this node in the tree, or null if there is no sibling node. @type Node
21153 this.nextSibling = null;
21158 * Fires when a new child node is appended
21159 * @param {Tree} tree The owner tree
21160 * @param {Node} this This node
21161 * @param {Node} node The newly appended node
21162 * @param {Number} index The index of the newly appended node
21167 * Fires when a child node is removed
21168 * @param {Tree} tree The owner tree
21169 * @param {Node} this This node
21170 * @param {Node} node The removed node
21175 * Fires when this node is moved to a new location in the tree
21176 * @param {Tree} tree The owner tree
21177 * @param {Node} this This node
21178 * @param {Node} oldParent The old parent of this node
21179 * @param {Node} newParent The new parent of this node
21180 * @param {Number} index The index it was moved to
21185 * Fires when a new child node is inserted.
21186 * @param {Tree} tree The owner tree
21187 * @param {Node} this This node
21188 * @param {Node} node The child node inserted
21189 * @param {Node} refNode The child node the node was inserted before
21193 * @event beforeappend
21194 * Fires before a new child is appended, return false to cancel the append.
21195 * @param {Tree} tree The owner tree
21196 * @param {Node} this This node
21197 * @param {Node} node The child node to be appended
21199 "beforeappend" : true,
21201 * @event beforeremove
21202 * Fires before a child is removed, return false to cancel the remove.
21203 * @param {Tree} tree The owner tree
21204 * @param {Node} this This node
21205 * @param {Node} node The child node to be removed
21207 "beforeremove" : true,
21209 * @event beforemove
21210 * Fires before this node is moved to a new location in the tree. Return false to cancel the move.
21211 * @param {Tree} tree The owner tree
21212 * @param {Node} this This node
21213 * @param {Node} oldParent The parent of this node
21214 * @param {Node} newParent The new parent this node is moving to
21215 * @param {Number} index The index it is being moved to
21217 "beforemove" : true,
21219 * @event beforeinsert
21220 * Fires before a new child is inserted, return false to cancel the insert.
21221 * @param {Tree} tree The owner tree
21222 * @param {Node} this This node
21223 * @param {Node} node The child node to be inserted
21224 * @param {Node} refNode The child node the node is being inserted before
21226 "beforeinsert" : true
21228 this.listeners = this.attributes.listeners;
21229 Roo.data.Node.superclass.constructor.call(this);
21232 Roo.extend(Roo.data.Node, Roo.util.Observable, {
21233 fireEvent : function(F){
21234 // first do standard event for this node
21235 if(Roo.data.Node.superclass.fireEvent.apply(this, arguments) === false){
21238 // then bubble it up to the tree if the event wasn't cancelled
21239 var ot = this.getOwnerTree();
21241 if(ot.proxyNodeEvent.apply(ot, arguments) === false){
21249 * Returns true if this node is a leaf
21250 * @return {Boolean}
21252 isLeaf : function(){
21253 return this.leaf === true;
21257 setFirstChild : function(G){
21258 this.firstChild = G;
21262 setLastChild : function(H){
21263 this.lastChild = H;
21268 * Returns true if this node is the last child of its parent
21269 * @return {Boolean}
21271 isLast : function(){
21272 return (!this.parentNode ? true : this.parentNode.lastChild == this);
21276 * Returns true if this node is the first child of its parent
21277 * @return {Boolean}
21279 isFirst : function(){
21280 return (!this.parentNode ? true : this.parentNode.firstChild == this);
21283 hasChildNodes : function(){
21284 return !this.isLeaf() && this.childNodes.length > 0;
21288 * Insert node(s) as the last child node of this node.
21289 * @param {Node/Array} node The node or Array of nodes to append
21290 * @return {Node} The appended node if single append, or null if an array was passed
21292 appendChild : function(I){
21294 if(I instanceof Array){
21296 }else if(arguments.length > 1){
21299 // if passed an array or multiple args do them one by one
21301 for(var i = 0, len = J.length; i < len; i++) {
21302 this.appendChild(J[i]);
21305 if(this.fireEvent("beforeappend", this.ownerTree, this, I) === false){
21308 var index = this.childNodes.length;
21309 var oldParent = I.parentNode;
21310 // it's a move, make sure we move it cleanly
21312 if(I.fireEvent("beforemove", I.getOwnerTree(), I, oldParent, this, index) === false){
21316 oldParent.removeChild(I);
21319 index = this.childNodes.length;
21321 this.setFirstChild(I);
21324 this.childNodes.push(I);
21325 I.parentNode = this;
21326 var ps = this.childNodes[index-1];
21328 I.previousSibling = ps;
21329 ps.nextSibling = I;
21331 I.previousSibling = null;
21334 I.nextSibling = null;
21335 this.setLastChild(I);
21336 I.setOwnerTree(this.getOwnerTree());
21337 this.fireEvent("append", this.ownerTree, this, I, index);
21339 I.fireEvent("move", this.ownerTree, I, oldParent, this, index);
21346 * Removes a child node from this node.
21347 * @param {Node} node The node to remove
21348 * @return {Node} The removed node
21350 removeChild : function(K){
21351 var L = this.childNodes.indexOf(K);
21355 if(this.fireEvent("beforeremove", this.ownerTree, this, K) === false){
21360 // remove it from childNodes collection
21361 this.childNodes.splice(L, 1);
21364 if(K.previousSibling){
21365 K.previousSibling.nextSibling = K.nextSibling;
21368 K.nextSibling.previousSibling = K.previousSibling;
21371 // update child refs
21372 if(this.firstChild == K){
21373 this.setFirstChild(K.nextSibling);
21375 if(this.lastChild == K){
21376 this.setLastChild(K.previousSibling);
21380 K.setOwnerTree(null);
21381 // clear any references from the node
21382 K.parentNode = null;
21383 K.previousSibling = null;
21384 K.nextSibling = null;
21385 this.fireEvent("remove", this.ownerTree, this, K);
21390 * Inserts the first node before the second node in this nodes childNodes collection.
21391 * @param {Node} node The node to insert
21392 * @param {Node} refNode The node to insert before (if null the node is appended)
21393 * @return {Node} The inserted node
21395 insertBefore : function(M, N){
21396 if(!N){ // like standard Dom, refNode can be null for append
21397 return this.appendChild(M);
21404 if(this.fireEvent("beforeinsert", this.ownerTree, this, M, N) === false){
21407 var O = this.childNodes.indexOf(N);
21408 var P = M.parentNode;
21411 // when moving internally, indexes will change after remove
21412 if(P == this && this.childNodes.indexOf(M) < O){
21416 // it's a move, make sure we move it cleanly
21418 if(M.fireEvent("beforemove", M.getOwnerTree(), M, P, this, O, N) === false){
21425 this.setFirstChild(M);
21428 this.childNodes.splice(Q, 0, M);
21429 M.parentNode = this;
21430 var ps = this.childNodes[Q-1];
21432 M.previousSibling = ps;
21433 ps.nextSibling = M;
21435 M.previousSibling = null;
21439 N.previousSibling = M;
21440 M.setOwnerTree(this.getOwnerTree());
21441 this.fireEvent("insert", this.ownerTree, this, M, N);
21443 M.fireEvent("move", this.ownerTree, M, P, this, Q, N);
21449 * Returns the child node at the specified index.
21450 * @param {Number} index
21453 item : function(R){
21454 return this.childNodes[R];
21458 * Replaces one child node in this node with another.
21459 * @param {Node} newChild The replacement node
21460 * @param {Node} oldChild The node to replace
21461 * @return {Node} The replaced node
21463 replaceChild : function(S, T){
21464 this.insertBefore(S, T);
21465 this.removeChild(T);
21470 * Returns the index of a child node
21471 * @param {Node} node
21472 * @return {Number} The index of the node or -1 if it was not found
21474 indexOf : function(U){
21475 return this.childNodes.indexOf(U);
21479 * Returns the tree this node is in.
21482 getOwnerTree : function(){
21483 // if it doesn't have one, look for one
21484 if(!this.ownerTree){
21488 this.ownerTree = p.ownerTree;
21495 return this.ownerTree;
21499 * Returns depth of this node (the root node has a depth of 0)
21502 getDepth : function(){
21505 while(p.parentNode){
21513 setOwnerTree : function(W){
21514 // if it's move, we need to update everyone
21515 if(W != this.ownerTree){
21516 if(this.ownerTree){
21517 this.ownerTree.unregisterNode(this);
21520 this.ownerTree = W;
21521 var cs = this.childNodes;
21522 for(var i = 0, len = cs.length; i < len; i++) {
21523 cs[i].setOwnerTree(W);
21526 W.registerNode(this);
21532 * Returns the path for this node. The path can be used to expand or select this node programmatically.
21533 * @param {String} attr (optional) The attr to use for the path (defaults to the node's id)
21534 * @return {String} The path
21536 getPath : function(X){
21538 var p = this.parentNode;
21539 var b = [this.attributes[X]];
21541 b.unshift(p.attributes[X]);
21544 var Y = this.getOwnerTree().pathSeparator;
21545 return Y + b.join(Y);
21549 * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
21550 * function call will be the scope provided or the current node. The arguments to the function
21551 * will be the args provided or the current node. If the function returns false at any point,
21552 * the bubble is stopped.
21553 * @param {Function} fn The function to call
21554 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21555 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21557 bubble : function(fn, Z, a){
21560 if(fn.call(Z || p, a || p) === false){
21569 * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
21570 * function call will be the scope provided or the current node. The arguments to the function
21571 * will be the args provided or the current node. If the function returns false at any point,
21572 * the cascade is stopped on that branch.
21573 * @param {Function} fn The function to call
21574 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21575 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21577 cascade : function(fn, c, d){
21578 if(fn.call(c || this, d || this) !== false){
21579 var cs = this.childNodes;
21580 for(var i = 0, len = cs.length; i < len; i++) {
21581 cs[i].cascade(fn, c, d);
21587 * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of
21588 * function call will be the scope provided or the current node. The arguments to the function
21589 * will be the args provided or the current node. If the function returns false at any point,
21590 * the iteration stops.
21591 * @param {Function} fn The function to call
21592 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21593 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21595 eachChild : function(fn, e, f){
21596 var cs = this.childNodes;
21597 for(var i = 0, len = cs.length; i < len; i++) {
21598 if(fn.call(e || this, f || cs[i]) === false){
21605 * Finds the first child that has the attribute with the specified value.
21606 * @param {String} attribute The attribute name
21607 * @param {Mixed} value The value to search for
21608 * @return {Node} The found child or null if none was found
21610 findChild : function(g, h){
21611 var cs = this.childNodes;
21612 for(var i = 0, len = cs.length; i < len; i++) {
21613 if(cs[i].attributes[g] == h){
21621 * Finds the first child by a custom function. The child matches if the function passed
21623 * @param {Function} fn
21624 * @param {Object} scope (optional)
21625 * @return {Node} The found child or null if none was found
21627 findChildBy : function(fn, j){
21628 var cs = this.childNodes;
21629 for(var i = 0, len = cs.length; i < len; i++) {
21630 if(fn.call(j||cs[i], cs[i]) === true){
21638 * Sorts this nodes children using the supplied sort function
21639 * @param {Function} fn
21640 * @param {Object} scope (optional)
21642 sort : function(fn, k){
21643 var cs = this.childNodes;
21646 var sortFn = k ? function(){fn.apply(k, arguments);} : fn;
21648 for(var i = 0; i < l; i++){
21650 n.previousSibling = cs[i-1];
21651 n.nextSibling = cs[i+1];
21653 this.setFirstChild(n);
21656 this.setLastChild(n);
21663 * Returns true if this node is an ancestor (at any point) of the passed node.
21664 * @param {Node} node
21665 * @return {Boolean}
21667 contains : function(m){
21668 return m.isAncestor(this);
21672 * Returns true if the passed node is an ancestor (at any point) of this node.
21673 * @param {Node} node
21674 * @return {Boolean}
21676 isAncestor : function(o){
21677 var p = this.parentNode;
21688 toString : function(){
21689 return "[Node"+(this.id?" "+this.id:"")+"]";
21694 * Ext JS Library 1.1.1
21695 * Copyright(c) 2006-2007, Ext JS, LLC.
21697 * Originally Released Under LGPL - original licence link has changed is not relivant.
21700 * <script type="text/javascript">
21705 * @class Roo.ComponentMgr
21706 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
21709 Roo.ComponentMgr = function(){
21710 var A = new Roo.util.MixedCollection();
21714 * Registers a component.
21715 * @param {Roo.Component} c The component
21717 register : function(c){
21722 * Unregisters a component.
21723 * @param {Roo.Component} c The component
21725 unregister : function(c){
21730 * Returns a component by id
21731 * @param {String} id The component id
21733 get : function(id){
21738 * Registers a function that will be called when a specified component is added to ComponentMgr
21739 * @param {String} id The component id
21740 * @param {Funtction} fn The callback function
21741 * @param {Object} scope The scope of the callback
21743 onAvailable : function(id, fn, C){
21744 A.on("add", function(D, o){
21746 fn.call(C || o, o);
21747 A.un("add", fn, C);
21755 * Ext JS Library 1.1.1
21756 * Copyright(c) 2006-2007, Ext JS, LLC.
21758 * Originally Released Under LGPL - original licence link has changed is not relivant.
21761 * <script type="text/javascript">
21765 * @class Roo.Component
21766 * @extends Roo.util.Observable
21767 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
21768 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
21769 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
21770 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
21771 * All visual components (widgets) that require rendering into a layout should subclass Component.
21773 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
21774 * element and its id used as the component id. If a string is passed, it is assumed to be the id of an existing element
21775 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
21777 Roo.Component = function(A){
21779 if(A.tagName || A.dom || typeof A == "string"){ // element object
21780 A = {el: A, id: A.id || A};
21783 this.initialConfig = A;
21785 Roo.apply(this, A);
21789 * Fires after the component is disabled.
21790 * @param {Roo.Component} this
21795 * Fires after the component is enabled.
21796 * @param {Roo.Component} this
21800 * @event beforeshow
21801 * Fires before the component is shown. Return false to stop the show.
21802 * @param {Roo.Component} this
21807 * Fires after the component is shown.
21808 * @param {Roo.Component} this
21812 * @event beforehide
21813 * Fires before the component is hidden. Return false to stop the hide.
21814 * @param {Roo.Component} this
21819 * Fires after the component is hidden.
21820 * @param {Roo.Component} this
21824 * @event beforerender
21825 * Fires before the component is rendered. Return false to stop the render.
21826 * @param {Roo.Component} this
21828 beforerender : true,
21831 * Fires after the component is rendered.
21832 * @param {Roo.Component} this
21836 * @event beforedestroy
21837 * Fires before the component is destroyed. Return false to stop the destroy.
21838 * @param {Roo.Component} this
21840 beforedestroy : true,
21843 * Fires after the component is destroyed.
21844 * @param {Roo.Component} this
21849 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
21852 Roo.ComponentMgr.register(this);
21853 Roo.Component.superclass.constructor.call(this);
21854 this.initComponent();
21855 if(this.renderTo){ // not supported by all components yet. use at your own risk!
21856 this.render(this.renderTo);
21857 delete this.renderTo;
21862 Roo.Component.AUTO_ID = 1000;
21864 Roo.extend(Roo.Component, Roo.util.Observable, {
21866 * @property {Boolean} hidden
21867 * true if this component is hidden. Read-only.
21871 * true if this component is disabled. Read-only.
21875 * true if this component has been rendered. Read-only.
21879 /** @cfg {String} disableClass
21880 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
21882 disabledClass : "x-item-disabled",
21883 /** @cfg {Boolean} allowDomMove
21884 * Whether the component can move the Dom node when rendering (defaults to true).
21886 allowDomMove : true,
21887 /** @cfg {String} hideMode
21888 * How this component should hidden. Supported values are
21889 * "visibility" (css visibility), "offsets" (negative offset position) and
21890 * "display" (css display) - defaults to "display".
21892 hideMode: 'display',
21895 ctype : "Roo.Component",
21897 /** @cfg {String} actionMode
21898 * which property holds the element that used for hide() / show() / disable() / enable()
21904 getActionEl : function(){
21905 return this[this.actionMode];
21908 initComponent : Roo.emptyFn,
21910 * If this is a lazy rendering component, render it to its container element.
21911 * @param {String/HTMLElement/Element} container (optional) The element this component should be rendered into. If it is being applied to existing markup, this should be left off.
21913 render : function(B, C){
21914 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
21916 this.el = Roo.get(this.el);
21917 B = this.el.dom.parentNode;
21918 this.allowDomMove = false;
21921 this.container = Roo.get(B);
21922 this.rendered = true;
21923 if(C !== undefined){
21924 if(typeof C == 'number'){
21925 C = this.container.dom.childNodes[C];
21931 this.onRender(this.container, C || null);
21933 this.el.addClass(this.cls);
21937 this.el.applyStyles(this.style);
21941 this.fireEvent("render", this);
21942 this.afterRender(this.container);
21954 // default function is not really useful
21955 onRender : function(ct, D){
21957 this.el = Roo.get(this.el);
21958 if(this.allowDomMove !== false){
21959 ct.dom.insertBefore(this.el.dom, D);
21965 getAutoCreate : function(){
21966 var E = typeof this.autoCreate == "object" ?
21967 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
21968 if(this.id && !E.id){
21975 afterRender : Roo.emptyFn,
21978 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
21979 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
21981 destroy : function(){
21982 if(this.fireEvent("beforedestroy", this) !== false){
21983 this.purgeListeners();
21984 this.beforeDestroy();
21986 this.el.removeAllListeners();
21988 if(this.actionMode == "container"){
21989 this.container.remove();
21994 Roo.ComponentMgr.unregister(this);
21995 this.fireEvent("destroy", this);
22000 beforeDestroy : function(){
22005 onDestroy : function(){
22010 * Returns the underlying {@link Roo.Element}.
22011 * @return {Roo.Element} The element
22013 getEl : function(){
22018 * Returns the id of this component.
22021 getId : function(){
22026 * Try to focus this component.
22027 * @param {Boolean} selectText True to also select the text in this component (if applicable)
22028 * @return {Roo.Component} this
22030 focus : function(F){
22034 this.el.dom.select();
22049 * Disable this component.
22050 * @return {Roo.Component} this
22052 disable : function(){
22057 this.disabled = true;
22058 this.fireEvent("disable", this);
22063 onDisable : function(){
22064 this.getActionEl().addClass(this.disabledClass);
22065 this.el.dom.disabled = true;
22069 * Enable this component.
22070 * @return {Roo.Component} this
22072 enable : function(){
22077 this.disabled = false;
22078 this.fireEvent("enable", this);
22083 onEnable : function(){
22084 this.getActionEl().removeClass(this.disabledClass);
22085 this.el.dom.disabled = false;
22089 * Convenience function for setting disabled/enabled by boolean.
22090 * @param {Boolean} disabled
22092 setDisabled : function(G){
22093 this[G ? "disable" : "enable"]();
22097 * Show this component.
22098 * @return {Roo.Component} this
22101 if(this.fireEvent("beforeshow", this) !== false){
22102 this.hidden = false;
22107 this.fireEvent("show", this);
22113 onShow : function(){
22114 var ae = this.getActionEl();
22115 if(this.hideMode == 'visibility'){
22116 ae.dom.style.visibility = "visible";
22117 }else if(this.hideMode == 'offsets'){
22118 ae.removeClass('x-hidden');
22120 ae.dom.style.display = "";
22125 * Hide this component.
22126 * @return {Roo.Component} this
22129 if(this.fireEvent("beforehide", this) !== false){
22130 this.hidden = true;
22135 this.fireEvent("hide", this);
22141 onHide : function(){
22142 var ae = this.getActionEl();
22143 if(this.hideMode == 'visibility'){
22144 ae.dom.style.visibility = "hidden";
22145 }else if(this.hideMode == 'offsets'){
22146 ae.addClass('x-hidden');
22148 ae.dom.style.display = "none";
22153 * Convenience function to hide or show this component by boolean.
22154 * @param {Boolean} visible True to show, false to hide
22155 * @return {Roo.Component} this
22157 setVisible: function(H){
22167 * Returns true if this component is visible.
22169 isVisible : function(){
22170 return this.getActionEl().isVisible();
22173 cloneConfig : function(I){
22175 var id = I.id || Roo.id();
22176 var J = Roo.applyIf(I, this.initialConfig);
22177 J.id = id; // prevent dup id
22178 return new this.constructor(J);
22183 * Ext JS Library 1.1.1
22184 * Copyright(c) 2006-2007, Ext JS, LLC.
22186 * Originally Released Under LGPL - original licence link has changed is not relivant.
22189 * <script type="text/javascript">
22194 * @extends Roo.Element
22195 * An extended {@link Roo.Element} object that supports a shadow and shim, constrain to viewport and
22196 * automatic maintaining of shadow/shim positions.
22197 * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
22198 * @cfg {String/Boolean} shadow True to create a shadow element with default class "x-layer-shadow", or
22199 * you can pass a string with a CSS class name. False turns off the shadow.
22200 * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: "div", cls: "x-layer"}).
22201 * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
22202 * @cfg {String} cls CSS class to add to the element
22203 * @cfg {Number} zindex Starting z-index (defaults to 11000)
22204 * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 3)
22206 * @param {Object} config An object with config options.
22207 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
22210 Roo.Layer = function(C, D){
22212 var dh = Roo.DomHelper;
22213 var cp = C.parentEl, E = cp ? Roo.getDom(cp) : document.body;
22215 this.dom = Roo.getDom(D);
22218 var o = C.dh || {tag: "div", cls: "x-layer"};
22219 this.dom = dh.append(E, o);
22222 this.addClass(C.cls);
22225 this.constrain = C.constrain !== false;
22226 this.visibilityMode = Roo.Element.VISIBILITY;
22228 this.id = this.dom.id = C.id;
22230 this.id = Roo.id(this.dom);
22233 this.zindex = C.zindex || this.getZIndex();
22234 this.position("absolute", this.zindex);
22236 this.shadowOffset = C.shadowOffset || 4;
22237 this.shadow = new Roo.Shadow({
22238 offset : this.shadowOffset,
22242 this.shadowOffset = 0;
22245 this.useShim = C.shim !== false && Roo.useShims;
22246 this.useDisplay = C.useDisplay;
22250 var A = Roo.Element.prototype;
22252 // shims are shared among layer to keep from having 100 iframes
22255 Roo.extend(Roo.Layer, Roo.Element, {
22257 getZIndex : function(){
22258 return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
22261 getShim : function(){
22270 C = this.createShim();
22271 C.enableDisplayMode('block');
22272 C.dom.style.display = 'none';
22273 C.dom.style.visibility = 'visible';
22275 var pn = this.dom.parentNode;
22276 if(C.dom.parentNode != pn){
22277 pn.insertBefore(C.dom, this.dom);
22280 C.setStyle('z-index', this.getZIndex()-2);
22285 hideShim : function(){
22287 this.shim.setDisplayed(false);
22293 disableShadow : function(){
22295 this.shadowDisabled = true;
22296 this.shadow.hide();
22297 this.lastShadowOffset = this.shadowOffset;
22298 this.shadowOffset = 0;
22302 enableShadow : function(D){
22304 this.shadowDisabled = false;
22305 this.shadowOffset = this.lastShadowOffset;
22306 delete this.lastShadowOffset;
22314 // this code can execute repeatedly in milliseconds (i.e. during a drag) so
22315 // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
22316 sync : function(E){
22317 var sw = this.shadow;
22318 if(!this.updating && this.isVisible() && (sw || this.useShim)){
22319 var sh = this.getShim();
22321 var w = this.getWidth(),
22322 h = this.getHeight();
22324 var l = this.getLeft(true),
22325 t = this.getTop(true);
22327 if(sw && !this.shadowDisabled){
22328 if(E && !sw.isVisible()){
22331 sw.realign(l, t, w, h);
22337 // fit the shim behind the shadow, so it is shimmed too
22338 var a = sw.adjusts, s = sh.dom.style;
22339 s.left = (Math.min(l, l+a.l))+"px";
22340 s.top = (Math.min(t, t+a.t))+"px";
22341 s.width = (w+a.w)+"px";
22342 s.height = (h+a.h)+"px";
22350 sh.setLeftTop(l, t);
22357 destroy : function(){
22360 this.shadow.hide();
22363 this.removeAllListeners();
22364 var pn = this.dom.parentNode;
22366 pn.removeChild(this.dom);
22369 Roo.Element.uncache(this.id);
22372 remove : function(){
22377 beginUpdate : function(){
22378 this.updating = true;
22382 endUpdate : function(){
22383 this.updating = false;
22388 hideUnders : function(F){
22390 this.shadow.hide();
22397 constrainXY : function(){
22398 if(this.constrain){
22399 var vw = Roo.lib.Dom.getViewWidth(),
22400 vh = Roo.lib.Dom.getViewHeight();
22401 var s = Roo.get(document).getScroll();
22403 var xy = this.getXY();
22404 var x = xy[0], y = xy[1];
22405 var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
22406 // only move it if it needs it
22408 // first validate right/bottom
22409 if((x + w) > vw+s.left){
22410 x = vw - w - this.shadowOffset;
22413 if((y + h) > vh+s.top){
22414 y = vh - h - this.shadowOffset;
22417 // then make sure top/left isn't negative
22428 var ay = this.avoidY;
22429 if(y <= ay && (y+h) >= ay){
22436 A.setXY.call(this, xy);
22442 isVisible : function(){
22443 return this.visible;
22447 showAction : function(){
22448 this.visible = true; // track visibility to prevent getStyle calls
22449 if(this.useDisplay === true){
22450 this.setDisplayed("");
22451 }else if(this.lastXY){
22452 A.setXY.call(this, this.lastXY);
22453 }else if(this.lastLT){
22454 A.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
22459 hideAction : function(){
22460 this.visible = false;
22461 if(this.useDisplay === true){
22462 this.setDisplayed(false);
22464 this.setLeftTop(-10000,-10000);
22468 // overridden Element method
22469 setVisible : function(v, a, d, c, e){
22474 var cb = function(){
22479 }.createDelegate(this);
22480 A.setVisible.call(this, true, true, d, cb, e);
22483 this.hideUnders(true);
22492 }.createDelegate(this);
22495 A.setVisible.call(this, v, a, d, cb, e);
22504 storeXY : function(xy){
22505 delete this.lastLT;
22509 storeLeftTop : function(G, H){
22510 delete this.lastXY;
22511 this.lastLT = [G, H];
22515 beforeFx : function(){
22516 this.beforeAction();
22517 return Roo.Layer.superclass.beforeFx.apply(this, arguments);
22521 afterFx : function(){
22522 Roo.Layer.superclass.afterFx.apply(this, arguments);
22523 this.sync(this.isVisible());
22527 beforeAction : function(){
22528 if(!this.updating && this.shadow){
22529 this.shadow.hide();
22533 // overridden Element method
22534 setLeft : function(I){
22535 this.storeLeftTop(I, this.getTop(true));
22536 A.setLeft.apply(this, arguments);
22540 setTop : function(J){
22541 this.storeLeftTop(this.getLeft(true), J);
22542 A.setTop.apply(this, arguments);
22546 setLeftTop : function(K, L){
22547 this.storeLeftTop(K, L);
22548 A.setLeftTop.apply(this, arguments);
22552 setXY : function(xy, a, d, c, e){
22554 this.beforeAction();
22556 var cb = this.createCB(c);
22557 A.setXY.call(this, xy, a, d, cb, e);
22564 createCB : function(c){
22575 // overridden Element method
22576 setX : function(x, a, d, c, e){
22577 this.setXY([x, this.getY()], a, d, c, e);
22580 // overridden Element method
22581 setY : function(y, a, d, c, e){
22582 this.setXY([this.getX(), y], a, d, c, e);
22585 // overridden Element method
22586 setSize : function(w, h, a, d, c, e){
22587 this.beforeAction();
22588 var cb = this.createCB(c);
22589 A.setSize.call(this, w, h, a, d, cb, e);
22595 // overridden Element method
22596 setWidth : function(w, a, d, c, e){
22597 this.beforeAction();
22598 var cb = this.createCB(c);
22599 A.setWidth.call(this, w, a, d, cb, e);
22605 // overridden Element method
22606 setHeight : function(h, a, d, c, e){
22607 this.beforeAction();
22608 var cb = this.createCB(c);
22609 A.setHeight.call(this, h, a, d, cb, e);
22615 // overridden Element method
22616 setBounds : function(x, y, w, h, a, d, c, e){
22617 this.beforeAction();
22618 var cb = this.createCB(c);
22620 this.storeXY([x, y]);
22621 A.setXY.call(this, [x, y]);
22622 A.setSize.call(this, w, h, a, d, cb, e);
22625 A.setBounds.call(this, x, y, w, h, a, d, cb, e);
22631 * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
22632 * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
22633 * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
22634 * @param {Number} zindex The new z-index to set
22635 * @return {this} The Layer
22637 setZIndex : function(M){
22639 this.setStyle("z-index", M + 2);
22641 this.shadow.setZIndex(M + 1);
22644 this.shim.setStyle("z-index", M);
22651 * Ext JS Library 1.1.1
22652 * Copyright(c) 2006-2007, Ext JS, LLC.
22654 * Originally Released Under LGPL - original licence link has changed is not relivant.
22657 * <script type="text/javascript">
22662 * @class Roo.Shadow
22663 * Simple class that can provide a shadow effect for any element. Note that the element MUST be absolutely positioned,
22664 * and the shadow does not provide any shimming. This should be used only in simple cases -- for more advanced
22665 * functionality that can also provide the same shadow effect, see the {@link Roo.Layer} class.
22667 * Create a new Shadow
22668 * @param {Object} config The config object
22670 Roo.Shadow = function(A){
22671 Roo.apply(this, A);
22672 if(typeof this.mode != "string"){
22673 this.mode = this.defaultMode;
22675 var o = this.offset, a = {h: 0};
22676 var B = Math.floor(this.offset/2);
22677 switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
22683 a.l -= this.offset + B;
22684 a.t -= this.offset + B;
22695 a.l -= (this.offset - B);
22696 a.t -= this.offset + B;
22698 a.w -= (this.offset - B)*2;
22709 a.l -= (this.offset - B);
22710 a.t -= (this.offset - B);
22712 a.w -= (this.offset + B + 1);
22713 a.h -= (this.offset + B);
22722 Roo.Shadow.prototype = {
22724 * @cfg {String} mode
22725 * The shadow display mode. Supports the following options:<br />
22726 * sides: Shadow displays on both sides and bottom only<br />
22727 * frame: Shadow displays equally on all four sides<br />
22728 * drop: Traditional bottom-right drop shadow (default)
22731 * @cfg {String} offset
22732 * The number of pixels to offset the shadow from the element (defaults to 4)
22737 defaultMode: "drop",
22740 * Displays the shadow under the target element
22741 * @param {String/HTMLElement/Element} targetEl The id or element under which the shadow should display
22743 show : function(C){
22746 this.el = Roo.Shadow.Pool.pull();
22747 if(this.el.dom.nextSibling != C.dom){
22748 this.el.insertBefore(C);
22752 this.el.setStyle("z-index", this.zIndex || parseInt(C.getStyle("z-index"), 10)-1);
22754 this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
22763 this.el.dom.style.display = "block";
22767 * Returns true if the shadow is visible, else false
22769 isVisible : function(){
22770 return this.el ? true : false;
22774 * Direct alignment when values are already available. Show must be called at least once before
22775 * calling this method to ensure it is initialized.
22776 * @param {Number} left The target element left position
22777 * @param {Number} top The target element top position
22778 * @param {Number} width The target element width
22779 * @param {Number} height The target element height
22781 realign : function(l, t, w, h){
22785 var a = this.adjusts, d = this.el.dom, s = d.style;
22787 s.left = (l+a.l)+"px";
22788 s.top = (t+a.t)+"px";
22789 var sw = (w+a.w), sh = (h+a.h), E = sw +"px", F = sh + "px";
22790 if(s.width != E || s.height != F){
22794 var cn = d.childNodes;
22795 var sww = Math.max(0, (sw-12))+"px";
22796 cn[0].childNodes[1].style.width = sww;
22797 cn[1].childNodes[1].style.width = sww;
22798 cn[2].childNodes[1].style.width = sww;
22799 cn[1].style.height = Math.max(0, (sh-12))+"px";
22805 * Hides this shadow
22809 this.el.dom.style.display = "none";
22810 Roo.Shadow.Pool.push(this.el);
22816 * Adjust the z-index of this shadow
22817 * @param {Number} zindex The new z-index
22819 setZIndex : function(z){
22822 this.el.setStyle("z-index", z);
22827 // Private utility class that manages the internal Shadow cache
22828 Roo.Shadow.Pool = function(){
22831 '<div class="x-ie-shadow"></div>' :
22832 '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
22835 var sh = p.shift();
22837 sh = Roo.get(Roo.DomHelper.insertHtml("beforeBegin", document.body.firstChild, G));
22838 sh.autoBoxAdjust = false;
22843 push : function(sh){
22850 * Ext JS Library 1.1.1
22851 * Copyright(c) 2006-2007, Ext JS, LLC.
22853 * Originally Released Under LGPL - original licence link has changed is not relivant.
22856 * <script type="text/javascript">
22860 * @class Roo.BoxComponent
22861 * @extends Roo.Component
22862 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
22863 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
22864 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
22865 * layout containers.
22867 * @param {Roo.Element/String/Object} config The configuration options.
22869 Roo.BoxComponent = function(A){
22870 Roo.Component.call(this, A);
22874 * Fires after the component is resized.
22875 * @param {Roo.Component} this
22876 * @param {Number} adjWidth The box-adjusted width that was set
22877 * @param {Number} adjHeight The box-adjusted height that was set
22878 * @param {Number} rawWidth The width that was originally specified
22879 * @param {Number} rawHeight The height that was originally specified
22884 * Fires after the component is moved.
22885 * @param {Roo.Component} this
22886 * @param {Number} x The new x position
22887 * @param {Number} y The new y position
22893 Roo.extend(Roo.BoxComponent, Roo.Component, {
22894 // private, set in afterRender to signify that the component has been rendered
22896 // private, used to defer height settings to subclasses
22897 deferHeight: false,
22898 /** @cfg {Number} width
22899 * width (optional) size of component
22901 /** @cfg {Number} height
22902 * height (optional) size of component
22906 * Sets the width and height of the component. This method fires the resize event. This method can accept
22907 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
22908 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
22909 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
22910 * @return {Roo.BoxComponent} this
22912 setSize : function(w, h){
22913 // support for standard size objects
22914 if(typeof w == 'object'){
22919 if(!this.boxReady){
22925 // prevent recalcs when not needed
22926 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
22930 this.lastSize = {width: w, height: h};
22932 var B = this.adjustSize(w, h);
22933 var aw = B.width, ah = B.height;
22934 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
22935 var rz = this.getResizeEl();
22936 if(!this.deferHeight && aw !== undefined && ah !== undefined){
22937 rz.setSize(aw, ah);
22938 }else if(!this.deferHeight && ah !== undefined){
22940 }else if(aw !== undefined){
22944 this.onResize(aw, ah, w, h);
22945 this.fireEvent('resize', this, aw, ah, w, h);
22951 * Gets the current size of the component's underlying element.
22952 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
22954 getSize : function(){
22955 return this.el.getSize();
22959 * Gets the current XY position of the component's underlying element.
22960 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
22961 * @return {Array} The XY position of the element (e.g., [100, 200])
22963 getPosition : function(C){
22965 return [this.el.getLeft(true), this.el.getTop(true)];
22967 return this.xy || this.el.getXY();
22971 * Gets the current box measurements of the component's underlying element.
22972 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
22973 * @returns {Object} box An object in the format {x, y, width, height}
22975 getBox : function(D){
22976 var s = this.el.getSize();
22978 s.x = this.el.getLeft(true);
22979 s.y = this.el.getTop(true);
22981 var xy = this.xy || this.el.getXY();
22989 * Sets the current box measurements of the component's underlying element.
22990 * @param {Object} box An object in the format {x, y, width, height}
22991 * @returns {Roo.BoxComponent} this
22993 updateBox : function(E){
22994 this.setSize(E.width, E.height);
22995 this.setPagePosition(E.x, E.y);
23000 getResizeEl : function(){
23001 return this.resizeEl || this.el;
23005 getPositionEl : function(){
23006 return this.positionEl || this.el;
23010 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
23011 * This method fires the move event.
23012 * @param {Number} left The new left
23013 * @param {Number} top The new top
23014 * @returns {Roo.BoxComponent} this
23016 setPosition : function(x, y){
23019 if(!this.boxReady){
23022 var F = this.adjustPosition(x, y);
23023 var ax = F.x, ay = F.y;
23025 var el = this.getPositionEl();
23026 if(ax !== undefined || ay !== undefined){
23027 if(ax !== undefined && ay !== undefined){
23028 el.setLeftTop(ax, ay);
23029 }else if(ax !== undefined){
23031 }else if(ay !== undefined){
23035 this.onPosition(ax, ay);
23036 this.fireEvent('move', this, ax, ay);
23042 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
23043 * This method fires the move event.
23044 * @param {Number} x The new x position
23045 * @param {Number} y The new y position
23046 * @returns {Roo.BoxComponent} this
23048 setPagePosition : function(x, y){
23051 if(!this.boxReady){
23054 if(x === undefined || y === undefined){ // cannot translate undefined points
23057 var p = this.el.translatePoints(x, y);
23058 this.setPosition(p.left, p.top);
23063 onRender : function(ct, G){
23064 Roo.BoxComponent.superclass.onRender.call(this, ct, G);
23066 this.resizeEl = Roo.get(this.resizeEl);
23068 if(this.positionEl){
23069 this.positionEl = Roo.get(this.positionEl);
23074 afterRender : function(){
23075 Roo.BoxComponent.superclass.afterRender.call(this);
23076 this.boxReady = true;
23077 this.setSize(this.width, this.height);
23078 if(this.x || this.y){
23079 this.setPosition(this.x, this.y);
23081 if(this.pageX || this.pageY){
23082 this.setPagePosition(this.pageX, this.pageY);
23087 * Force the component's size to recalculate based on the underlying element's current height and width.
23088 * @returns {Roo.BoxComponent} this
23090 syncSize : function(){
23091 delete this.lastSize;
23092 this.setSize(this.el.getWidth(), this.el.getHeight());
23097 * Called after the component is resized, this method is empty by default but can be implemented by any
23098 * subclass that needs to perform custom logic after a resize occurs.
23099 * @param {Number} adjWidth The box-adjusted width that was set
23100 * @param {Number} adjHeight The box-adjusted height that was set
23101 * @param {Number} rawWidth The width that was originally specified
23102 * @param {Number} rawHeight The height that was originally specified
23104 onResize : function(H, I, J, K){
23109 * Called after the component is moved, this method is empty by default but can be implemented by any
23110 * subclass that needs to perform custom logic after a move occurs.
23111 * @param {Number} x The new x position
23112 * @param {Number} y The new y position
23114 onPosition : function(x, y){
23119 adjustSize : function(w, h){
23120 if(this.autoWidth){
23123 if(this.autoHeight){
23126 return {width : w, height: h};
23130 adjustPosition : function(x, y){
23131 return {x : x, y: y};
23136 * Ext JS Library 1.1.1
23137 * Copyright(c) 2006-2007, Ext JS, LLC.
23139 * Originally Released Under LGPL - original licence link has changed is not relivant.
23142 * <script type="text/javascript">
23147 * @class Roo.SplitBar
23148 * @extends Roo.util.Observable
23149 * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
23153 var split = new Roo.SplitBar("elementToDrag", "elementToSize",
23154 Roo.SplitBar.HORIZONTAL, Roo.SplitBar.LEFT);
23155 split.setAdapter(new Roo.SplitBar.AbsoluteLayoutAdapter("container"));
23156 split.minSize = 100;
23157 split.maxSize = 600;
23158 split.animate = true;
23159 split.on('moved', splitterMoved);
23162 * Create a new SplitBar
23163 * @param {String/HTMLElement/Roo.Element} dragElement The element to be dragged and act as the SplitBar.
23164 * @param {String/HTMLElement/Roo.Element} resizingElement The element to be resized based on where the SplitBar element is dragged
23165 * @param {Number} orientation (optional) Either Roo.SplitBar.HORIZONTAL or Roo.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
23166 * @param {Number} placement (optional) Either Roo.SplitBar.LEFT or Roo.SplitBar.RIGHT for horizontal or
23167 Roo.SplitBar.TOP or Roo.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
23168 position of the SplitBar).
23170 Roo.SplitBar = function(A, B, C, D, E){
23173 this.el = Roo.get(A, true);
23174 this.el.dom.unselectable = "on";
23176 this.resizingEl = Roo.get(B, true);
23180 * The orientation of the split. Either Roo.SplitBar.HORIZONTAL or Roo.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
23181 * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
23184 this.orientation = C || Roo.SplitBar.HORIZONTAL;
23187 * The minimum size of the resizing element. (Defaults to 0)
23193 * The maximum size of the resizing element. (Defaults to 2000)
23196 this.maxSize = 2000;
23199 * Whether to animate the transition to the new size
23202 this.animate = false;
23205 * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
23208 this.useShim = false;
23215 this.proxy = Roo.SplitBar.createProxy(this.orientation);
23217 this.proxy = Roo.get(E).dom;
23221 this.dd = new Roo.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
23224 this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
23227 this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
23230 this.dragSpecs = {};
23233 * @private The adapter to use to positon and resize elements
23235 this.adapter = new Roo.SplitBar.BasicLayoutAdapter();
23236 this.adapter.init(this);
23238 if(this.orientation == Roo.SplitBar.HORIZONTAL){
23240 this.placement = D || (this.el.getX() > this.resizingEl.getX() ? Roo.SplitBar.LEFT : Roo.SplitBar.RIGHT);
23241 this.el.addClass("x-splitbar-h");
23244 this.placement = D || (this.el.getY() > this.resizingEl.getY() ? Roo.SplitBar.TOP : Roo.SplitBar.BOTTOM);
23245 this.el.addClass("x-splitbar-v");
23252 * Fires when the splitter is moved (alias for {@link #event-moved})
23253 * @param {Roo.SplitBar} this
23254 * @param {Number} newSize the new width or height
23259 * Fires when the splitter is moved
23260 * @param {Roo.SplitBar} this
23261 * @param {Number} newSize the new width or height
23265 * @event beforeresize
23266 * Fires before the splitter is dragged
23267 * @param {Roo.SplitBar} this
23269 "beforeresize" : true,
23271 "beforeapply" : true
23274 Roo.util.Observable.call(this);
23277 Roo.extend(Roo.SplitBar, Roo.util.Observable, {
23278 onStartProxyDrag : function(x, y){
23279 this.fireEvent("beforeresize", this);
23281 var o = Roo.DomHelper.insertFirst(document.body, {cls: "x-drag-overlay", html: " "}, true);
23283 o.enableDisplayMode("block");
23284 // all splitbars share the same overlay
23285 Roo.SplitBar.prototype.overlay = o;
23288 this.overlay.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
23289 this.overlay.show();
23290 Roo.get(this.proxy).setDisplayed("block");
23291 var F = this.adapter.getElementSize(this);
23292 this.activeMinSize = this.getMinimumSize();;
23293 this.activeMaxSize = this.getMaximumSize();;
23294 var c1 = F - this.activeMinSize;
23295 var c2 = Math.max(this.activeMaxSize - F, 0);
23296 if(this.orientation == Roo.SplitBar.HORIZONTAL){
23297 this.dd.resetConstraints();
23298 this.dd.setXConstraint(
23299 this.placement == Roo.SplitBar.LEFT ? c1 : c2,
23300 this.placement == Roo.SplitBar.LEFT ? c2 : c1
23302 this.dd.setYConstraint(0, 0);
23304 this.dd.resetConstraints();
23305 this.dd.setXConstraint(0, 0);
23306 this.dd.setYConstraint(
23307 this.placement == Roo.SplitBar.TOP ? c1 : c2,
23308 this.placement == Roo.SplitBar.TOP ? c2 : c1
23312 this.dragSpecs.startSize = F;
23313 this.dragSpecs.startPoint = [x, y];
23314 Roo.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
23318 * @private Called after the drag operation by the DDProxy
23320 onEndProxyDrag : function(e){
23321 Roo.get(this.proxy).setDisplayed(false);
23322 var G = Roo.lib.Event.getXY(e);
23324 this.overlay.hide();
23327 if(this.orientation == Roo.SplitBar.HORIZONTAL){
23328 H = this.dragSpecs.startSize +
23329 (this.placement == Roo.SplitBar.LEFT ?
23330 G[0] - this.dragSpecs.startPoint[0] :
23331 this.dragSpecs.startPoint[0] - G[0]
23334 H = this.dragSpecs.startSize +
23335 (this.placement == Roo.SplitBar.TOP ?
23336 G[1] - this.dragSpecs.startPoint[1] :
23337 this.dragSpecs.startPoint[1] - G[1]
23341 H = Math.min(Math.max(H, this.activeMinSize), this.activeMaxSize);
23342 if(H != this.dragSpecs.startSize){
23343 if(this.fireEvent('beforeapply', this, H) !== false){
23344 this.adapter.setElementSize(this, H);
23345 this.fireEvent("moved", this, H);
23346 this.fireEvent("resize", this, H);
23352 * Get the adapter this SplitBar uses
23353 * @return The adapter object
23355 getAdapter : function(){
23356 return this.adapter;
23360 * Set the adapter this SplitBar uses
23361 * @param {Object} adapter A SplitBar adapter object
23363 setAdapter : function(I){
23365 this.adapter.init(this);
23369 * Gets the minimum size for the resizing element
23370 * @return {Number} The minimum size
23372 getMinimumSize : function(){
23373 return this.minSize;
23377 * Sets the minimum size for the resizing element
23378 * @param {Number} minSize The minimum size
23380 setMinimumSize : function(J){
23385 * Gets the maximum size for the resizing element
23386 * @return {Number} The maximum size
23388 getMaximumSize : function(){
23389 return this.maxSize;
23393 * Sets the maximum size for the resizing element
23394 * @param {Number} maxSize The maximum size
23396 setMaximumSize : function(K){
23401 * Sets the initialize size for the resizing element
23402 * @param {Number} size The initial size
23404 setCurrentSize : function(L){
23405 var M = this.animate;
23406 this.animate = false;
23407 this.adapter.setElementSize(this, L);
23412 * Destroy this splitbar.
23413 * @param {Boolean} removeEl True to remove the element
23415 destroy : function(N){
23417 this.shim.remove();
23421 this.proxy.parentNode.removeChild(this.proxy);
23429 * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
23431 Roo.SplitBar.createProxy = function(O){
23432 var P = new Roo.Element(document.createElement("div"));
23434 var Q = 'x-splitbar-proxy';
23435 P.addClass(Q + ' ' + (O == Roo.SplitBar.HORIZONTAL ? Q +'-h' : Q + '-v'));
23436 document.body.appendChild(P.dom);
23441 * @class Roo.SplitBar.BasicLayoutAdapter
23442 * Default Adapter. It assumes the splitter and resizing element are not positioned
23443 * elements and only gets/sets the width of the element. Generally used for table based layouts.
23445 Roo.SplitBar.BasicLayoutAdapter = function(){
23448 Roo.SplitBar.BasicLayoutAdapter.prototype = {
23449 // do nothing for now
23450 init : function(s){
23454 * Called before drag operations to get the current size of the resizing element.
23455 * @param {Roo.SplitBar} s The SplitBar using this adapter
23457 getElementSize : function(s){
23458 if(s.orientation == Roo.SplitBar.HORIZONTAL){
23459 return s.resizingEl.getWidth();
23461 return s.resizingEl.getHeight();
23466 * Called after drag operations to set the size of the resizing element.
23467 * @param {Roo.SplitBar} s The SplitBar using this adapter
23468 * @param {Number} newSize The new size to set
23469 * @param {Function} onComplete A function to be invoked when resizing is complete
23471 setElementSize : function(s, R, S){
23472 if(s.orientation == Roo.SplitBar.HORIZONTAL){
23474 s.resizingEl.setWidth(R);
23479 s.resizingEl.setWidth(R, true, .1, S, 'easeOut');
23484 s.resizingEl.setHeight(R);
23489 s.resizingEl.setHeight(R, true, .1, S, 'easeOut');
23496 *@class Roo.SplitBar.AbsoluteLayoutAdapter
23497 * @extends Roo.SplitBar.BasicLayoutAdapter
23498 * Adapter that moves the splitter element to align with the resized sizing element.
23499 * Used with an absolute positioned SplitBar.
23500 * @param {String/HTMLElement/Roo.Element} container The container that wraps around the absolute positioned content. If it's
23501 * document.body, make sure you assign an id to the body element.
23503 Roo.SplitBar.AbsoluteLayoutAdapter = function(T){
23504 this.basic = new Roo.SplitBar.BasicLayoutAdapter();
23505 this.container = Roo.get(T);
23508 Roo.SplitBar.AbsoluteLayoutAdapter.prototype = {
23509 init : function(s){
23510 this.basic.init(s);
23513 getElementSize : function(s){
23514 return this.basic.getElementSize(s);
23517 setElementSize : function(s, U, V){
23518 this.basic.setElementSize(s, U, this.moveSplitter.createDelegate(this, [s]));
23521 moveSplitter : function(s){
23522 var W = Roo.SplitBar;
23523 switch(s.placement){
23525 s.el.setX(s.resizingEl.getRight());
23528 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
23531 s.el.setY(s.resizingEl.getBottom());
23534 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
23541 * Orientation constant - Create a vertical SplitBar
23545 Roo.SplitBar.VERTICAL = 1;
23548 * Orientation constant - Create a horizontal SplitBar
23552 Roo.SplitBar.HORIZONTAL = 2;
23555 * Placement constant - The resizing element is to the left of the splitter element
23559 Roo.SplitBar.LEFT = 1;
23562 * Placement constant - The resizing element is to the right of the splitter element
23566 Roo.SplitBar.RIGHT = 2;
23569 * Placement constant - The resizing element is positioned above the splitter element
23573 Roo.SplitBar.TOP = 3;
23576 * Placement constant - The resizing element is positioned under splitter element
23580 Roo.SplitBar.BOTTOM = 4;
23584 * Ext JS Library 1.1.1
23585 * Copyright(c) 2006-2007, Ext JS, LLC.
23587 * Originally Released Under LGPL - original licence link has changed is not relivant.
23590 * <script type="text/javascript">
23595 * @extends Roo.util.Observable
23596 * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template.
23597 * This class also supports single and multi selection modes. <br>
23598 * Create a data model bound view:
23600 var store = new Roo.data.Store(...);
23602 var view = new Roo.View("my-element",
23603 '<div id="{0}">{2} - {1}</div>', // auto create template
23605 singleSelect: true,
23606 selectedClass: "ydataview-selected",
23610 // listen for node click?
23611 view.on("click", function(vw, index, node, e){
23612 alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
23616 dataModel.load("foobar.xml");
23618 For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
23620 * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
23621 * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
23623 * Create a new View
23624 * @param {String/HTMLElement/Element} container The container element where the view is to be rendered.
23625 * @param {String/DomHelper.Template} tpl The rendering template or a string to create a template with
23626 * @param {Object} config The config object
23628 Roo.View = function(A, B, C){
23629 this.el = Roo.get(A);
23630 if(typeof B == "string"){
23631 B = new Roo.Template(B);
23636 * The template used by this View
23637 * @type {Roo.DomHelper.Template}
23641 Roo.apply(this, C);
23646 * @event beforeclick
23647 * Fires before a click is processed. Returns false to cancel the default action.
23648 * @param {Roo.View} this
23649 * @param {Number} index The index of the target node
23650 * @param {HTMLElement} node The target node
23651 * @param {Roo.EventObject} e The raw event object
23653 "beforeclick" : true,
23656 * Fires when a template node is clicked.
23657 * @param {Roo.View} this
23658 * @param {Number} index The index of the target node
23659 * @param {HTMLElement} node The target node
23660 * @param {Roo.EventObject} e The raw event object
23665 * Fires when a template node is double clicked.
23666 * @param {Roo.View} this
23667 * @param {Number} index The index of the target node
23668 * @param {HTMLElement} node The target node
23669 * @param {Roo.EventObject} e The raw event object
23673 * @event contextmenu
23674 * Fires when a template node is right clicked.
23675 * @param {Roo.View} this
23676 * @param {Number} index The index of the target node
23677 * @param {HTMLElement} node The target node
23678 * @param {Roo.EventObject} e The raw event object
23680 "contextmenu" : true,
23682 * @event selectionchange
23683 * Fires when the selected nodes change.
23684 * @param {Roo.View} this
23685 * @param {Array} selections Array of the selected nodes
23687 "selectionchange" : true,
23690 * @event beforeselect
23691 * Fires before a selection is made. If any handlers return false, the selection is cancelled.
23692 * @param {Roo.View} this
23693 * @param {HTMLElement} node The node to be selected
23694 * @param {Array} selections Array of currently selected nodes
23696 "beforeselect" : true
23700 "click": this.onClick,
23701 "dblclick": this.onDblClick,
23702 "contextmenu": this.onContextMenu,
23706 this.selections = [];
23708 this.cmp = new Roo.CompositeElementLite([]);
23710 this.store = Roo.factory(this.store, Roo.data);
23711 this.setStore(this.store, true);
23714 Roo.View.superclass.constructor.call(this);
23717 Roo.extend(Roo.View, Roo.util.Observable, {
23719 * The css class to add to selected nodes
23720 * @type {Roo.DomHelper.Template}
23722 selectedClass : "x-view-selected",
23726 * Returns the element this view is bound to.
23727 * @return {Roo.Element}
23729 getEl : function(){
23734 * Refreshes the view.
23736 refresh : function(){
23738 this.clearSelections();
23739 this.el.update("");
23741 var E = this.store.getRange();
23743 this.el.update(this.emptyText);
23746 for(var i = 0, len = E.length; i < len; i++){
23747 var data = this.prepareData(E[i].data, i, E[i]);
23748 D[D.length] = t.apply(data);
23751 this.el.update(D.join(""));
23752 this.nodes = this.el.dom.childNodes;
23753 this.updateIndexes(0);
23757 * Function to override to reformat the data that is sent to
23758 * the template for each node.
23759 * @param {Array/Object} data The raw data (array of colData for a data model bound view or
23760 * a JSON object for an UpdateManager bound view).
23762 prepareData : function(F){
23766 onUpdate : function(ds, G){
23767 this.clearSelections();
23768 var H = this.store.indexOf(G);
23769 var n = this.nodes[H];
23770 this.tpl.insertBefore(n, this.prepareData(G.data));
23771 n.parentNode.removeChild(n);
23772 this.updateIndexes(H, H);
23775 onAdd : function(ds, I, J){
23776 this.clearSelections();
23777 if(this.nodes.length == 0){
23781 var n = this.nodes[J];
23782 for(var i = 0, len = I.length; i < len; i++){
23783 var d = this.prepareData(I[i].data);
23785 this.tpl.insertBefore(n, d);
23787 this.tpl.append(this.el, d);
23791 this.updateIndexes(J);
23794 onRemove : function(ds, K, L){
23795 this.clearSelections();
23796 this.el.dom.removeChild(this.nodes[L]);
23797 this.updateIndexes(L);
23801 * Refresh an individual node.
23802 * @param {Number} index
23804 refreshNode : function(M){
23805 this.onUpdate(this.store, this.store.getAt(M));
23808 updateIndexes : function(N, O){
23809 var ns = this.nodes;
23811 O = O || ns.length - 1;
23812 for(var i = N; i <= O; i++){
23813 ns[i].nodeIndex = i;
23818 * Changes the data store this view uses and refresh the view.
23819 * @param {Store} store
23821 setStore : function(P, Q){
23822 if(!Q && this.store){
23823 this.store.un("datachanged", this.refresh);
23824 this.store.un("add", this.onAdd);
23825 this.store.un("remove", this.onRemove);
23826 this.store.un("update", this.onUpdate);
23827 this.store.un("clear", this.refresh);
23831 P.on("datachanged", this.refresh, this);
23832 P.on("add", this.onAdd, this);
23833 P.on("remove", this.onRemove, this);
23834 P.on("update", this.onUpdate, this);
23835 P.on("clear", this.refresh, this);
23844 * Returns the template node the passed child belongs to or null if it doesn't belong to one.
23845 * @param {HTMLElement} node
23846 * @return {HTMLElement} The template node
23848 findItemFromChild : function(R){
23849 var el = this.el.dom;
23850 if(!R || R.parentNode == el){
23853 var p = R.parentNode;
23854 while(p && p != el){
23855 if(p.parentNode == el){
23865 onClick : function(e){
23866 var S = this.findItemFromChild(e.getTarget());
23868 var M = this.indexOf(S);
23869 if(this.onItemClick(S, M, e) !== false){
23870 this.fireEvent("click", this, M, S, e);
23873 this.clearSelections();
23878 onContextMenu : function(e){
23879 var T = this.findItemFromChild(e.getTarget());
23881 this.fireEvent("contextmenu", this, this.indexOf(T), T, e);
23886 onDblClick : function(e){
23887 var U = this.findItemFromChild(e.getTarget());
23889 this.fireEvent("dblclick", this, this.indexOf(U), U, e);
23893 onItemClick : function(V, W, e){
23894 if(this.fireEvent("beforeclick", this, W, V, e) === false){
23897 if(this.multiSelect || this.singleSelect){
23898 if(this.multiSelect && e.shiftKey && this.lastSelection){
23899 this.select(this.getNodes(this.indexOf(this.lastSelection), W), false);
23901 this.select(V, this.multiSelect && e.ctrlKey);
23902 this.lastSelection = V;
23905 e.preventDefault();
23911 * Get the number of selected nodes.
23914 getSelectionCount : function(){
23915 return this.selections.length;
23919 * Get the currently selected nodes.
23920 * @return {Array} An array of HTMLElements
23922 getSelectedNodes : function(){
23923 return this.selections;
23927 * Get the indexes of the selected nodes.
23930 getSelectedIndexes : function(){
23931 var X = [], s = this.selections;
23932 for(var i = 0, len = s.length; i < len; i++){
23933 X.push(s[i].nodeIndex);
23939 * Clear all selections
23940 * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange event
23942 clearSelections : function(Y){
23943 if(this.nodes && (this.multiSelect || this.singleSelect) && this.selections.length > 0){
23944 this.cmp.elements = this.selections;
23945 this.cmp.removeClass(this.selectedClass);
23946 this.selections = [];
23948 this.fireEvent("selectionchange", this, this.selections);
23954 * Returns true if the passed node is selected
23955 * @param {HTMLElement/Number} node The node or node index
23956 * @return {Boolean}
23958 isSelected : function(Z){
23959 var s = this.selections;
23964 Z = this.getNode(Z);
23965 return s.indexOf(Z) !== -1;
23970 * @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
23971 * @param {Boolean} keepExisting (optional) true to keep existing selections
23972 * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
23974 select : function(a, b, c){
23975 if(a instanceof Array){
23977 this.clearSelections(true);
23979 for(var i = 0, len = a.length; i < len; i++){
23980 this.select(a[i], true, true);
23983 var Z = this.getNode(a);
23984 if(Z && !this.isSelected(Z)){
23986 this.clearSelections(true);
23988 if(this.fireEvent("beforeselect", this, Z, this.selections) !== false){
23989 Roo.fly(Z).addClass(this.selectedClass);
23990 this.selections.push(Z);
23992 this.fireEvent("selectionchange", this, this.selections);
24000 * Gets a template node.
24001 * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
24002 * @return {HTMLElement} The node or null if it wasn't found
24004 getNode : function(f){
24005 if(typeof f == "string"){
24006 return document.getElementById(f);
24007 }else if(typeof f == "number"){
24008 return this.nodes[f];
24014 * Gets a range template nodes.
24015 * @param {Number} startIndex
24016 * @param {Number} endIndex
24017 * @return {Array} An array of nodes
24019 getNodes : function(g, h){
24020 var ns = this.nodes;
24022 h = typeof h == "undefined" ? ns.length - 1 : h;
24025 for(var i = g; i <= h; i++){
24029 for(var i = g; i >= h; i--){
24037 * Finds the index of the passed node
24038 * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
24039 * @return {Number} The index of the node or -1
24041 indexOf : function(k){
24042 k = this.getNode(k);
24043 if(typeof k.nodeIndex == "number"){
24044 return k.nodeIndex;
24046 var ns = this.nodes;
24047 for(var i = 0, len = ns.length; i < len; i++){
24058 * Ext JS Library 1.1.1
24059 * Copyright(c) 2006-2007, Ext JS, LLC.
24061 * Originally Released Under LGPL - original licence link has changed is not relivant.
24064 * <script type="text/javascript">
24068 * @class Roo.JsonView
24069 * @extends Roo.View
24070 * Shortcut class to create a JSON + {@link Roo.UpdateManager} template view. Usage:
24072 var view = new Roo.JsonView("my-element",
24073 '<div id="{id}">{foo} - {bar}</div>', // auto create template
24074 { multiSelect: true, jsonRoot: "data" }
24077 // listen for node click?
24078 view.on("click", function(vw, index, node, e){
24079 alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
24082 // direct load of JSON data
24083 view.load("foobar.php");
24085 // Example from my blog list
24086 var tpl = new Roo.Template(
24087 '<div class="entry">' +
24088 '<a class="entry-title" href="{link}">{title}</a>' +
24089 "<h4>{date} by {author} | {comments} Comments</h4>{description}" +
24090 "</div><hr />"
24093 var moreView = new Roo.JsonView("entry-list", tpl, {
24096 moreView.on("beforerender", this.sortEntries, this);
24098 url: "/blog/get-posts.php",
24099 params: "allposts=true",
24100 text: "Loading Blog Entries..."
24104 * Create a new JsonView
24105 * @param {String/HTMLElement/Element} container The container element where the view is to be rendered.
24106 * @param {Template} tpl The rendering template
24107 * @param {Object} config The config object
24109 Roo.JsonView = function(A, B, C){
24110 Roo.JsonView.superclass.constructor.call(this, A, B, C);
24112 var um = this.el.getUpdateManager();
24113 um.setRenderer(this);
24114 um.on("update", this.onLoad, this);
24115 um.on("failure", this.onLoadException, this);
24118 * @event beforerender
24119 * Fires before rendering of the downloaded JSON data.
24120 * @param {Roo.JsonView} this
24121 * @param {Object} data The JSON data loaded
24125 * Fires when data is loaded.
24126 * @param {Roo.JsonView} this
24127 * @param {Object} data The JSON data loaded
24128 * @param {Object} response The raw Connect response object
24131 * @event loadexception
24132 * Fires when loading fails.
24133 * @param {Roo.JsonView} this
24134 * @param {Object} response The raw Connect response object
24137 'beforerender' : true,
24139 'loadexception' : true
24142 Roo.extend(Roo.JsonView, Roo.View, {
24144 * The root property in the loaded JSON object that contains the data
24150 * Refreshes the view.
24152 refresh : function(){
24153 this.clearSelections();
24154 this.el.update("");
24156 var o = this.jsonData;
24157 if(o && o.length > 0){
24158 for(var i = 0, len = o.length; i < len; i++){
24159 var data = this.prepareData(o[i], i, o);
24160 D[D.length] = this.tpl.apply(data);
24163 D.push(this.emptyText);
24166 this.el.update(D.join(""));
24167 this.nodes = this.el.dom.childNodes;
24168 this.updateIndexes(0);
24172 * Performs an async HTTP request, and loads the JSON from the response. If <i>params</i> are specified it uses POST, otherwise it uses GET.
24173 * @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:
24176 url: "your-url.php",
24177 params: {param1: "foo", param2: "bar"}, // or a URL encoded string
24178 callback: yourFunction,
24179 scope: yourObject, //(optional scope)
24182 text: "Loading...",
24187 * The only required property is <i>url</i>. The optional properties <i>nocache</i>, <i>text</i> and <i>scripts</i>
24188 * are respectively shorthand for <i>disableCaching</i>, <i>indicatorText</i>, and <i>loadScripts</i> and are used to set their associated property on this UpdateManager instance.
24189 * @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}
24190 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
24191 * @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.
24194 var um = this.el.getUpdateManager();
24195 um.update.apply(um, arguments);
24198 render : function(el, E){
24199 this.clearSelections();
24200 this.el.update("");
24203 o = Roo.util.JSON.decode(E.responseText);
24206 o = /** eval:var:o */ eval("o." + this.jsonRoot);
24212 * The current JSON data or null
24215 this.beforeRender();
24220 * Get the number of records in the current JSON dataset
24223 getCount : function(){
24224 return this.jsonData ? this.jsonData.length : 0;
24228 * Returns the JSON object for the specified node(s)
24229 * @param {HTMLElement/Array} node The node or an array of nodes
24230 * @return {Object/Array} If you pass in an array, you get an array back, otherwise
24231 * you get the JSON object for the node
24233 getNodeData : function(F){
24234 if(F instanceof Array){
24236 for(var i = 0, len = F.length; i < len; i++){
24237 data.push(this.getNodeData(F[i]));
24241 return this.jsonData[this.indexOf(F)] || null;
24244 beforeRender : function(){
24245 this.snapshot = this.jsonData;
24247 this.sort.apply(this, this.sortInfo);
24250 this.fireEvent("beforerender", this, this.jsonData);
24253 onLoad : function(el, o){
24254 this.fireEvent("load", this, this.jsonData, o);
24257 onLoadException : function(el, o){
24258 this.fireEvent("loadexception", this, o);
24262 * Filter the data by a specific property.
24263 * @param {String} property A property on your JSON objects
24264 * @param {String/RegExp} value Either string that the property values
24265 * should start with, or a RegExp to test against the property
24267 filter : function(G, H){
24270 var ss = this.snapshot;
24271 if(typeof H == "string"){
24272 var vlen = H.length;
24274 this.clearFilter();
24278 H = H.toLowerCase();
24279 for(var i = 0, len = ss.length; i < len; i++){
24281 if(o[G].substr(0, vlen).toLowerCase() == H){
24285 } else if(H.exec){ // regex?
24286 for(var i = 0, len = ss.length; i < len; i++){
24296 this.jsonData = data;
24302 * Filter by a function. The passed function will be called with each
24303 * object in the current dataset. If the function returns true the value is kept,
24304 * otherwise it is filtered.
24305 * @param {Function} fn
24306 * @param {Object} scope (optional) The scope of the function (defaults to this JsonView)
24308 filterBy : function(fn, I){
24311 var ss = this.snapshot;
24312 for(var i = 0, len = ss.length; i < len; i++){
24314 if(fn.call(I || this, o)){
24319 this.jsonData = data;
24325 * Clears the current filter.
24327 clearFilter : function(){
24328 if(this.snapshot && this.jsonData != this.snapshot){
24329 this.jsonData = this.snapshot;
24336 * Sorts the data for this view and refreshes it.
24337 * @param {String} property A property on your JSON objects to sort on
24338 * @param {String} direction (optional) "desc" or "asc" (defaults to "asc")
24339 * @param {Function} sortType (optional) A function to call to convert the data to a sortable value.
24341 sort : function(J, K, L){
24342 this.sortInfo = Array.prototype.slice.call(arguments, 0);
24345 var dsc = K && K.toLowerCase() == "desc";
24346 var f = function(o1, o2){
24347 var v1 = L ? L(o1[p]) : o1[p];
24348 var v2 = L ? L(o2[p]) : o2[p];
24351 return dsc ? +1 : -1;
24352 } else if(v1 > v2){
24353 return dsc ? -1 : +1;
24358 this.jsonData.sort(f);
24360 if(this.jsonData != this.snapshot){
24361 this.snapshot.sort(f);
24368 * Ext JS Library 1.1.1
24369 * Copyright(c) 2006-2007, Ext JS, LLC.
24371 * Originally Released Under LGPL - original licence link has changed is not relivant.
24374 * <script type="text/javascript">
24379 * @class Roo.ColorPalette
24380 * @extends Roo.Component
24381 * Simple color palette class for choosing colors. The palette can be rendered to any container.<br />
24382 * Here's an example of typical usage:
24384 var cp = new Roo.ColorPalette({value:'993300'}); // initial selected color
24385 cp.render('my-div');
24387 cp.on('select', function(palette, selColor){
24388 // do something with selColor
24392 * Create a new ColorPalette
24393 * @param {Object} config The config object
24395 Roo.ColorPalette = function(A){
24396 Roo.ColorPalette.superclass.constructor.call(this, A);
24400 * Fires when a color is selected
24401 * @param {ColorPalette} this
24402 * @param {String} color The 6-digit color hex code (without the # symbol)
24408 this.on("select", this.handler, this.scope, true);
24411 Roo.extend(Roo.ColorPalette, Roo.Component, {
24413 * @cfg {String} itemCls
24414 * The CSS class to apply to the containing element (defaults to "x-color-palette")
24416 itemCls : "x-color-palette",
24418 * @cfg {String} value
24419 * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol). Note that
24420 * the hex codes are case-sensitive.
24423 clickEvent:'click',
24425 ctype: "Roo.ColorPalette",
24428 * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the selection event
24430 allowReselect : false,
24433 * <p>An array of 6-digit color hex code strings (without the # symbol). This array can contain any number
24434 * of colors, and each hex code should be unique. The width of the palette is controlled via CSS by adjusting
24435 * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
24436 * of colors with the width setting until the box is symmetrical.</p>
24437 * <p>You can override individual colors if needed:</p>
24439 var cp = new Roo.ColorPalette();
24440 cp.colors[0] = "FF0000"; // change the first box to red
24443 Or you can provide a custom array of your own for complete control:
24445 var cp = new Roo.ColorPalette();
24446 cp.colors = ["000000", "993300", "333300"];
24451 "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
24452 "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
24453 "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
24454 "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
24455 "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
24459 onRender : function(B, C){
24460 var t = new Roo.MasterTemplate(
24461 '<tpl><a href="#" class="color-{0}" hidefocus="on"><em><span style="background:#{0}" unselectable="on"> </span></em></a></tpl>'
24463 var c = this.colors;
24464 for(var i = 0, len = c.length; i < len; i++){
24467 var el = document.createElement("div");
24468 el.className = this.itemCls;
24470 B.dom.insertBefore(el, C);
24471 this.el = Roo.get(el);
24472 this.el.on(this.clickEvent, this.handleClick, this, {delegate: "a"});
24473 if(this.clickEvent != 'click'){
24474 this.el.on('click', Roo.emptyFn, this, {delegate: "a", preventDefault:true});
24479 afterRender : function(){
24480 Roo.ColorPalette.superclass.afterRender.call(this);
24482 var s = this.value;
24489 handleClick : function(e, t){
24490 e.preventDefault();
24491 if(!this.disabled){
24492 var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
24493 this.select(c.toUpperCase());
24498 * Selects the specified color in the palette (fires the select event)
24499 * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
24501 select : function(D){
24502 D = D.replace("#", "");
24503 if(D != this.value || this.allowReselect){
24506 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
24509 el.child("a.color-"+D).addClass("x-color-palette-sel");
24511 this.fireEvent("select", this, D);
24517 * Ext JS Library 1.1.1
24518 * Copyright(c) 2006-2007, Ext JS, LLC.
24520 * Originally Released Under LGPL - original licence link has changed is not relivant.
24523 * <script type="text/javascript">
24527 * @class Roo.DatePicker
24528 * @extends Roo.Component
24529 * Simple date picker class.
24531 * Create a new DatePicker
24532 * @param {Object} config The config object
24534 Roo.DatePicker = function(A){
24535 Roo.DatePicker.superclass.constructor.call(this, A);
24537 this.value = A && A.value ?
24538 A.value.clearTime() : new Date().clearTime();
24543 * Fires when a date is selected
24544 * @param {DatePicker} this
24545 * @param {Date} date The selected date
24551 this.on("select", this.handler, this.scope || this);
24553 // build the disabledDatesRE
24554 if(!this.disabledDatesRE && this.disabledDates){
24555 var dd = this.disabledDates;
24557 for(var i = 0; i < dd.length; i++){
24559 if(i != dd.length-1) re += "|";
24562 this.disabledDatesRE = new RegExp(re + ")");
24566 Roo.extend(Roo.DatePicker, Roo.Component, {
24568 * @cfg {String} todayText
24569 * The text to display on the button that selects the current date (defaults to "Today")
24571 todayText : "Today",
24573 * @cfg {String} okText
24574 * The text to display on the ok button
24576 okText : " OK ", //   to give the user extra clicking room
24578 * @cfg {String} cancelText
24579 * The text to display on the cancel button
24581 cancelText : "Cancel",
24583 * @cfg {String} todayTip
24584 * The tooltip to display for the button that selects the current date (defaults to "{current date} (Spacebar)")
24586 todayTip : "{0} (Spacebar)",
24588 * @cfg {Date} minDate
24589 * Minimum allowable date (JavaScript date object, defaults to null)
24593 * @cfg {Date} maxDate
24594 * Maximum allowable date (JavaScript date object, defaults to null)
24598 * @cfg {String} minText
24599 * The error text to display if the minDate validation fails (defaults to "This date is before the minimum date")
24601 minText : "This date is before the minimum date",
24603 * @cfg {String} maxText
24604 * The error text to display if the maxDate validation fails (defaults to "This date is after the maximum date")
24606 maxText : "This date is after the maximum date",
24608 * @cfg {String} format
24609 * The default date format string which can be overriden for localization support. The format must be
24610 * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
24614 * @cfg {Array} disabledDays
24615 * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
24617 disabledDays : null,
24619 * @cfg {String} disabledDaysText
24620 * The tooltip to display when the date falls on a disabled day (defaults to "")
24622 disabledDaysText : "",
24624 * @cfg {RegExp} disabledDatesRE
24625 * JavaScript regular expression used to disable a pattern of dates (defaults to null)
24627 disabledDatesRE : null,
24629 * @cfg {String} disabledDatesText
24630 * The tooltip text to display when the date falls on a disabled date (defaults to "")
24632 disabledDatesText : "",
24634 * @cfg {Boolean} constrainToViewport
24635 * True to constrain the date picker to the viewport (defaults to true)
24637 constrainToViewport : true,
24639 * @cfg {Array} monthNames
24640 * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
24642 monthNames : Date.monthNames,
24644 * @cfg {Array} dayNames
24645 * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
24647 dayNames : Date.dayNames,
24649 * @cfg {String} nextText
24650 * The next month navigation button tooltip (defaults to 'Next Month (Control+Right)')
24652 nextText: 'Next Month (Control+Right)',
24654 * @cfg {String} prevText
24655 * The previous month navigation button tooltip (defaults to 'Previous Month (Control+Left)')
24657 prevText: 'Previous Month (Control+Left)',
24659 * @cfg {String} monthYearText
24660 * The header month selector tooltip (defaults to 'Choose a month (Control+Up/Down to move years)')
24662 monthYearText: 'Choose a month (Control+Up/Down to move years)',
24664 * @cfg {Number} startDay
24665 * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
24669 * @cfg {Bool} showClear
24670 * Show a clear button (usefull for date form elements that can be blank.)
24676 * Sets the value of the date field
24677 * @param {Date} value The date to set
24679 setValue : function(B){
24680 var C = this.value;
24681 this.value = B.clearTime(true);
24683 this.update(this.value);
24688 * Gets the current selected value of the date field
24689 * @return {Date} The selected date
24691 getValue : function(){
24696 focus : function(){
24698 this.update(this.activeDate);
24703 onRender : function(D, E){
24705 '<table cellspacing="0">',
24706 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>',
24707 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
24708 var dn = this.dayNames;
24709 for(var i = 0; i < 7; i++){
24710 var d = this.startDay+i;
24715 m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
24718 m[m.length] = "</tr></thead><tbody><tr>";
24719 for(var i = 0; i < 42; i++) {
24720 if(i % 7 == 0 && i != 0){
24721 m[m.length] = "</tr><tr>";
24724 m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
24727 m[m.length] = '</tr></tbody></table></td></tr><tr>'+
24728 '<td colspan="3" class="x-date-bottom" align="center"></td></tr></table><div class="x-date-mp"></div>';
24730 var el = document.createElement("div");
24731 el.className = "x-date-picker";
24732 el.innerHTML = m.join("");
24734 D.dom.insertBefore(el, E);
24736 this.el = Roo.get(el);
24737 this.eventEl = Roo.get(el.firstChild);
24739 new Roo.util.ClickRepeater(this.el.child("td.x-date-left a"), {
24740 handler: this.showPrevMonth,
24742 preventDefault:true,
24746 new Roo.util.ClickRepeater(this.el.child("td.x-date-right a"), {
24747 handler: this.showNextMonth,
24749 preventDefault:true,
24753 this.eventEl.on("mousewheel", this.handleMouseWheel, this);
24755 this.monthPicker = this.el.down('div.x-date-mp');
24756 this.monthPicker.enableDisplayMode('block');
24758 var kn = new Roo.KeyNav(this.eventEl, {
24759 "left" : function(e){
24761 this.showPrevMonth() :
24762 this.update(this.activeDate.add("d", -1));
24765 "right" : function(e){
24767 this.showNextMonth() :
24768 this.update(this.activeDate.add("d", 1));
24771 "up" : function(e){
24773 this.showNextYear() :
24774 this.update(this.activeDate.add("d", -7));
24777 "down" : function(e){
24779 this.showPrevYear() :
24780 this.update(this.activeDate.add("d", 7));
24783 "pageUp" : function(e){
24784 this.showNextMonth();
24787 "pageDown" : function(e){
24788 this.showPrevMonth();
24791 "enter" : function(e){
24792 e.stopPropagation();
24799 this.eventEl.on("click", this.handleDateClick, this, {delegate: "a.x-date-date"});
24801 this.eventEl.addKeyListener(Roo.EventObject.SPACE, this.selectToday, this);
24803 this.el.unselectable();
24805 this.cells = this.el.select("table.x-date-inner tbody td");
24806 this.textNodes = this.el.query("table.x-date-inner tbody span");
24808 this.mbtn = new Roo.Button(this.el.child("td.x-date-middle", true), {
24810 tooltip: this.monthYearText
24813 this.mbtn.on('click', this.showMonthPicker, this);
24814 this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");
24817 var F = (new Date()).dateFormat(this.format);
24819 var G = new Roo.Toolbar(this.el.child("td.x-date-bottom", true));
24821 text: String.format(this.todayText, F),
24822 tooltip: String.format(this.todayTip, F),
24823 handler: this.selectToday,
24827 //var todayBtn = new Roo.Button(this.el.child("td.x-date-bottom", true), {
24830 if (this.showClear) {
24832 G.add( new Roo.Toolbar.Fill());
24835 cls: 'x-btn-icon x-btn-clear',
24836 handler: function() {
24838 this.fireEvent("select", this, '');
24849 this.update(this.value);
24852 createMonthPicker : function(){
24853 if(!this.monthPicker.dom.firstChild){
24854 var buf = ['<table border="0" cellspacing="0">'];
24855 for(var i = 0; i < 6; i++){
24857 '<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',
24858 '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',
24860 '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
24861 '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
24866 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
24868 '</button><button type="button" class="x-date-mp-cancel">',
24870 '</button></td></tr>',
24873 this.monthPicker.update(buf.join(''));
24874 this.monthPicker.on('click', this.onMonthClick, this);
24875 this.monthPicker.on('dblclick', this.onMonthDblClick, this);
24877 this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
24878 this.mpYears = this.monthPicker.select('td.x-date-mp-year');
24880 this.mpMonths.each(function(m, a, i){
24883 m.dom.xmonth = 5 + Math.round(i * .5);
24885 m.dom.xmonth = Math.round((i-1) * .5);
24891 showMonthPicker : function(){
24892 this.createMonthPicker();
24893 var H = this.el.getSize();
24894 this.monthPicker.setSize(H);
24895 this.monthPicker.child('table').setSize(H);
24897 this.mpSelMonth = (this.activeDate || this.value).getMonth();
24898 this.updateMPMonth(this.mpSelMonth);
24899 this.mpSelYear = (this.activeDate || this.value).getFullYear();
24900 this.updateMPYear(this.mpSelYear);
24902 this.monthPicker.slideIn('t', {duration:.2});
24905 updateMPYear : function(y){
24907 var ys = this.mpYears.elements;
24908 for(var i = 1; i <= 10; i++){
24909 var td = ys[i-1], y2;
24911 y2 = y + Math.round(i * .5);
24912 td.firstChild.innerHTML = y2;
24915 y2 = y - (5-Math.round(i * .5));
24916 td.firstChild.innerHTML = y2;
24920 this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
24924 updateMPMonth : function(sm){
24925 this.mpMonths.each(function(m, a, i){
24926 m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
24930 selectMPMonth: function(m){
24934 onMonthClick : function(e, t){
24936 var el = new Roo.Element(t), pn;
24937 if(el.is('button.x-date-mp-cancel')){
24938 this.hideMonthPicker();
24940 else if(el.is('button.x-date-mp-ok')){
24941 this.update(new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
24942 this.hideMonthPicker();
24944 else if(pn = el.up('td.x-date-mp-month', 2)){
24945 this.mpMonths.removeClass('x-date-mp-sel');
24946 pn.addClass('x-date-mp-sel');
24947 this.mpSelMonth = pn.dom.xmonth;
24949 else if(pn = el.up('td.x-date-mp-year', 2)){
24950 this.mpYears.removeClass('x-date-mp-sel');
24951 pn.addClass('x-date-mp-sel');
24952 this.mpSelYear = pn.dom.xyear;
24954 else if(el.is('a.x-date-mp-prev')){
24955 this.updateMPYear(this.mpyear-10);
24957 else if(el.is('a.x-date-mp-next')){
24958 this.updateMPYear(this.mpyear+10);
24962 onMonthDblClick : function(e, t){
24964 var el = new Roo.Element(t), pn;
24965 if(pn = el.up('td.x-date-mp-month', 2)){
24966 this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
24967 this.hideMonthPicker();
24969 else if(pn = el.up('td.x-date-mp-year', 2)){
24970 this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
24971 this.hideMonthPicker();
24975 hideMonthPicker : function(I){
24976 if(this.monthPicker){
24978 this.monthPicker.hide();
24980 this.monthPicker.slideOut('t', {duration:.2});
24986 showPrevMonth : function(e){
24987 this.update(this.activeDate.add("mo", -1));
24991 showNextMonth : function(e){
24992 this.update(this.activeDate.add("mo", 1));
24996 showPrevYear : function(){
24997 this.update(this.activeDate.add("y", -1));
25001 showNextYear : function(){
25002 this.update(this.activeDate.add("y", 1));
25006 handleMouseWheel : function(e){
25007 var J = e.getWheelDelta();
25009 this.showPrevMonth();
25012 this.showNextMonth();
25018 handleDateClick : function(e, t){
25020 if(t.dateValue && !Roo.fly(t.parentNode).hasClass("x-date-disabled")){
25021 this.setValue(new Date(t.dateValue));
25022 this.fireEvent("select", this, this.value);
25027 selectToday : function(){
25028 this.setValue(new Date().clearTime());
25029 this.fireEvent("select", this, this.value);
25033 update : function(K){
25034 var vd = this.activeDate;
25035 this.activeDate = K;
25037 var t = K.getTime();
25038 if(vd.getMonth() == K.getMonth() && vd.getFullYear() == K.getFullYear()){
25039 this.cells.removeClass("x-date-selected");
25040 this.cells.each(function(c){
25041 if(c.dom.firstChild.dateValue == t){
25042 c.addClass("x-date-selected");
25043 setTimeout(function(){
25044 try{c.dom.firstChild.focus();}catch(e){}
25052 var L = K.getDaysInMonth();
25053 var M = K.getFirstDateOfMonth();
25054 var N = M.getDay()-this.startDay;
25056 if(N <= this.startDay){
25060 var pm = K.add("mo", -1);
25061 var O = pm.getDaysInMonth()-N;
25063 var P = this.cells.elements;
25064 var Q = this.textNodes;
25067 // convert everything to numbers so it's fast
25069 var d = (new Date(pm.getFullYear(), pm.getMonth(), O)).clearTime();
25070 var S = new Date().clearTime().getTime();
25071 var T = K.clearTime().getTime();
25072 var U = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
25073 var V = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
25074 var W = this.disabledDatesRE;
25075 var X = this.disabledDatesText;
25076 var Y = this.disabledDays ? this.disabledDays.join("") : false;
25077 var Z = this.disabledDaysText;
25078 var a = this.format;
25080 var b = function(f, g){
25082 var t = d.getTime();
25083 g.firstChild.dateValue = t;
25085 g.className += " x-date-today";
25086 g.title = f.todayText;
25089 g.className += " x-date-selected";
25090 setTimeout(function(){
25091 try{g.firstChild.focus();}catch(e){}
25096 g.className = " x-date-disabled";
25097 g.title = f.minText;
25101 g.className = " x-date-disabled";
25102 g.title = f.maxText;
25106 if(Y.indexOf(d.getDay()) != -1){
25108 g.className = " x-date-disabled";
25112 var fvalue = d.dateFormat(a);
25113 if(W.test(fvalue)){
25114 g.title = X.replace("%0", fvalue);
25115 g.className = " x-date-disabled";
25121 for(; i < N; i++) {
25122 Q[i].innerHTML = (++O);
25123 d.setDate(d.getDate()+1);
25124 P[i].className = "x-date-prevday";
25128 intDay = i - N + 1;
25129 Q[i].innerHTML = (intDay);
25130 d.setDate(d.getDate()+1);
25131 P[i].className = "x-date-active";
25135 for(; i < 42; i++) {
25136 Q[i].innerHTML = (++c);
25137 d.setDate(d.getDate()+1);
25138 P[i].className = "x-date-nextday";
25143 this.mbtn.setText(this.monthNames[K.getMonth()] + " " + K.getFullYear());
25145 if(!this.internalRender){
25146 var main = this.el.dom.firstChild;
25147 var w = main.offsetWidth;
25148 this.el.setWidth(w + this.el.getBorderWidth("lr"));
25149 Roo.fly(main).setWidth(w);
25150 this.internalRender = true;
25151 // opera does not respect the auto grow header center column
25152 // then, after it gets a width opera refuses to recalculate
25153 // without a second pass
25154 if(Roo.isOpera && !this.secondPass){
25155 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
25156 this.secondPass = true;
25157 this.update.defer(10, this, [K]);
25164 * Ext JS Library 1.1.1
25165 * Copyright(c) 2006-2007, Ext JS, LLC.
25167 * Originally Released Under LGPL - original licence link has changed is not relivant.
25170 * <script type="text/javascript">
25173 * @class Roo.TabPanel
25174 * @extends Roo.util.Observable
25175 * A lightweight tab container.
25179 // basic tabs 1, built from existing content
25180 var tabs = new Roo.TabPanel("tabs1");
25181 tabs.addTab("script", "View Script");
25182 tabs.addTab("markup", "View Markup");
25183 tabs.activate("script");
25185 // more advanced tabs, built from javascript
25186 var jtabs = new Roo.TabPanel("jtabs");
25187 jtabs.addTab("jtabs-1", "Normal Tab", "My content was added during construction.");
25189 // set up the UpdateManager
25190 var tab2 = jtabs.addTab("jtabs-2", "Ajax Tab 1");
25191 var updater = tab2.getUpdateManager();
25192 updater.setDefaultUrl("ajax1.htm");
25193 tab2.on('activate', updater.refresh, updater, true);
25195 // Use setUrl for Ajax loading
25196 var tab3 = jtabs.addTab("jtabs-3", "Ajax Tab 2");
25197 tab3.setUrl("ajax2.htm", null, true);
25200 var tab4 = jtabs.addTab("tabs1-5", "Disabled Tab", "Can't see me cause I'm disabled");
25203 jtabs.activate("jtabs-1");
25206 * Create a new TabPanel.
25207 * @param {String/HTMLElement/Roo.Element} container The id, DOM element or Roo.Element container where this TabPanel is to be rendered.
25208 * @param {Object/Boolean} config Config object to set any properties for this TabPanel, or true to render the tabs on the bottom.
25210 Roo.TabPanel = function(A, B){
25212 * The container element for this TabPanel.
25213 * @type Roo.Element
25215 this.el = Roo.get(A, true);
25217 if(typeof B == "boolean"){
25218 this.tabPosition = B ? "bottom" : "top";
25220 Roo.apply(this, B);
25223 if(this.tabPosition == "bottom"){
25224 this.bodyEl = Roo.get(this.createBody(this.el.dom));
25225 this.el.addClass("x-tabs-bottom");
25228 this.stripWrap = Roo.get(this.createStrip(this.el.dom), true);
25229 this.stripEl = Roo.get(this.createStripList(this.stripWrap.dom), true);
25230 this.stripBody = Roo.get(this.stripWrap.dom.firstChild.firstChild, true);
25232 Roo.fly(this.stripWrap.dom.firstChild).setStyle("overflow-x", "hidden");
25234 if(this.tabPosition != "bottom"){
25235 /** The body element that contains {@link Roo.TabPanelItem} bodies.
25236 * @type Roo.Element
25238 this.bodyEl = Roo.get(this.createBody(this.el.dom));
25239 this.el.addClass("x-tabs-top");
25244 this.bodyEl.setStyle("position", "relative");
25246 this.active = null;
25247 this.activateDelegate = this.activate.createDelegate(this);
25252 * Fires when the active tab changes
25253 * @param {Roo.TabPanel} this
25254 * @param {Roo.TabPanelItem} activePanel The new active tab
25258 * @event beforetabchange
25259 * Fires before the active tab changes, set cancel to true on the "e" parameter to cancel the change
25260 * @param {Roo.TabPanel} this
25261 * @param {Object} e Set cancel to true on this object to cancel the tab change
25262 * @param {Roo.TabPanelItem} tab The tab being changed to
25264 "beforetabchange" : true
25267 Roo.EventManager.onWindowResize(this.onResize, this);
25268 this.cpad = this.el.getPadding("lr");
25269 this.hiddenCount = 0;
25271 Roo.TabPanel.superclass.constructor.call(this);
25274 Roo.extend(Roo.TabPanel, Roo.util.Observable, {
25276 *@cfg {String} tabPosition "top" or "bottom" (defaults to "top")
25278 tabPosition : "top",
25280 *@cfg {Number} currentTabWidth The width of the current tab (defaults to 0)
25282 currentTabWidth : 0,
25284 *@cfg {Number} minTabWidth The minimum width of a tab (defaults to 40) (ignored if {@link #resizeTabs} is not true)
25288 *@cfg {Number} maxTabWidth The maximum width of a tab (defaults to 250) (ignored if {@link #resizeTabs} is not true)
25292 *@cfg {Number} preferredTabWidth The preferred (default) width of a tab (defaults to 175) (ignored if {@link #resizeTabs} is not true)
25294 preferredTabWidth : 175,
25296 *@cfg {Boolean} resizeTabs True to enable dynamic tab resizing (defaults to false)
25298 resizeTabs : false,
25300 *@cfg {Boolean} monitorResize Set this to true to turn on window resize monitoring (ignored if {@link #resizeTabs} is not true) (defaults to true)
25302 monitorResize : true,
25305 * Creates a new {@link Roo.TabPanelItem} by looking for an existing element with the provided id -- if it's not found it creates one.
25306 * @param {String} id The id of the div to use <b>or create</b>
25307 * @param {String} text The text for the tab
25308 * @param {String} content (optional) Content to put in the TabPanelItem body
25309 * @param {Boolean} closable (optional) True to create a close icon on the tab
25310 * @return {Roo.TabPanelItem} The created TabPanelItem
25312 addTab : function(id, C, D, E){
25313 var F = new Roo.TabPanelItem(this, id, C, E);
25314 this.addTabItem(F);
25322 * Returns the {@link Roo.TabPanelItem} with the specified id/index
25323 * @param {String/Number} id The id or index of the TabPanelItem to fetch.
25324 * @return {Roo.TabPanelItem}
25326 getTab : function(id){
25327 return this.items[id];
25331 * Hides the {@link Roo.TabPanelItem} with the specified id/index
25332 * @param {String/Number} id The id or index of the TabPanelItem to hide.
25334 hideTab : function(id){
25335 var t = this.items[id];
25338 this.hiddenCount++;
25339 this.autoSizeTabs();
25344 * "Unhides" the {@link Roo.TabPanelItem} with the specified id/index.
25345 * @param {String/Number} id The id or index of the TabPanelItem to unhide.
25347 unhideTab : function(id){
25348 var t = this.items[id];
25350 t.setHidden(false);
25351 this.hiddenCount--;
25352 this.autoSizeTabs();
25357 * Adds an existing {@link Roo.TabPanelItem}.
25358 * @param {Roo.TabPanelItem} item The TabPanelItem to add
25360 addTabItem : function(G){
25361 this.items[G.id] = G;
25362 this.items.push(G);
25363 if(this.resizeTabs){
25364 G.setWidth(this.currentTabWidth || this.preferredTabWidth);
25365 this.autoSizeTabs();
25372 * Removes a {@link Roo.TabPanelItem}.
25373 * @param {String/Number} id The id or index of the TabPanelItem to remove.
25375 removeTab : function(id){
25376 var H = this.items;
25379 var J = H.indexOf(I);
25380 if(this.active == I && H.length > 1){
25381 var newTab = this.getNextAvailable(J);
25382 if(newTab)newTab.activate();
25385 this.stripEl.dom.removeChild(I.pnode.dom);
25386 if(I.bodyEl.dom.parentNode == this.bodyEl.dom){ // if it was moved already prevent error
25387 this.bodyEl.dom.removeChild(I.bodyEl.dom);
25391 delete this.items[I.id];
25392 I.fireEvent("close", I);
25393 I.purgeListeners();
25394 this.autoSizeTabs();
25397 getNextAvailable : function(K){
25398 var L = this.items;
25400 // look for a next tab that will slide over to
25401 // replace the one being removed
25402 while(M < L.length){
25404 if(G && !G.isHidden()){
25409 // if one isn't found select the previous tab (on the left)
25413 if(G && !G.isHidden()){
25421 * Disables a {@link Roo.TabPanelItem}. It cannot be the active tab, if it is this call is ignored.
25422 * @param {String/Number} id The id or index of the TabPanelItem to disable.
25424 disableTab : function(id){
25425 var N = this.items[id];
25426 if(N && this.active != N){
25432 * Enables a {@link Roo.TabPanelItem} that is disabled.
25433 * @param {String/Number} id The id or index of the TabPanelItem to enable.
25435 enableTab : function(id){
25436 var O = this.items[id];
25441 * Activates a {@link Roo.TabPanelItem}. The currently active one will be deactivated.
25442 * @param {String/Number} id The id or index of the TabPanelItem to activate.
25443 * @return {Roo.TabPanelItem} The TabPanelItem.
25445 activate : function(id){
25446 var P = this.items[id];
25450 if(P == this.active || P.disabled){
25454 this.fireEvent("beforetabchange", this, e, P);
25455 if(e.cancel !== true && !P.disabled){
25457 this.active.hide();
25460 this.active = this.items[id];
25461 this.active.show();
25462 this.fireEvent("tabchange", this, this.active);
25468 * Gets the active {@link Roo.TabPanelItem}.
25469 * @return {Roo.TabPanelItem} The active TabPanelItem or null if none are active.
25471 getActiveTab : function(){
25472 return this.active;
25476 * Updates the tab body element to fit the height of the container element
25477 * for overflow scrolling
25478 * @param {Number} targetHeight (optional) Override the starting height from the elements height
25480 syncHeight : function(Q){
25481 var R = (Q || this.el.getHeight())-this.el.getBorderWidth("tb")-this.el.getPadding("tb");
25482 var bm = this.bodyEl.getMargins();
25483 var S = R-(this.stripWrap.getHeight()||0)-(bm.top+bm.bottom);
25484 this.bodyEl.setHeight(S);
25488 onResize : function(){
25489 if(this.monitorResize){
25490 this.autoSizeTabs();
25495 * Disables tab resizing while tabs are being added (if {@link #resizeTabs} is false this does nothing)
25497 beginUpdate : function(){
25498 this.updating = true;
25502 * Stops an update and resizes the tabs (if {@link #resizeTabs} is false this does nothing)
25504 endUpdate : function(){
25505 this.updating = false;
25506 this.autoSizeTabs();
25510 * Manual call to resize the tabs (if {@link #resizeTabs} is false this does nothing)
25512 autoSizeTabs : function(){
25513 var T = this.items.length;
25514 var U = T - this.hiddenCount;
25515 if(!this.resizeTabs || T < 1 || U < 1 || this.updating) return;
25516 var w = Math.max(this.el.getWidth() - this.cpad, 10);
25517 var V = Math.floor(w / U);
25518 var b = this.stripBody;
25519 if(b.getWidth() > w){
25520 var tabs = this.items;
25521 this.setTabWidth(Math.max(V, this.minTabWidth)-2);
25522 if(V < this.minTabWidth){
25523 /*if(!this.sleft){ // incomplete scrolling code
25524 this.createScrollButtons();
25527 this.stripClip.setWidth(w - (this.sleft.getWidth()+this.sright.getWidth()));*/
25530 if(this.currentTabWidth < this.preferredTabWidth){
25531 this.setTabWidth(Math.min(V, this.preferredTabWidth)-2);
25537 * Returns the number of tabs in this TabPanel.
25540 getCount : function(){
25541 return this.items.length;
25545 * Resizes all the tabs to the passed width
25546 * @param {Number} The new width
25548 setTabWidth : function(W){
25549 this.currentTabWidth = W;
25550 for(var i = 0, len = this.items.length; i < len; i++) {
25551 if(!this.items[i].isHidden())this.items[i].setWidth(W);
25556 * Destroys this TabPanel
25557 * @param {Boolean} removeEl (optional) True to remove the element from the DOM as well (defaults to undefined)
25559 destroy : function(X){
25560 Roo.EventManager.removeResizeListener(this.onResize, this);
25561 for(var i = 0, len = this.items.length; i < len; i++){
25562 this.items[i].purgeListeners();
25565 this.el.update("");
25572 * @class Roo.TabPanelItem
25573 * @extends Roo.util.Observable
25574 * Represents an individual item (tab plus body) in a TabPanel.
25575 * @param {Roo.TabPanel} tabPanel The {@link Roo.TabPanel} this TabPanelItem belongs to
25576 * @param {String} id The id of this TabPanelItem
25577 * @param {String} text The text for the tab of this TabPanelItem
25578 * @param {Boolean} closable True to allow this TabPanelItem to be closable (defaults to false)
25580 Roo.TabPanelItem = function(Y, id, Z, a){
25582 * The {@link Roo.TabPanel} this TabPanelItem belongs to
25583 * @type Roo.TabPanel
25587 * The id for this TabPanelItem
25592 this.disabled = false;
25596 this.loaded = false;
25600 * The body element for this TabPanelItem.
25601 * @type Roo.Element
25603 this.bodyEl = Roo.get(Y.createItemBody(Y.bodyEl.dom, id));
25604 this.bodyEl.setVisibilityMode(Roo.Element.VISIBILITY);
25605 this.bodyEl.setStyle("display", "block");
25606 this.bodyEl.setStyle("zoom", "1");
25609 var d = Y.createStripElements(Y.stripEl.dom, Z, a);
25611 this.el = Roo.get(d.el, true);
25612 this.inner = Roo.get(d.inner, true);
25613 this.textEl = Roo.get(this.el.dom.firstChild.firstChild.firstChild, true);
25614 this.pnode = Roo.get(d.el.parentNode, true);
25615 this.el.on("mousedown", this.onTabMouseDown, this);
25616 this.el.on("click", this.onTabClick, this);
25619 var c = Roo.get(d.close, true);
25620 c.dom.title = this.closeText;
25621 c.addClassOnOver("close-over");
25622 c.on("click", this.closeClick, this);
25629 * Fires when this tab becomes the active tab.
25630 * @param {Roo.TabPanel} tabPanel The parent TabPanel
25631 * @param {Roo.TabPanelItem} this
25635 * @event beforeclose
25636 * Fires before this tab is closed. To cancel the close, set cancel to true on e (e.cancel = true).
25637 * @param {Roo.TabPanelItem} this
25638 * @param {Object} e Set cancel to true on this object to cancel the close.
25640 "beforeclose": true,
25643 * Fires when this tab is closed.
25644 * @param {Roo.TabPanelItem} this
25648 * @event deactivate
25649 * Fires when this tab is no longer the active tab.
25650 * @param {Roo.TabPanel} tabPanel The parent TabPanel
25651 * @param {Roo.TabPanelItem} this
25653 "deactivate" : true
25655 this.hidden = false;
25657 Roo.TabPanelItem.superclass.constructor.call(this);
25660 Roo.extend(Roo.TabPanelItem, Roo.util.Observable, {
25661 purgeListeners : function(){
25662 Roo.util.Observable.prototype.purgeListeners.call(this);
25663 this.el.removeAllListeners();
25666 * Shows this TabPanelItem -- this <b>does not</b> deactivate the currently active TabPanelItem.
25669 this.pnode.addClass("on");
25672 this.tabPanel.stripWrap.repaint();
25675 this.fireEvent("activate", this.tabPanel, this);
25679 * Returns true if this tab is the active tab.
25680 * @return {Boolean}
25682 isActive : function(){
25683 return this.tabPanel.getActiveTab() == this;
25687 * Hides this TabPanelItem -- if you don't activate another TabPanelItem this could look odd.
25690 this.pnode.removeClass("on");
25692 this.fireEvent("deactivate", this.tabPanel, this);
25695 hideAction : function(){
25696 this.bodyEl.hide();
25697 this.bodyEl.setStyle("position", "absolute");
25698 this.bodyEl.setLeft("-20000px");
25699 this.bodyEl.setTop("-20000px");
25702 showAction : function(){
25703 this.bodyEl.setStyle("position", "relative");
25704 this.bodyEl.setTop("");
25705 this.bodyEl.setLeft("");
25706 this.bodyEl.show();
25710 * Set the tooltip for the tab.
25711 * @param {String} tooltip The tab's tooltip
25713 setTooltip : function(f){
25714 if(Roo.QuickTips && Roo.QuickTips.isEnabled()){
25715 this.textEl.dom.qtip = f;
25716 this.textEl.dom.removeAttribute('title');
25718 this.textEl.dom.title = f;
25722 onTabClick : function(e){
25723 e.preventDefault();
25724 this.tabPanel.activate(this.id);
25727 onTabMouseDown : function(e){
25728 e.preventDefault();
25729 this.tabPanel.activate(this.id);
25732 getWidth : function(){
25733 return this.inner.getWidth();
25736 setWidth : function(g){
25737 var h = g - this.pnode.getPadding("lr");
25738 this.inner.setWidth(h);
25739 this.textEl.setWidth(h-this.inner.getPadding("lr"));
25740 this.pnode.setWidth(g);
25744 * Show or hide the tab
25745 * @param {Boolean} hidden True to hide or false to show.
25747 setHidden : function(j){
25749 this.pnode.setStyle("display", j ? "none" : "");
25753 * Returns true if this tab is "hidden"
25754 * @return {Boolean}
25756 isHidden : function(){
25757 return this.hidden;
25761 * Returns the text for this tab
25764 getText : function(){
25768 autoSize : function(){
25769 //this.el.beginMeasure();
25770 this.textEl.setWidth(1);
25771 this.setWidth(this.textEl.dom.scrollWidth+this.pnode.getPadding("lr")+this.inner.getPadding("lr"));
25772 //this.el.endMeasure();
25776 * Sets the text for the tab (Note: this also sets the tooltip text)
25777 * @param {String} text The tab's text and tooltip
25779 setText : function(k){
25781 this.textEl.update(k);
25782 this.setTooltip(k);
25783 if(!this.tabPanel.resizeTabs){
25788 * Activates this TabPanelItem -- this <b>does</b> deactivate the currently active TabPanelItem.
25790 activate : function(){
25791 this.tabPanel.activate(this.id);
25795 * Disables this TabPanelItem -- this does nothing if this is the active TabPanelItem.
25797 disable : function(){
25798 if(this.tabPanel.active != this){
25799 this.disabled = true;
25800 this.pnode.addClass("disabled");
25805 * Enables this TabPanelItem if it was previously disabled.
25807 enable : function(){
25808 this.disabled = false;
25809 this.pnode.removeClass("disabled");
25813 * Sets the content for this TabPanelItem.
25814 * @param {String} content The content
25815 * @param {Boolean} loadScripts true to look for and load scripts
25817 setContent : function(l, m){
25818 this.bodyEl.update(l, m);
25822 * Gets the {@link Roo.UpdateManager} for the body of this TabPanelItem. Enables you to perform Ajax updates.
25823 * @return {Roo.UpdateManager} The UpdateManager
25825 getUpdateManager : function(){
25826 return this.bodyEl.getUpdateManager();
25830 * Set a URL to be used to load the content for this TabPanelItem.
25831 * @param {String/Function} url The URL to load the content from, or a function to call to get the URL
25832 * @param {String/Object} params (optional) The string params for the update call or an object of the params. See {@link Roo.UpdateManager#update} for more details. (Defaults to null)
25833 * @param {Boolean} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this TabPanelItem is activated. (Defaults to false)
25834 * @return {Roo.UpdateManager} The UpdateManager
25836 setUrl : function(n, o, p){
25837 if(this.refreshDelegate){
25838 this.un('activate', this.refreshDelegate);
25841 this.refreshDelegate = this._handleRefresh.createDelegate(this, [n, o, p]);
25842 this.on("activate", this.refreshDelegate);
25843 return this.bodyEl.getUpdateManager();
25847 _handleRefresh : function(q, r, s){
25848 if(!s || !this.loaded){
25849 var updater = this.bodyEl.getUpdateManager();
25850 updater.update(q, r, this._setLoaded.createDelegate(this));
25855 * Forces a content refresh from the URL specified in the {@link #setUrl} method.
25856 * Will fail silently if the setUrl method has not been called.
25857 * This does not activate the panel, just updates its content.
25859 refresh : function(){
25860 if(this.refreshDelegate){
25861 this.loaded = false;
25862 this.refreshDelegate();
25867 _setLoaded : function(){
25868 this.loaded = true;
25872 closeClick : function(e){
25875 this.fireEvent("beforeclose", this, o);
25876 if(o.cancel !== true){
25877 this.tabPanel.removeTab(this.id);
25881 * The text displayed in the tooltip for the close icon.
25884 closeText : "Close this tab"
25888 Roo.TabPanel.prototype.createStrip = function(u){
25889 var v = document.createElement("div");
25890 v.className = "x-tabs-wrap";
25895 Roo.TabPanel.prototype.createStripList = function(x){
25896 // div wrapper for retard IE
25897 x.innerHTML = '<div class="x-tabs-strip-wrap"><table class="x-tabs-strip" cellspacing="0" cellpadding="0" border="0"><tbody><tr></tr></tbody></table></div>';
25898 return x.firstChild.firstChild.firstChild.firstChild;
25901 Roo.TabPanel.prototype.createBody = function(y){
25902 var z = document.createElement("div");
25903 Roo.id(z, "tab-body");
25904 Roo.fly(z).addClass("x-tabs-body");
25909 Roo.TabPanel.prototype.createItemBody = function(AA, id){
25910 var AB = Roo.getDom(id);
25912 AB = document.createElement("div");
25916 Roo.fly(AB).addClass("x-tabs-item-body");
25917 AA.insertBefore(AB, AA.firstChild);
25921 Roo.TabPanel.prototype.createStripElements = function(AC, AD, AE){
25922 var td = document.createElement("td");
25923 AC.appendChild(td);
25925 td.className = "x-tabs-closable";
25926 if(!this.closeTpl){
25927 this.closeTpl = new Roo.Template(
25928 '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
25929 '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span>' +
25930 '<div unselectable="on" class="close-icon"> </div></em></span></a>'
25933 var el = this.closeTpl.overwrite(td, {"text": AD});
25934 var close = el.getElementsByTagName("div")[0];
25935 var inner = el.getElementsByTagName("em")[0];
25936 return {"el": el, "close": close, "inner": inner};
25939 this.tabTpl = new Roo.Template(
25940 '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
25941 '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span></em></span></a>'
25944 var el = this.tabTpl.overwrite(td, {"text": AD});
25945 var inner = el.getElementsByTagName("em")[0];
25946 return {"el": el, "inner": inner};
25951 * Ext JS Library 1.1.1
25952 * Copyright(c) 2006-2007, Ext JS, LLC.
25954 * Originally Released Under LGPL - original licence link has changed is not relivant.
25957 * <script type="text/javascript">
25961 * @class Roo.Button
25962 * @extends Roo.util.Observable
25963 * Simple Button class
25964 * @cfg {String} text The button text
25965 * @cfg {String} icon The path to an image to display in the button (the image will be set as the background-image
25966 * CSS property of the button by default, so if you want a mixed icon/text button, set cls:"x-btn-text-icon")
25967 * @cfg {Function} handler A function called when the button is clicked (can be used instead of click event)
25968 * @cfg {Object} scope The scope of the handler
25969 * @cfg {Number} minWidth The minimum width for this button (used to give a set of buttons a common width)
25970 * @cfg {String/Object} tooltip The tooltip for the button - can be a string or QuickTips config object
25971 * @cfg {Boolean} hidden True to start hidden (defaults to false)
25972 * @cfg {Boolean} disabled True to start disabled (defaults to false)
25973 * @cfg {Boolean} pressed True to start pressed (only if enableToggle = true)
25974 * @cfg {String} toggleGroup The group this toggle button is a member of (only 1 per group can be pressed, only
25975 applies if enableToggle = true)
25976 * @cfg {String/HTMLElement/Element} renderTo The element to append the button to
25977 * @cfg {Boolean/Object} repeat True to repeat fire the click event while the mouse is down. This can also be
25978 an {@link Roo.util.ClickRepeater} config object (defaults to false).
25980 * Create a new button
25981 * @param {Object} config The config object
25983 Roo.Button = function(A, B)
25987 A = B.renderTo || false;
25991 Roo.apply(this, B);
25995 * Fires when this button is clicked
25996 * @param {Button} this
25997 * @param {EventObject} e The click event
26002 * Fires when the "pressed" state of this button changes (only if enableToggle = true)
26003 * @param {Button} this
26004 * @param {Boolean} pressed
26009 * Fires when the mouse hovers over the button
26010 * @param {Button} this
26011 * @param {Event} e The event object
26013 'mouseover' : true,
26016 * Fires when the mouse exits the button
26017 * @param {Button} this
26018 * @param {Event} e The event object
26023 * Fires when the button is rendered
26024 * @param {Button} this
26029 this.menu = Roo.menu.MenuMgr.get(this.menu);
26036 Roo.util.Observable.call(this);
26039 Roo.extend(Roo.Button, Roo.util.Observable, {
26045 * Read-only. True if this button is hidden
26050 * Read-only. True if this button is disabled
26055 * Read-only. True if this button is pressed (only if enableToggle = true)
26061 * @cfg {Number} tabIndex
26062 * The DOM tabIndex for this button (defaults to undefined)
26064 tabIndex : undefined,
26067 * @cfg {Boolean} enableToggle
26068 * True to enable pressed/not pressed toggling (defaults to false)
26070 enableToggle: false,
26072 * @cfg {Mixed} menu
26073 * Standard menu attribute consisting of a reference to a menu object, a menu id or a menu config blob (defaults to undefined).
26077 * @cfg {String} menuAlign
26078 * The position to align the menu to (see {@link Roo.Element#alignTo} for more details, defaults to 'tl-bl?').
26080 menuAlign : "tl-bl?",
26083 * @cfg {String} iconCls
26084 * A css class which sets a background image to be used as the icon for this button (defaults to undefined).
26086 iconCls : undefined,
26088 * @cfg {String} type
26089 * The button's type, corresponding to the DOM input element type attribute. Either "submit," "reset" or "button" (default).
26094 menuClassTarget: 'tr',
26097 * @cfg {String} clickEvent
26098 * The type of event to map to the button's event handler (defaults to 'click')
26100 clickEvent : 'click',
26103 * @cfg {Boolean} handleMouseEvents
26104 * False to disable visual cues on mouseover, mouseout and mousedown (defaults to true)
26106 handleMouseEvents : true,
26109 * @cfg {String} tooltipType
26110 * The type of tooltip to use. Either "qtip" (default) for QuickTips or "title" for title attribute.
26112 tooltipType : 'qtip',
26115 * @cfg {String} cls
26116 * A CSS class to apply to the button's main element.
26120 * @cfg {Roo.Template} template (Optional)
26121 * An {@link Roo.Template} with which to create the Button's main element. This Template must
26122 * contain numeric substitution parameter 0 if it is to display the tRoo property. Changing the template could
26123 * require code modifications if required elements (e.g. a button) aren't present.
26127 render : function(C){
26129 if(this.hideParent){
26130 this.parentEl = Roo.get(C);
26132 if(!this.dhconfig){
26133 if(!this.template){
26134 if(!Roo.Button.buttonTemplate){
26135 // hideous table template
26136 Roo.Button.buttonTemplate = new Roo.Template(
26137 '<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
26138 '<td class="x-btn-left"><i> </i></td><td class="x-btn-center"><em unselectable="on"><button class="x-btn-text" type="{1}">{0}</button></em></td><td class="x-btn-right"><i> </i></td>',
26139 "</tr></tbody></table>");
26142 this.template = Roo.Button.buttonTemplate;
26145 D = this.template.append(C, [this.text || ' ', this.type], true);
26146 var btnEl = D.child("button:first");
26147 btnEl.on('focus', this.onFocus, this);
26148 btnEl.on('blur', this.onBlur, this);
26150 D.addClass(this.cls);
26153 btnEl.setStyle('background-image', 'url(' +this.icon +')');
26156 btnEl.addClass(this.iconCls);
26158 D.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
26161 if(this.tabIndex !== undefined){
26162 btnEl.dom.tabIndex = this.tabIndex;
26165 if(typeof this.tooltip == 'object'){
26166 Roo.QuickTips.tips(Roo.apply({
26170 btnEl.dom[this.tooltipType] = this.tooltip;
26174 D = Roo.DomHelper.append(Roo.get(C).dom, this.dhconfig, true);
26179 this.el.dom.id = this.el.id = this.id;
26182 this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
26183 this.menu.on("show", this.onMenuShow, this);
26184 this.menu.on("hide", this.onMenuHide, this);
26187 D.addClass("x-btn");
26188 if(Roo.isIE && !Roo.isIE7){
26189 this.autoWidth.defer(1, this);
26193 if(this.handleMouseEvents){
26194 D.on("mouseover", this.onMouseOver, this);
26195 D.on("mouseout", this.onMouseOut, this);
26196 D.on("mousedown", this.onMouseDown, this);
26199 D.on(this.clickEvent, this.onClick, this);
26200 //btn.on("mouseup", this.onMouseUp, this);
26208 Roo.ButtonToggleMgr.register(this);
26210 this.el.addClass("x-btn-pressed");
26213 var repeater = new Roo.util.ClickRepeater(D,
26214 typeof this.repeat == "object" ? this.repeat : {}
26216 repeater.on("click", this.onClick, this);
26219 this.fireEvent('render', this);
26223 * Returns the button's underlying element
26224 * @return {Roo.Element} The element
26226 getEl : function(){
26231 * Destroys this Button and removes any listeners.
26233 destroy : function(){
26234 Roo.ButtonToggleMgr.unregister(this);
26235 this.el.removeAllListeners();
26236 this.purgeListeners();
26241 autoWidth : function(){
26243 this.el.setWidth("auto");
26244 if(Roo.isIE7 && Roo.isStrict){
26245 var ib = this.el.child('button');
26246 if(ib && ib.getWidth() > 20){
26248 ib.setWidth(Roo.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
26253 this.el.beginMeasure();
26255 if(this.el.getWidth() < this.minWidth){
26256 this.el.setWidth(this.minWidth);
26259 this.el.endMeasure();
26266 * Assigns this button's click handler
26267 * @param {Function} handler The function to call when the button is clicked
26268 * @param {Object} scope (optional) Scope for the function passed in
26270 setHandler : function(E, F){
26276 * Sets this button's text
26277 * @param {String} text The button text
26279 setText : function(G){
26282 this.el.child("td.x-btn-center button.x-btn-text").update(G);
26289 * Gets the text for this button
26290 * @return {String} The button text
26292 getText : function(){
26300 this.hidden = false;
26302 this[this.hideParent? 'parentEl' : 'el'].setStyle("display", "");
26310 this.hidden = true;
26312 this[this.hideParent? 'parentEl' : 'el'].setStyle("display", "none");
26317 * Convenience function for boolean show/hide
26318 * @param {Boolean} visible True to show, false to hide
26320 setVisible: function(H){
26329 * If a state it passed, it becomes the pressed state otherwise the current state is toggled.
26330 * @param {Boolean} state (optional) Force a particular state
26332 toggle : function(I){
26333 I = I === undefined ? !this.pressed : I;
26334 if(I != this.pressed){
26336 this.el.addClass("x-btn-pressed");
26337 this.pressed = true;
26338 this.fireEvent("toggle", this, true);
26340 this.el.removeClass("x-btn-pressed");
26341 this.pressed = false;
26342 this.fireEvent("toggle", this, false);
26344 if(this.toggleHandler){
26345 this.toggleHandler.call(this.scope || this, this, I);
26353 focus : function(){
26354 this.el.child('button:first').focus();
26358 * Disable this button
26360 disable : function(){
26362 this.el.addClass("x-btn-disabled");
26365 this.disabled = true;
26369 * Enable this button
26371 enable : function(){
26373 this.el.removeClass("x-btn-disabled");
26376 this.disabled = false;
26380 * Convenience function for boolean enable/disable
26381 * @param {Boolean} enabled True to enable, false to disable
26383 setDisabled : function(v){
26384 this[v !== true ? "enable" : "disable"]();
26388 onClick : function(e){
26390 e.preventDefault();
26395 if(!this.disabled){
26396 if(this.enableToggle){
26399 if(this.menu && !this.menu.isVisible()){
26400 this.menu.show(this.el, this.menuAlign);
26403 this.fireEvent("click", this, e);
26405 this.el.removeClass("x-btn-over");
26406 this.handler.call(this.scope || this, this, e);
26411 onMouseOver : function(e){
26412 if(!this.disabled){
26413 this.el.addClass("x-btn-over");
26414 this.fireEvent('mouseover', this, e);
26418 onMouseOut : function(e){
26419 if(!e.within(this.el, true)){
26420 this.el.removeClass("x-btn-over");
26421 this.fireEvent('mouseout', this, e);
26425 onFocus : function(e){
26426 if(!this.disabled){
26427 this.el.addClass("x-btn-focus");
26431 onBlur : function(e){
26432 this.el.removeClass("x-btn-focus");
26435 onMouseDown : function(e){
26436 if(!this.disabled && e.button == 0){
26437 this.el.addClass("x-btn-click");
26438 Roo.get(document).on('mouseup', this.onMouseUp, this);
26442 onMouseUp : function(e){
26444 this.el.removeClass("x-btn-click");
26445 Roo.get(document).un('mouseup', this.onMouseUp, this);
26449 onMenuShow : function(e){
26450 this.el.addClass("x-btn-menu-active");
26453 onMenuHide : function(e){
26454 this.el.removeClass("x-btn-menu-active");
26458 // Private utility class used by Button
26459 Roo.ButtonToggleMgr = function(){
26464 var g = J[L.toggleGroup];
26465 for(var i = 0, l = g.length; i < l; i++){
26467 g[i].toggle(false);
26474 register : function(N){
26475 if(!N.toggleGroup){
26478 var g = J[N.toggleGroup];
26480 g = J[N.toggleGroup] = [];
26487 unregister : function(O){
26488 if(!O.toggleGroup){
26491 var g = J[O.toggleGroup];
26501 * Ext JS Library 1.1.1
26502 * Copyright(c) 2006-2007, Ext JS, LLC.
26504 * Originally Released Under LGPL - original licence link has changed is not relivant.
26507 * <script type="text/javascript">
26511 * @class Roo.SplitButton
26512 * @extends Roo.Button
26513 * A split button that provides a built-in dropdown arrow that can fire an event separately from the default
26514 * click event of the button. Typically this would be used to display a dropdown menu that provides additional
26515 * options to the primary button action, but any custom handler can provide the arrowclick implementation.
26516 * @cfg {Function} arrowHandler A function called when the arrow button is clicked (can be used instead of click event)
26517 * @cfg {String} arrowTooltip The title attribute of the arrow
26519 * Create a new menu button
26520 * @param {String/HTMLElement/Element} renderTo The element to append the button to
26521 * @param {Object} config The config object
26523 Roo.SplitButton = function(A, B){
26524 Roo.SplitButton.superclass.constructor.call(this, A, B);
26526 * @event arrowclick
26527 * Fires when this button's arrow is clicked
26528 * @param {SplitButton} this
26529 * @param {EventObject} e The click event
26531 this.addEvents({"arrowclick":true});
26534 Roo.extend(Roo.SplitButton, Roo.Button, {
26535 render : function(C){
26536 // this is one sweet looking template!
26537 var D = new Roo.Template(
26538 '<table cellspacing="0" class="x-btn-menu-wrap x-btn"><tr><td>',
26539 '<table cellspacing="0" class="x-btn-wrap x-btn-menu-text-wrap"><tbody>',
26540 '<tr><td class="x-btn-left"><i> </i></td><td class="x-btn-center"><button class="x-btn-text" type="{1}">{0}</button></td></tr>',
26541 "</tbody></table></td><td>",
26542 '<table cellspacing="0" class="x-btn-wrap x-btn-menu-arrow-wrap"><tbody>',
26543 '<tr><td class="x-btn-center"><button class="x-btn-menu-arrow-el" type="button"> </button></td><td class="x-btn-right"><i> </i></td></tr>',
26544 "</tbody></table></td></tr></table>"
26546 var E = D.append(C, [this.text, this.type], true);
26547 var F = E.child("button");
26549 E.addClass(this.cls);
26552 F.setStyle('background-image', 'url(' +this.icon +')');
26555 F.addClass(this.iconCls);
26557 E.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
26562 if(this.handleMouseEvents){
26563 E.on("mouseover", this.onMouseOver, this);
26564 E.on("mouseout", this.onMouseOut, this);
26565 E.on("mousedown", this.onMouseDown, this);
26566 E.on("mouseup", this.onMouseUp, this);
26569 E.on(this.clickEvent, this.onClick, this);
26571 if(typeof this.tooltip == 'object'){
26572 Roo.QuickTips.tips(Roo.apply({
26576 F.dom[this.tooltipType] = this.tooltip;
26579 if(this.arrowTooltip){
26580 E.child("button:nth(2)").dom[this.tooltipType] = this.arrowTooltip;
26589 this.el.addClass("x-btn-pressed");
26591 if(Roo.isIE && !Roo.isIE7){
26592 this.autoWidth.defer(1, this);
26597 this.menu.on("show", this.onMenuShow, this);
26598 this.menu.on("hide", this.onMenuHide, this);
26601 this.fireEvent('render', this);
26605 autoWidth : function(){
26607 var tbl = this.el.child("table:first");
26608 var tbl2 = this.el.child("table:last");
26609 this.el.setWidth("auto");
26610 tbl.setWidth("auto");
26611 if(Roo.isIE7 && Roo.isStrict){
26612 var ib = this.el.child('button:first');
26613 if(ib && ib.getWidth() > 20){
26615 ib.setWidth(Roo.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
26620 this.el.beginMeasure();
26622 if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){
26623 tbl.setWidth(this.minWidth-tbl2.getWidth());
26626 this.el.endMeasure();
26630 this.el.setWidth(tbl.getWidth()+tbl2.getWidth());
26634 * Sets this button's click handler
26635 * @param {Function} handler The function to call when the button is clicked
26636 * @param {Object} scope (optional) Scope for the function passed above
26638 setHandler : function(G, H){
26644 * Sets this button's arrow click handler
26645 * @param {Function} handler The function to call when the arrow is clicked
26646 * @param {Object} scope (optional) Scope for the function passed above
26648 setArrowHandler : function(I, J){
26649 this.arrowHandler = I;
26656 focus : function(){
26658 this.el.child("button:first").focus();
26663 onClick : function(e){
26664 e.preventDefault();
26665 if(!this.disabled){
26666 if(e.getTarget(".x-btn-menu-arrow-wrap")){
26667 if(this.menu && !this.menu.isVisible()){
26668 this.menu.show(this.el, this.menuAlign);
26671 this.fireEvent("arrowclick", this, e);
26672 if(this.arrowHandler){
26673 this.arrowHandler.call(this.scope || this, this, e);
26676 this.fireEvent("click", this, e);
26678 this.handler.call(this.scope || this, this, e);
26684 onMouseDown : function(e){
26685 if(!this.disabled){
26686 Roo.fly(e.getTarget("table")).addClass("x-btn-click");
26690 onMouseUp : function(e){
26691 Roo.fly(e.getTarget("table")).removeClass("x-btn-click");
26696 // backwards compat
26697 Roo.MenuButton = Roo.SplitButton;
26700 * Ext JS Library 1.1.1
26701 * Copyright(c) 2006-2007, Ext JS, LLC.
26703 * Originally Released Under LGPL - original licence link has changed is not relivant.
26706 * <script type="text/javascript">
26710 * @class Roo.Toolbar
26711 * Basic Toolbar class.
26713 * Creates a new Toolbar
26714 * @param {Object} config The config object
26716 Roo.Toolbar = function(A, B, C)
26718 /// old consturctor format still supported..
26719 if(A instanceof Array){ // omit the container for later rendering
26724 if (typeof(A) == 'object' && A.xtype) {
26727 B = C.buttons; // not really - use items!!
26730 if (C && C.items) {
26735 Roo.apply(this, C);
26742 Roo.each(D, function(b) {
26748 Roo.Toolbar.prototype = {
26750 * @cfg {Roo.data.Store} items
26751 * array of button configs or elements to add
26755 * @cfg {String/HTMLElement/Element} container
26756 * The id or element that will contain the toolbar
26759 render : function(ct){
26760 this.el = Roo.get(ct);
26762 this.el.addClass(this.cls);
26765 // using a table allows for vertical alignment
26766 // 100% width is needed by Safari...
26767 this.el.update('<div class="x-toolbar x-small-editor"><table cellspacing="0"><tr></tr></table></div>');
26768 this.tr = this.el.child("tr", true);
26770 this.items = new Roo.util.MixedCollection(false, function(o){
26771 return o.id || ("item" + (++E));
26774 this.add.apply(this, this.buttons);
26775 delete this.buttons;
26780 * Adds element(s) to the toolbar -- this function takes a variable number of
26781 * arguments of mixed type and adds them to the toolbar.
26782 * @param {Mixed} arg1 The following types of arguments are all valid:<br />
26784 * <li>{@link Roo.Toolbar.Button} config: A valid button config object (equivalent to {@link #addButton})</li>
26785 * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>
26786 * <li>Field: Any form field (equivalent to {@link #addField})</li>
26787 * <li>Item: Any subclass of {@link Roo.Toolbar.Item} (equivalent to {@link #addItem})</li>
26788 * <li>String: Any generic string (gets wrapped in a {@link Roo.Toolbar.TextItem}, equivalent to {@link #addText}).
26789 * Note that there are a few special strings that are treated differently as explained nRoo.</li>
26790 * <li>'separator' or '-': Creates a separator element (equivalent to {@link #addSeparator})</li>
26791 * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>
26792 * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>
26794 * @param {Mixed} arg2
26795 * @param {Mixed} etc.
26798 var a = arguments, l = a.length;
26799 for(var i = 0; i < l; i++){
26804 _add : function(el) {
26807 el = Roo.factory(el, typeof(Roo.Toolbar[el.xtype]) == 'undefined' ? Roo.form : Roo.Toolbar);
26810 if (el.applyTo){ // some kind of form field
26811 return this.addField(el);
26813 if (el.render){ // some kind of Toolbar.Item
26814 return this.addItem(el);
26816 if (typeof el == "string"){ // string
26817 if(el == "separator" || el == "-"){
26818 return this.addSeparator();
26821 return this.addSpacer();
26824 return this.addFill();
26826 return this.addText(el);
26829 if(el.tagName){ // element
26830 return this.addElement(el);
26832 if(typeof el == "object"){ // must be button config?
26833 return this.addButton(el);
26835 // and now what?!?!
26841 * Add an Xtype element
26842 * @param {Object} xtype Xtype Object
26843 * @return {Object} created Object
26845 addxtype : function(e){
26846 return this.add(e);
26850 * Returns the Element for this toolbar.
26851 * @return {Roo.Element}
26853 getEl : function(){
26859 * @return {Roo.Toolbar.Item} The separator item
26861 addSeparator : function(){
26862 return this.addItem(new Roo.Toolbar.Separator());
26866 * Adds a spacer element
26867 * @return {Roo.Toolbar.Spacer} The spacer item
26869 addSpacer : function(){
26870 return this.addItem(new Roo.Toolbar.Spacer());
26874 * Adds a fill element that forces subsequent additions to the right side of the toolbar
26875 * @return {Roo.Toolbar.Fill} The fill item
26877 addFill : function(){
26878 return this.addItem(new Roo.Toolbar.Fill());
26882 * Adds any standard HTML element to the toolbar
26883 * @param {String/HTMLElement/Element} el The element or id of the element to add
26884 * @return {Roo.Toolbar.Item} The element's item
26886 addElement : function(el){
26887 return this.addItem(new Roo.Toolbar.Item(el));
26890 * Collection of items on the toolbar.. (only Toolbar Items, so use fields to retrieve fields)
26891 * @type Roo.util.MixedCollection
26896 * Adds any Toolbar.Item or subclass
26897 * @param {Roo.Toolbar.Item} item
26898 * @return {Roo.Toolbar.Item} The item
26900 addItem : function(F){
26901 var td = this.nextBlock();
26908 * Adds a button (or buttons). See {@link Roo.Toolbar.Button} for more info on the config.
26909 * @param {Object/Array} config A button config or array of configs
26910 * @return {Roo.Toolbar.Button/Array}
26912 addButton : function(G){
26913 if(G instanceof Array){
26915 for(var i = 0, len = G.length; i < len; i++) {
26916 B.push(this.addButton(G[i]));
26921 if(!(G instanceof Roo.Toolbar.Button)){
26923 new Roo.Toolbar.SplitButton(G) :
26924 new Roo.Toolbar.Button(G);
26926 var td = this.nextBlock();
26933 * Adds text to the toolbar
26934 * @param {String} text The text to add
26935 * @return {Roo.Toolbar.Item} The element's item
26937 addText : function(H){
26938 return this.addItem(new Roo.Toolbar.TextItem(H));
26942 * Inserts any {@link Roo.Toolbar.Item}/{@link Roo.Toolbar.Button} at the specified index.
26943 * @param {Number} index The index where the item is to be inserted
26944 * @param {Object/Roo.Toolbar.Item/Roo.Toolbar.Button (may be Array)} item The button, or button config object to be inserted.
26945 * @return {Roo.Toolbar.Button/Item}
26947 insertButton : function(I, J){
26948 if(J instanceof Array){
26950 for(var i = 0, len = J.length; i < len; i++) {
26951 B.push(this.insertButton(I + i, J[i]));
26955 if (!(J instanceof Roo.Toolbar.Button)){
26956 J = new Roo.Toolbar.Button(J);
26958 var td = document.createElement("td");
26959 this.tr.insertBefore(td, this.tr.childNodes[I]);
26961 this.items.insert(I, J);
26966 * Adds a new element to the toolbar from the passed {@link Roo.DomHelper} config.
26967 * @param {Object} config
26968 * @return {Roo.Toolbar.Item} The element's item
26970 addDom : function(K, L){
26971 var td = this.nextBlock();
26972 Roo.DomHelper.overwrite(td, K);
26973 var ti = new Roo.Toolbar.Item(td.firstChild);
26975 this.items.add(ti);
26980 * Collection of fields on the toolbar.. usefull for quering (value is false if there are no fields)
26981 * @type Roo.util.MixedCollection
26986 * Adds a dynamically rendered Roo.form field (TextField, ComboBox, etc). Note: the field should not have
26987 * been rendered yet. For a field that has already been rendered, use {@link #addElement}.
26988 * @param {Roo.form.Field} field
26989 * @return {Roo.ToolbarItem}
26993 addField : function(M) {
26994 if (!this.fields) {
26996 this.fields = new Roo.util.MixedCollection(false, function(o){
26997 return o.id || ("item" + (++E));
27002 var td = this.nextBlock();
27004 var ti = new Roo.Toolbar.Item(td.firstChild);
27006 this.items.add(ti);
27007 this.fields.add(M);
27018 this.el.child('div').setVisibilityMode(Roo.Element.DISPLAY);
27019 this.el.child('div').hide();
27027 this.el.child('div').show();
27031 nextBlock : function(){
27032 var td = document.createElement("td");
27033 this.tr.appendChild(td);
27038 destroy : function(){
27039 if(this.items){ // rendered?
27040 Roo.destroy.apply(Roo, this.items.items);
27042 if(this.fields){ // rendered?
27043 Roo.destroy.apply(Roo, this.fields.items);
27046 Roo.Element.uncache(this.el, this.tr);
27051 * @class Roo.Toolbar.Item
27052 * The base class that other classes should extend in order to get some basic common toolbar item functionality.
27054 * Creates a new Item
27055 * @param {HTMLElement} el
27057 Roo.Toolbar.Item = function(el){
27058 this.el = Roo.getDom(el);
27059 this.id = Roo.id(this.el);
27060 this.hidden = false;
27063 Roo.Toolbar.Item.prototype = {
27066 * Get this item's HTML Element
27067 * @return {HTMLElement}
27069 getEl : function(){
27074 render : function(td){
27076 td.appendChild(this.el);
27080 * Removes and destroys this item.
27082 destroy : function(){
27083 this.td.parentNode.removeChild(this.td);
27090 this.hidden = false;
27091 this.td.style.display = "";
27098 this.hidden = true;
27099 this.td.style.display = "none";
27103 * Convenience function for boolean show/hide.
27104 * @param {Boolean} visible true to show/false to hide
27106 setVisible: function(N){
27115 * Try to focus this item.
27117 focus : function(){
27118 Roo.fly(this.el).focus();
27122 * Disables this item.
27124 disable : function(){
27125 Roo.fly(this.td).addClass("x-item-disabled");
27126 this.disabled = true;
27127 this.el.disabled = true;
27131 * Enables this item.
27133 enable : function(){
27134 Roo.fly(this.td).removeClass("x-item-disabled");
27135 this.disabled = false;
27136 this.el.disabled = false;
27142 * @class Roo.Toolbar.Separator
27143 * @extends Roo.Toolbar.Item
27144 * A simple toolbar separator class
27146 * Creates a new Separator
27148 Roo.Toolbar.Separator = function(){
27149 var s = document.createElement("span");
27150 s.className = "ytb-sep";
27151 Roo.Toolbar.Separator.superclass.constructor.call(this, s);
27153 Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
27154 enable:Roo.emptyFn,
27155 disable:Roo.emptyFn,
27160 * @class Roo.Toolbar.Spacer
27161 * @extends Roo.Toolbar.Item
27162 * A simple element that adds extra horizontal space to a toolbar.
27164 * Creates a new Spacer
27166 Roo.Toolbar.Spacer = function(){
27167 var s = document.createElement("div");
27168 s.className = "ytb-spacer";
27169 Roo.Toolbar.Spacer.superclass.constructor.call(this, s);
27171 Roo.extend(Roo.Toolbar.Spacer, Roo.Toolbar.Item, {
27172 enable:Roo.emptyFn,
27173 disable:Roo.emptyFn,
27178 * @class Roo.Toolbar.Fill
27179 * @extends Roo.Toolbar.Spacer
27180 * A simple element that adds a greedy (100% width) horizontal space to a toolbar.
27182 * Creates a new Spacer
27184 Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
27186 render : function(td){
27187 td.style.width = '100%';
27188 Roo.Toolbar.Fill.superclass.render.call(this, td);
27193 * @class Roo.Toolbar.TextItem
27194 * @extends Roo.Toolbar.Item
27195 * A simple class that renders text directly into a toolbar.
27197 * Creates a new TextItem
27198 * @param {String} text
27200 Roo.Toolbar.TextItem = function(O){
27201 if (typeof(O) == 'object') {
27204 var s = document.createElement("span");
27205 s.className = "ytb-text";
27207 Roo.Toolbar.TextItem.superclass.constructor.call(this, s);
27209 Roo.extend(Roo.Toolbar.TextItem, Roo.Toolbar.Item, {
27210 enable:Roo.emptyFn,
27211 disable:Roo.emptyFn,
27216 * @class Roo.Toolbar.Button
27217 * @extends Roo.Button
27218 * A button that renders into a toolbar.
27220 * Creates a new Button
27221 * @param {Object} config A standard {@link Roo.Button} config object
27223 Roo.Toolbar.Button = function(P){
27224 Roo.Toolbar.Button.superclass.constructor.call(this, null, P);
27226 Roo.extend(Roo.Toolbar.Button, Roo.Button, {
27227 render : function(td){
27229 Roo.Toolbar.Button.superclass.render.call(this, td);
27233 * Removes and destroys this button
27235 destroy : function(){
27236 Roo.Toolbar.Button.superclass.destroy.call(this);
27237 this.td.parentNode.removeChild(this.td);
27241 * Shows this button
27244 this.hidden = false;
27245 this.td.style.display = "";
27249 * Hides this button
27252 this.hidden = true;
27253 this.td.style.display = "none";
27257 * Disables this item
27259 disable : function(){
27260 Roo.fly(this.td).addClass("x-item-disabled");
27261 this.disabled = true;
27265 * Enables this item
27267 enable : function(){
27268 Roo.fly(this.td).removeClass("x-item-disabled");
27269 this.disabled = false;
27272 // backwards compat
27273 Roo.ToolbarButton = Roo.Toolbar.Button;
27276 * @class Roo.Toolbar.SplitButton
27277 * @extends Roo.SplitButton
27278 * A menu button that renders into a toolbar.
27280 * Creates a new SplitButton
27281 * @param {Object} config A standard {@link Roo.SplitButton} config object
27283 Roo.Toolbar.SplitButton = function(Q){
27284 Roo.Toolbar.SplitButton.superclass.constructor.call(this, null, Q);
27286 Roo.extend(Roo.Toolbar.SplitButton, Roo.SplitButton, {
27287 render : function(td){
27289 Roo.Toolbar.SplitButton.superclass.render.call(this, td);
27293 * Removes and destroys this button
27295 destroy : function(){
27296 Roo.Toolbar.SplitButton.superclass.destroy.call(this);
27297 this.td.parentNode.removeChild(this.td);
27301 * Shows this button
27304 this.hidden = false;
27305 this.td.style.display = "";
27309 * Hides this button
27312 this.hidden = true;
27313 this.td.style.display = "none";
27317 // backwards compat
27318 Roo.Toolbar.MenuButton = Roo.Toolbar.SplitButton;
27321 * Ext JS Library 1.1.1
27322 * Copyright(c) 2006-2007, Ext JS, LLC.
27324 * Originally Released Under LGPL - original licence link has changed is not relivant.
27327 * <script type="text/javascript">
27331 * @class Roo.PagingToolbar
27332 * @extends Roo.Toolbar
27333 * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
27335 * Create a new PagingToolbar
27336 * @param {Object} config The config object
27338 Roo.PagingToolbar = function(el, ds, A)
27340 // old args format still supported... - xtype is prefered..
27341 if (typeof(el) == 'object' && el.xtype) {
27342 // created from xtype...
27344 ds = el.dataSource;
27350 Roo.PagingToolbar.superclass.constructor.call(this, el, null, A);
27353 this.renderButtons(this.el);
27357 Roo.extend(Roo.PagingToolbar, Roo.Toolbar, {
27359 * @cfg {Roo.data.Store} dataSource
27360 * The underlying data store providing the paged data
27363 * @cfg {String/HTMLElement/Element} container
27364 * container The id or element that will contain the toolbar
27367 * @cfg {Boolean} displayInfo
27368 * True to display the displayMsg (defaults to false)
27371 * @cfg {Number} pageSize
27372 * The number of records to display per page (defaults to 20)
27376 * @cfg {String} displayMsg
27377 * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
27379 displayMsg : 'Displaying {0} - {1} of {2}',
27381 * @cfg {String} emptyMsg
27382 * The message to display when no records are found (defaults to "No data to display")
27384 emptyMsg : 'No data to display',
27386 * Customizable piece of the default paging text (defaults to "Page")
27389 beforePageText : "Page",
27391 * Customizable piece of the default paging text (defaults to "of %0")
27394 afterPageText : "of {0}",
27396 * Customizable piece of the default paging text (defaults to "First Page")
27399 firstText : "First Page",
27401 * Customizable piece of the default paging text (defaults to "Previous Page")
27404 prevText : "Previous Page",
27406 * Customizable piece of the default paging text (defaults to "Next Page")
27409 nextText : "Next Page",
27411 * Customizable piece of the default paging text (defaults to "Last Page")
27414 lastText : "Last Page",
27416 * Customizable piece of the default paging text (defaults to "Refresh")
27419 refreshText : "Refresh",
27422 renderButtons : function(el){
27423 Roo.PagingToolbar.superclass.render.call(this, el);
27424 this.first = this.addButton({
27425 tooltip: this.firstText,
27426 cls: "x-btn-icon x-grid-page-first",
27428 handler: this.onClick.createDelegate(this, ["first"])
27430 this.prev = this.addButton({
27431 tooltip: this.prevText,
27432 cls: "x-btn-icon x-grid-page-prev",
27434 handler: this.onClick.createDelegate(this, ["prev"])
27436 this.addSeparator();
27437 this.add(this.beforePageText);
27438 this.field = Roo.get(this.addDom({
27443 cls: "x-grid-page-number"
27445 this.field.on("keydown", this.onPagingKeydown, this);
27446 this.field.on("focus", function(){this.dom.select();});
27447 this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
27448 this.field.setHeight(18);
27449 this.addSeparator();
27450 this.next = this.addButton({
27451 tooltip: this.nextText,
27452 cls: "x-btn-icon x-grid-page-next",
27454 handler: this.onClick.createDelegate(this, ["next"])
27456 this.last = this.addButton({
27457 tooltip: this.lastText,
27458 cls: "x-btn-icon x-grid-page-last",
27460 handler: this.onClick.createDelegate(this, ["last"])
27462 this.addSeparator();
27463 this.loading = this.addButton({
27464 tooltip: this.refreshText,
27465 cls: "x-btn-icon x-grid-loading",
27466 handler: this.onClick.createDelegate(this, ["refresh"])
27469 if(this.displayInfo){
27470 this.displayEl = Roo.fly(this.el.dom.firstChild).createChild({cls:'x-paging-info'});
27475 updateInfo : function(){
27476 if(this.displayEl){
27477 var count = this.ds.getCount();
27478 var msg = count == 0 ?
27482 this.cursor+1, this.cursor+count, this.ds.getTotalCount()
27484 this.displayEl.update(msg);
27489 onLoad : function(ds, r, o){
27490 this.cursor = o.params ? o.params.start : 0;
27491 var d = this.getPageData(), ap = d.activePage, ps = d.pages;
27493 this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
27494 this.field.dom.value = ap;
27495 this.first.setDisabled(ap == 1);
27496 this.prev.setDisabled(ap == 1);
27497 this.next.setDisabled(ap == ps);
27498 this.last.setDisabled(ap == ps);
27499 this.loading.enable();
27504 getPageData : function(){
27505 var B = this.ds.getTotalCount();
27508 activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
27509 pages : B < this.pageSize ? 1 : Math.ceil(B/this.pageSize)
27514 onLoadError : function(){
27515 this.loading.enable();
27519 onPagingKeydown : function(e){
27520 var k = e.getKey();
27521 var d = this.getPageData();
27522 if(k == e.RETURN ){
27523 var v = this.field.dom.value, pageNum;
27524 if(!v || isNaN(pageNum = parseInt(v, 10))){
27525 this.field.dom.value = d.activePage;
27529 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
27530 this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
27533 else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
27535 var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
27536 this.field.dom.value = pageNum;
27537 this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
27540 else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
27542 var v = this.field.dom.value, pageNum;
27543 var increment = (e.shiftKey) ? 10 : 1;
27544 if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
27546 if(!v || isNaN(pageNum = parseInt(v, 10))) {
27547 this.field.dom.value = d.activePage;
27550 else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
27552 this.field.dom.value = parseInt(v, 10) + increment;
27553 pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
27554 this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
27562 beforeLoad : function(){
27564 this.loading.disable();
27569 onClick : function(C){
27573 ds.load({params:{start: 0, limit: this.pageSize}});
27576 ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
27579 ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
27582 var B = ds.getTotalCount();
27583 var extra = B % this.pageSize;
27584 var lastStart = extra ? (B - extra) : B-this.pageSize;
27585 ds.load({params:{start: lastStart, limit: this.pageSize}});
27588 ds.load({params:{start: this.cursor, limit: this.pageSize}});
27594 * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
27595 * @param {Roo.data.Store} store The data store to unbind
27597 unbind : function(ds){
27598 ds.un("beforeload", this.beforeLoad, this);
27599 ds.un("load", this.onLoad, this);
27600 ds.un("loadexception", this.onLoadError, this);
27601 ds.un("remove", this.updateInfo, this);
27602 ds.un("add", this.updateInfo, this);
27603 this.ds = undefined;
27607 * Binds the paging toolbar to the specified {@link Roo.data.Store}
27608 * @param {Roo.data.Store} store The data store to bind
27610 bind : function(ds){
27611 ds.on("beforeload", this.beforeLoad, this);
27612 ds.on("load", this.onLoad, this);
27613 ds.on("loadexception", this.onLoadError, this);
27614 ds.on("remove", this.updateInfo, this);
27615 ds.on("add", this.updateInfo, this);
27621 * Ext JS Library 1.1.1
27622 * Copyright(c) 2006-2007, Ext JS, LLC.
27624 * Originally Released Under LGPL - original licence link has changed is not relivant.
27627 * <script type="text/javascript">
27631 * @class Roo.Resizable
27632 * @extends Roo.util.Observable
27633 * <p>Applies drag handles to an element to make it resizable. The drag handles are inserted into the element
27634 * and positioned absolute. Some elements, such as a textarea or image, don't support this. To overcome that, you can wrap
27635 * the textarea in a div and set "resizeChild" to true (or to the id of the element), <b>or</b> set wrap:true in your config and
27636 * the element will be wrapped for you automatically.</p>
27637 * <p>Here is the list of valid resize handles:</p>
27640 ------ -------------------
27651 * <p>Here's an example showing the creation of a typical Resizable:</p>
27653 var resizer = new Roo.Resizable("element-id", {
27661 resizer.on("resize", myHandler);
27663 * <p>To hide a particular handle, set its display to none in CSS, or through script:<br>
27664 * resizer.east.setDisplayed(false);</p>
27665 * @cfg {Boolean/String/Element} resizeChild True to resize the first child, or id/element to resize (defaults to false)
27666 * @cfg {Array/String} adjustments String "auto" or an array [width, height] with values to be <b>added</b> to the
27667 * resize operation's new size (defaults to [0, 0])
27668 * @cfg {Number} minWidth The minimum width for the element (defaults to 5)
27669 * @cfg {Number} minHeight The minimum height for the element (defaults to 5)
27670 * @cfg {Number} maxWidth The maximum width for the element (defaults to 10000)
27671 * @cfg {Number} maxHeight The maximum height for the element (defaults to 10000)
27672 * @cfg {Boolean} enabled False to disable resizing (defaults to true)
27673 * @cfg {Boolean} wrap True to wrap an element with a div if needed (required for textareas and images, defaults to false)
27674 * @cfg {Number} width The width of the element in pixels (defaults to null)
27675 * @cfg {Number} height The height of the element in pixels (defaults to null)
27676 * @cfg {Boolean} animate True to animate the resize (not compatible with dynamic sizing, defaults to false)
27677 * @cfg {Number} duration Animation duration if animate = true (defaults to .35)
27678 * @cfg {Boolean} dynamic True to resize the element while dragging instead of using a proxy (defaults to false)
27679 * @cfg {String} handles String consisting of the resize handles to display (defaults to undefined)
27680 * @cfg {Boolean} multiDirectional <b>Deprecated</b>. The old style of adding multi-direction resize handles, deprecated
27681 * in favor of the handles config option (defaults to false)
27682 * @cfg {Boolean} disableTrackOver True to disable mouse tracking. This is only applied at config time. (defaults to false)
27683 * @cfg {String} easing Animation easing if animate = true (defaults to 'easingOutStrong')
27684 * @cfg {Number} widthIncrement The increment to snap the width resize in pixels (dynamic must be true, defaults to 0)
27685 * @cfg {Number} heightIncrement The increment to snap the height resize in pixels (dynamic must be true, defaults to 0)
27686 * @cfg {Boolean} pinned True to ensure that the resize handles are always visible, false to display them only when the
27687 * user mouses over the resizable borders. This is only applied at config time. (defaults to false)
27688 * @cfg {Boolean} preserveRatio True to preserve the original ratio between height and width during resize (defaults to false)
27689 * @cfg {Boolean} transparent True for transparent handles. This is only applied at config time. (defaults to false)
27690 * @cfg {Number} minX The minimum allowed page X for the element (only used for west resizing, defaults to 0)
27691 * @cfg {Number} minY The minimum allowed page Y for the element (only used for north resizing, defaults to 0)
27692 * @cfg {Boolean} draggable Convenience to initialize drag drop (defaults to false)
27694 * Create a new resizable component
27695 * @param {String/HTMLElement/Roo.Element} el The id or element to resize
27696 * @param {Object} config configuration options
27698 Roo.Resizable = function(el, A){
27699 this.el = Roo.get(el);
27702 A.resizeChild = this.el;
27703 this.el = this.el.wrap(typeof A.wrap == "object" ? A.wrap : {cls:"xresizable-wrap"});
27704 this.el.id = this.el.dom.id = A.resizeChild.id + "-rzwrap";
27705 this.el.setStyle("overflow", "hidden");
27706 this.el.setPositioning(A.resizeChild.getPositioning());
27707 A.resizeChild.clearPositioning();
27708 if(!A.width || !A.height){
27709 var csize = A.resizeChild.getSize();
27710 this.el.setSize(csize.width, csize.height);
27712 if(A.pinned && !A.adjustments){
27713 A.adjustments = "auto";
27718 this.proxy = this.el.createProxy({tag: "div", cls: "x-resizable-proxy", id: this.el.id + "-rzproxy"});
27719 this.proxy.unselectable();
27720 this.proxy.enableDisplayMode('block');
27722 Roo.apply(this, A);
27725 this.disableTrackOver = true;
27726 this.el.addClass("x-resizable-pinned");
27728 // if the element isn't positioned, make it relative
27729 var B = this.el.getStyle("position");
27730 if(B != "absolute" && B != "fixed"){
27731 this.el.setStyle("position", "relative");
27733 if(!this.handles){ // no handles passed, must be legacy style
27734 this.handles = 's,e,se';
27735 if(this.multiDirectional){
27736 this.handles += ',n,w';
27739 if(this.handles == "all"){
27740 this.handles = "n s e w ne nw se sw";
27742 var hs = this.handles.split(/\s*?[,;]\s*?| /);
27743 var ps = Roo.Resizable.positions;
27744 for(var i = 0, len = hs.length; i < len; i++){
27745 if(hs[i] && ps[hs[i]]){
27746 var pos = ps[hs[i]];
27747 this[pos] = new Roo.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
27752 this.corner = this.southeast;
27754 if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
27755 this.updateBox = true;
27759 this.activeHandle = null;
27761 if(this.resizeChild){
27762 if(typeof this.resizeChild == "boolean"){
27763 this.resizeChild = Roo.get(this.el.dom.firstChild, true);
27765 this.resizeChild = Roo.get(this.resizeChild, true);
27769 if(this.adjustments == "auto"){
27770 var rc = this.resizeChild;
27771 var hw = this.west, he = this.east, hn = this.north, hs = this.south;
27772 if(rc && (hw || hn)){
27773 rc.position("relative");
27774 rc.setLeft(hw ? hw.el.getWidth() : 0);
27775 rc.setTop(hn ? hn.el.getHeight() : 0);
27778 this.adjustments = [
27779 (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
27780 (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
27784 if(this.draggable){
27785 this.dd = this.dynamic ?
27786 this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
27787 this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
27794 * @event beforeresize
27795 * Fired before resize is allowed. Set enabled to false to cancel resize.
27796 * @param {Roo.Resizable} this
27797 * @param {Roo.EventObject} e The mousedown event
27799 "beforeresize" : true,
27802 * Fired after a resize.
27803 * @param {Roo.Resizable} this
27804 * @param {Number} width The new width
27805 * @param {Number} height The new height
27806 * @param {Roo.EventObject} e The mouseup event
27811 if(this.width !== null && this.height !== null){
27812 this.resizeTo(this.width, this.height);
27814 this.updateChildSize();
27817 this.el.dom.style.zoom = 1;
27820 Roo.Resizable.superclass.constructor.call(this);
27823 Roo.extend(Roo.Resizable, Roo.util.Observable, {
27824 resizeChild : false,
27825 adjustments : [0, 0],
27835 multiDirectional : false,
27836 disableTrackOver : false,
27837 easing : 'easeOutStrong',
27838 widthIncrement : 0,
27839 heightIncrement : 0,
27843 preserveRatio : false,
27844 transparent: false,
27850 * @cfg {String/HTMLElement/Element} constrainTo Constrain the resize to a particular element
27852 constrainTo: undefined,
27854 * @cfg {Roo.lib.Region} resizeRegion Constrain the resize to a particular region
27856 resizeRegion: undefined,
27860 * Perform a manual resize
27861 * @param {Number} width
27862 * @param {Number} height
27864 resizeTo : function(C, D){
27865 this.el.setSize(C, D);
27866 this.updateChildSize();
27867 this.fireEvent("resize", this, C, D, null);
27871 startSizing : function(e, E){
27872 this.fireEvent("beforeresize", this, e);
27873 if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
27876 this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: " "});
27877 this.overlay.unselectable();
27878 this.overlay.enableDisplayMode("block");
27879 this.overlay.on("mousemove", this.onMouseMove, this);
27880 this.overlay.on("mouseup", this.onMouseUp, this);
27883 this.overlay.setStyle("cursor", E.el.getStyle("cursor"));
27885 this.resizing = true;
27886 this.startBox = this.el.getBox();
27887 this.startPoint = e.getXY();
27888 this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
27889 (this.startBox.y + this.startBox.height) - this.startPoint[1]];
27891 this.overlay.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
27892 this.overlay.show();
27894 if(this.constrainTo) {
27895 var ct = Roo.get(this.constrainTo);
27896 this.resizeRegion = ct.getRegion().adjust(
27897 ct.getFrameWidth('t'),
27898 ct.getFrameWidth('l'),
27899 -ct.getFrameWidth('b'),
27900 -ct.getFrameWidth('r')
27905 this.proxy.setStyle('visibility', 'hidden'); // workaround display none
27907 this.proxy.setBox(this.startBox);
27909 this.proxy.setStyle('visibility', 'visible');
27915 onMouseDown : function(F, e){
27918 this.activeHandle = F;
27919 this.startSizing(e, F);
27924 onMouseUp : function(e){
27925 var G = this.resizeElement();
27926 this.resizing = false;
27928 this.overlay.hide();
27930 this.fireEvent("resize", this, G.width, G.height, e);
27934 updateChildSize : function(){
27935 if(this.resizeChild){
27937 var child = this.resizeChild;
27938 var adj = this.adjustments;
27939 if(el.dom.offsetWidth){
27940 var b = el.getSize(true);
27941 child.setSize(b.width+adj[0], b.height+adj[1]);
27943 // Second call here for IE
27944 // The first call enables instant resizing and
27945 // the second call corrects scroll bars if they
27948 setTimeout(function(){
27949 if(el.dom.offsetWidth){
27950 var b = el.getSize(true);
27951 child.setSize(b.width+adj[0], b.height+adj[1]);
27959 snap : function(H, I, J){
27960 if(!I || !H) return H;
27970 return Math.max(J, K);
27974 resizeElement : function(){
27975 var L = this.proxy.getBox();
27976 if(this.updateBox){
27977 this.el.setBox(L, false, this.animate, this.duration, null, this.easing);
27979 this.el.setSize(L.width, L.height, this.animate, this.duration, null, this.easing);
27982 this.updateChildSize();
27990 constrain : function(v, M, m, mx){
27993 }else if(v - M > mx){
28000 onMouseMove : function(e){
28002 try{// try catch so if something goes wrong the user doesn't get hung
28004 if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
28008 //var curXY = this.startPoint;
28009 var curSize = this.curSize || this.startBox;
28010 var x = this.startBox.x, y = this.startBox.y;
28011 var ox = x, oy = y;
28012 var w = curSize.width, h = curSize.height;
28013 var ow = w, oh = h;
28014 var mw = this.minWidth, mh = this.minHeight;
28015 var mxw = this.maxWidth, mxh = this.maxHeight;
28016 var wi = this.widthIncrement;
28017 var hi = this.heightIncrement;
28019 var eventXY = e.getXY();
28020 var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
28021 var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));
28023 var pos = this.activeHandle.position;
28028 w = Math.min(Math.max(mw, w), mxw);
28032 h = Math.min(Math.max(mh, h), mxh);
28037 w = Math.min(Math.max(mw, w), mxw);
28038 h = Math.min(Math.max(mh, h), mxh);
28041 diffY = this.constrain(h, diffY, mh, mxh);
28046 diffX = this.constrain(w, diffX, mw, mxw);
28052 w = Math.min(Math.max(mw, w), mxw);
28053 diffY = this.constrain(h, diffY, mh, mxh);
28058 diffX = this.constrain(w, diffX, mw, mxw);
28059 diffY = this.constrain(h, diffY, mh, mxh);
28066 diffX = this.constrain(w, diffX, mw, mxw);
28068 h = Math.min(Math.max(mh, h), mxh);
28074 var sw = this.snap(w, wi, mw);
28075 var sh = this.snap(h, hi, mh);
28076 if(sw != w || sh != h){
28100 if(this.preserveRatio){
28105 h = Math.min(Math.max(mh, h), mxh);
28110 w = Math.min(Math.max(mw, w), mxw);
28115 w = Math.min(Math.max(mw, w), mxw);
28121 w = Math.min(Math.max(mw, w), mxw);
28127 h = Math.min(Math.max(mh, h), mxh);
28135 h = Math.min(Math.max(mh, h), mxh);
28145 h = Math.min(Math.max(mh, h), mxh);
28154 this.proxy.setBounds(x, y, w, h);
28156 this.resizeElement();
28163 handleOver : function(){
28165 this.el.addClass("x-resizable-over");
28170 handleOut : function(){
28171 if(!this.resizing){
28172 this.el.removeClass("x-resizable-over");
28177 * Returns the element this component is bound to.
28178 * @return {Roo.Element}
28180 getEl : function(){
28185 * Returns the resizeChild element (or null).
28186 * @return {Roo.Element}
28188 getResizeChild : function(){
28189 return this.resizeChild;
28193 * Destroys this resizable. If the element was wrapped and
28194 * removeEl is not true then the element remains.
28195 * @param {Boolean} removeEl (optional) true to remove the element from the DOM
28197 destroy : function(N){
28198 this.proxy.remove();
28200 this.overlay.removeAllListeners();
28201 this.overlay.remove();
28203 var ps = Roo.Resizable.positions;
28205 if(typeof ps[k] != "function" && this[ps[k]]){
28206 var h = this[ps[k]];
28207 h.el.removeAllListeners();
28212 this.el.update("");
28219 // hash to map config positions to true positions
28220 Roo.Resizable.positions = {
28221 n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"
28225 Roo.Resizable.Handle = function(rz, O, P, Q){
28227 // only initialize the template if resizable is used
28228 var tpl = Roo.DomHelper.createTemplate(
28229 {tag: "div", cls: "x-resizable-handle x-resizable-handle-{0}"}
28232 Roo.Resizable.Handle.prototype.tpl = tpl;
28237 this.el = this.tpl.append(rz.el.dom, [this.position], true);
28238 this.el.unselectable();
28240 this.el.setOpacity(0);
28243 this.el.on("mousedown", this.onMouseDown, this);
28245 this.el.on("mouseover", this.onMouseOver, this);
28246 this.el.on("mouseout", this.onMouseOut, this);
28251 Roo.Resizable.Handle.prototype = {
28252 afterResize : function(rz){
28256 onMouseDown : function(e){
28257 this.rz.onMouseDown(this, e);
28260 onMouseOver : function(e){
28261 this.rz.handleOver(this, e);
28264 onMouseOut : function(e){
28265 this.rz.handleOut(this, e);
28270 * Ext JS Library 1.1.1
28271 * Copyright(c) 2006-2007, Ext JS, LLC.
28273 * Originally Released Under LGPL - original licence link has changed is not relivant.
28276 * <script type="text/javascript">
28280 * @class Roo.Editor
28281 * @extends Roo.Component
28282 * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
28284 * Create a new Editor
28285 * @param {Roo.form.Field} field The Field object (or descendant)
28286 * @param {Object} config The config object
28288 Roo.Editor = function(A, B){
28289 Roo.Editor.superclass.constructor.call(this, B);
28293 * @event beforestartedit
28294 * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning
28295 * false from the handler of this event.
28296 * @param {Editor} this
28297 * @param {Roo.Element} boundEl The underlying element bound to this editor
28298 * @param {Mixed} value The field value being set
28300 "beforestartedit" : true,
28303 * Fires when this editor is displayed
28304 * @param {Roo.Element} boundEl The underlying element bound to this editor
28305 * @param {Mixed} value The starting field value
28307 "startedit" : true,
28309 * @event beforecomplete
28310 * Fires after a change has been made to the field, but before the change is reflected in the underlying
28311 * field. Saving the change to the field can be canceled by returning false from the handler of this event.
28312 * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
28313 * event will not fire since no edit actually occurred.
28314 * @param {Editor} this
28315 * @param {Mixed} value The current field value
28316 * @param {Mixed} startValue The original field value
28318 "beforecomplete" : true,
28321 * Fires after editing is complete and any changed value has been written to the underlying field.
28322 * @param {Editor} this
28323 * @param {Mixed} value The current field value
28324 * @param {Mixed} startValue The original field value
28328 * @event specialkey
28329 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
28330 * {@link Roo.EventObject#getKey} to determine which key was pressed.
28331 * @param {Roo.form.Field} this
28332 * @param {Roo.EventObject} e The event object
28334 "specialkey" : true
28338 Roo.extend(Roo.Editor, Roo.Component, {
28340 * @cfg {Boolean/String} autosize
28341 * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
28342 * or "height" to adopt the height only (defaults to false)
28345 * @cfg {Boolean} revertInvalid
28346 * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
28347 * validation fails (defaults to true)
28350 * @cfg {Boolean} ignoreNoChange
28351 * True to skip the the edit completion process (no save, no events fired) if the user completes an edit and
28352 * the value has not changed (defaults to false). Applies only to string values - edits for other data types
28353 * will never be ignored.
28356 * @cfg {Boolean} hideEl
28357 * False to keep the bound element visible while the editor is displayed (defaults to true)
28360 * @cfg {Mixed} value
28361 * The data value of the underlying field (defaults to "")
28365 * @cfg {String} alignment
28366 * The position to align to (see {@link Roo.Element#alignTo} for more details, defaults to "c-c?").
28370 * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
28371 * for bottom-right shadow (defaults to "frame")
28375 * @cfg {Boolean} constrain True to constrain the editor to the viewport
28379 * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false)
28381 completeOnEnter : false,
28383 * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false)
28385 cancelOnEsc : false,
28387 * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
28392 onRender : function(ct, C){
28393 this.el = new Roo.Layer({
28394 shadow: this.shadow,
28400 constrain: this.constrain
28402 this.el.setStyle("overflow", Roo.isGecko ? "auto" : "hidden");
28403 if(this.field.msgTarget != 'title'){
28404 this.field.msgTarget = 'qtip';
28407 this.field.render(this.el);
28409 this.field.el.dom.setAttribute('autocomplete', 'off');
28412 this.field.on("specialkey", this.onSpecialKey, this);
28413 if(this.swallowKeys){
28414 this.field.el.swallowEvent(['keydown','keypress']);
28418 this.field.on("blur", this.onBlur, this);
28419 if(this.field.grow){
28420 this.field.on("autosize", this.el.sync, this.el, {delay:1});
28424 onSpecialKey : function(D, e){
28425 if(this.completeOnEnter && e.getKey() == e.ENTER){
28427 this.completeEdit();
28428 }else if(this.cancelOnEsc && e.getKey() == e.ESC){
28431 this.fireEvent('specialkey', D, e);
28436 * Starts the editing process and shows the editor.
28437 * @param {String/HTMLElement/Element} el The element to edit
28438 * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
28439 * to the innerHTML of el.
28441 startEdit : function(el, E){
28443 this.completeEdit();
28446 this.boundEl = Roo.get(el);
28447 var v = E !== undefined ? E : this.boundEl.dom.innerHTML;
28448 if(!this.rendered){
28449 this.render(this.parentEl || document.body);
28451 if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
28455 this.startValue = v;
28456 this.field.setValue(v);
28458 var sz = this.boundEl.getSize();
28459 switch(this.autoSize){
28461 this.setSize(sz.width, "");
28464 this.setSize("", sz.height);
28467 this.setSize(sz.width, sz.height);
28471 this.el.alignTo(this.boundEl, this.alignment);
28472 this.editing = true;
28474 Roo.QuickTips.disable();
28481 * Sets the height and width of this editor.
28482 * @param {Number} width The new width
28483 * @param {Number} height The new height
28485 setSize : function(w, h){
28486 this.field.setSize(w, h);
28493 * Realigns the editor to the bound field based on the current alignment config value.
28495 realign : function(){
28496 this.el.alignTo(this.boundEl, this.alignment);
28500 * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
28501 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
28503 completeEdit : function(F){
28507 var v = this.getValue();
28508 if(this.revertInvalid !== false && !this.field.isValid()){
28509 v = this.startValue;
28510 this.cancelEdit(true);
28512 if(String(v) === String(this.startValue) && this.ignoreNoChange){
28513 this.editing = false;
28517 if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
28518 this.editing = false;
28519 if(this.updateEl && this.boundEl){
28520 this.boundEl.update(v);
28526 this.fireEvent("complete", this, v, this.startValue);
28531 onShow : function(){
28533 if(this.hideEl !== false){
28534 this.boundEl.hide();
28538 if(Roo.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
28539 this.fixIEFocus = true;
28540 this.deferredFocus.defer(50, this);
28542 this.field.focus();
28545 this.fireEvent("startedit", this.boundEl, this.startValue);
28548 deferredFocus : function(){
28550 this.field.focus();
28555 * Cancels the editing process and hides the editor without persisting any changes. The field value will be
28556 * reverted to the original starting value.
28557 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
28558 * cancel (defaults to false)
28560 cancelEdit : function(G){
28562 this.setValue(this.startValue);
28570 onBlur : function(){
28571 if(this.allowBlur !== true && this.editing){
28572 this.completeEdit();
28577 onHide : function(){
28579 this.completeEdit();
28584 if(this.field.collapse){
28585 this.field.collapse();
28589 if(this.hideEl !== false){
28590 this.boundEl.show();
28593 Roo.QuickTips.enable();
28598 * Sets the data value of the editor
28599 * @param {Mixed} value Any valid value supported by the underlying field
28601 setValue : function(v){
28602 this.field.setValue(v);
28606 * Gets the data value of the editor
28607 * @return {Mixed} The data value
28609 getValue : function(){
28610 return this.field.getValue();
28615 * Ext JS Library 1.1.1
28616 * Copyright(c) 2006-2007, Ext JS, LLC.
28618 * Originally Released Under LGPL - original licence link has changed is not relivant.
28621 * <script type="text/javascript">
28625 * @class Roo.BasicDialog
28626 * @extends Roo.util.Observable
28627 * Lightweight Dialog Class. The code below shows the creation of a typical dialog using existing HTML markup:
28629 var dlg = new Roo.BasicDialog("my-dlg", {
28638 dlg.addKeyListener(27, dlg.hide, dlg); // ESC can also close the dialog
28639 dlg.addButton('OK', dlg.hide, dlg); // Could call a save function instead of hiding
28640 dlg.addButton('Cancel', dlg.hide, dlg);
28643 <b>A Dialog should always be a direct child of the body element.</b>
28644 * @cfg {Boolean/DomHelper} autoCreate True to auto create from scratch, or using a DomHelper Object (defaults to false)
28645 * @cfg {String} title Default text to display in the title bar (defaults to null)
28646 * @cfg {Number} width Width of the dialog in pixels (can also be set via CSS). Determined by browser if unspecified.
28647 * @cfg {Number} height Height of the dialog in pixels (can also be set via CSS). Determined by browser if unspecified.
28648 * @cfg {Number} x The default left page coordinate of the dialog (defaults to center screen)
28649 * @cfg {Number} y The default top page coordinate of the dialog (defaults to center screen)
28650 * @cfg {String/Element} animateTarget Id or element from which the dialog should animate while opening
28651 * (defaults to null with no animation)
28652 * @cfg {Boolean} resizable False to disable manual dialog resizing (defaults to true)
28653 * @cfg {String} resizeHandles Which resize handles to display - see the {@link Roo.Resizable} handles config
28654 * property for valid values (defaults to 'all')
28655 * @cfg {Number} minHeight The minimum allowable height for a resizable dialog (defaults to 80)
28656 * @cfg {Number} minWidth The minimum allowable width for a resizable dialog (defaults to 200)
28657 * @cfg {Boolean} modal True to show the dialog modally, preventing user interaction with the rest of the page (defaults to false)
28658 * @cfg {Boolean} autoScroll True to allow the dialog body contents to overflow and display scrollbars (defaults to false)
28659 * @cfg {Boolean} closable False to remove the built-in top-right corner close button (defaults to true)
28660 * @cfg {Boolean} collapsible False to remove the built-in top-right corner collapse button (defaults to true)
28661 * @cfg {Boolean} constraintoviewport True to keep the dialog constrained within the visible viewport boundaries (defaults to true)
28662 * @cfg {Boolean} syncHeightBeforeShow True to cause the dimensions to be recalculated before the dialog is shown (defaults to false)
28663 * @cfg {Boolean} draggable False to disable dragging of the dialog within the viewport (defaults to true)
28664 * @cfg {Boolean} autoTabs If true, all elements with class 'x-dlg-tab' will get automatically converted to tabs (defaults to false)
28665 * @cfg {String} tabTag The tag name of tab elements, used when autoTabs = true (defaults to 'div')
28666 * @cfg {Boolean} proxyDrag True to drag a lightweight proxy element rather than the dialog itself, used when
28667 * draggable = true (defaults to false)
28668 * @cfg {Boolean} fixedcenter True to ensure that anytime the dialog is shown or resized it gets centered (defaults to false)
28669 * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop" for bottom-right
28670 * shadow (defaults to false)
28671 * @cfg {Number} shadowOffset The number of pixels to offset the shadow if displayed (defaults to 5)
28672 * @cfg {String} buttonAlign Valid values are "left," "center" and "right" (defaults to "right")
28673 * @cfg {Number} minButtonWidth Minimum width of all dialog buttons (defaults to 75)
28674 * @cfg {Array} buttons Array of buttons
28675 * @cfg {Boolean} shim True to create an iframe shim that prevents selects from showing through (defaults to false)
28677 * Create a new BasicDialog.
28678 * @param {String/HTMLElement/Roo.Element} el The container element or DOM node, or its id
28679 * @param {Object} config Configuration options
28681 Roo.BasicDialog = function(el, A){
28682 this.el = Roo.get(el);
28683 var dh = Roo.DomHelper;
28684 if(!this.el && A && A.autoCreate){
28685 if(typeof A.autoCreate == "object"){
28686 if(!A.autoCreate.id){
28687 A.autoCreate.id = el;
28690 this.el = dh.append(document.body,
28691 A.autoCreate, true);
28693 this.el = dh.append(document.body,
28694 {tag: "div", id: el, style:'visibility:hidden;'}, true);
28699 el.setDisplayed(true);
28700 el.hide = this.hideAction;
28702 el.addClass("x-dlg");
28704 Roo.apply(this, A);
28706 this.proxy = el.createProxy("x-dlg-proxy");
28707 this.proxy.hide = this.hideAction;
28708 this.proxy.setOpacity(.5);
28712 el.setWidth(A.width);
28715 el.setHeight(A.height);
28718 this.size = el.getSize();
28719 if(typeof A.x != "undefined" && typeof A.y != "undefined"){
28720 this.xy = [A.x,A.y];
28722 this.xy = el.getCenterXY(true);
28725 /** The header element @type Roo.Element */
28726 this.header = el.child("> .x-dlg-hd");
28727 /** The body element @type Roo.Element */
28728 this.body = el.child("> .x-dlg-bd");
28729 /** The footer element @type Roo.Element */
28730 this.footer = el.child("> .x-dlg-ft");
28733 this.header = el.createChild({tag: "div", cls:"x-dlg-hd", html: " "}, this.body ? this.body.dom : null);
28736 this.body = el.createChild({tag: "div", cls:"x-dlg-bd"});
28740 this.header.unselectable();
28742 this.header.update(this.title);
28745 // this element allows the dialog to be focused for keyboard event
28746 this.focusEl = el.createChild({tag: "a", href:"#", cls:"x-dlg-focus", tabIndex:"-1"});
28747 this.focusEl.swallowEvent("click", true);
28749 this.header.wrap({cls:"x-dlg-hd-right"}).wrap({cls:"x-dlg-hd-left"}, true);
28751 // wrap the body and footer for special rendering
28752 this.bwrap = this.body.wrap({tag: "div", cls:"x-dlg-dlg-body"});
28754 this.bwrap.dom.appendChild(this.footer.dom);
28758 this.bg = this.el.createChild({
28759 tag: "div", cls:"x-dlg-bg",
28760 html: '<div class="x-dlg-bg-left"><div class="x-dlg-bg-right"><div class="x-dlg-bg-center"> </div></div></div>'
28762 this.centerBg = this.bg.child("div.x-dlg-bg-center");
28765 if(this.autoScroll !== false && !this.autoTabs){
28766 this.body.setStyle("overflow", "auto");
28770 this.toolbox = this.el.createChild({cls: "x-dlg-toolbox"});
28772 if(this.closable !== false){
28773 this.el.addClass("x-dlg-closable");
28774 this.close = this.toolbox.createChild({cls:"x-dlg-close"});
28775 this.close.on("click", this.closeClick, this);
28776 this.close.addClassOnOver("x-dlg-close-over");
28778 if(this.collapsible !== false){
28779 this.collapseBtn = this.toolbox.createChild({cls:"x-dlg-collapse"});
28780 this.collapseBtn.on("click", this.collapseClick, this);
28781 this.collapseBtn.addClassOnOver("x-dlg-collapse-over");
28782 this.header.on("dblclick", this.collapseClick, this);
28784 if(this.resizable !== false){
28785 this.el.addClass("x-dlg-resizable");
28786 this.resizer = new Roo.Resizable(el, {
28787 minWidth: this.minWidth || 80,
28788 minHeight:this.minHeight || 80,
28789 handles: this.resizeHandles || "all",
28792 this.resizer.on("beforeresize", this.beforeResize, this);
28793 this.resizer.on("resize", this.onResize, this);
28795 if(this.draggable !== false){
28796 el.addClass("x-dlg-draggable");
28797 if (!this.proxyDrag) {
28798 var dd = new Roo.dd.DD(el.dom.id, "WindowDrag");
28801 var dd = new Roo.dd.DDProxy(el.dom.id, "WindowDrag", {dragElId: this.proxy.id});
28804 dd.setHandleElId(this.header.id);
28805 dd.endDrag = this.endMove.createDelegate(this);
28806 dd.startDrag = this.startMove.createDelegate(this);
28807 dd.onDrag = this.onDrag.createDelegate(this);
28812 this.mask = dh.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
28813 this.mask.enableDisplayMode("block");
28815 this.el.addClass("x-dlg-modal");
28818 this.shadow = new Roo.Shadow({
28819 mode : typeof this.shadow == "string" ? this.shadow : "sides",
28820 offset : this.shadowOffset
28823 this.shadowOffset = 0;
28825 if(Roo.useShims && this.shim !== false){
28826 this.shim = this.el.createShim();
28827 this.shim.hide = this.hideAction;
28835 if (this.buttons) {
28836 var bts= this.buttons;
28838 Roo.each(bts, function(b) {
28848 * Fires when a key is pressed
28849 * @param {Roo.BasicDialog} this
28850 * @param {Roo.EventObject} e
28855 * Fires when this dialog is moved by the user.
28856 * @param {Roo.BasicDialog} this
28857 * @param {Number} x The new page X
28858 * @param {Number} y The new page Y
28863 * Fires when this dialog is resized by the user.
28864 * @param {Roo.BasicDialog} this
28865 * @param {Number} width The new width
28866 * @param {Number} height The new height
28870 * @event beforehide
28871 * Fires before this dialog is hidden.
28872 * @param {Roo.BasicDialog} this
28874 "beforehide" : true,
28877 * Fires when this dialog is hidden.
28878 * @param {Roo.BasicDialog} this
28882 * @event beforeshow
28883 * Fires before this dialog is shown.
28884 * @param {Roo.BasicDialog} this
28886 "beforeshow" : true,
28889 * Fires when this dialog is shown.
28890 * @param {Roo.BasicDialog} this
28894 el.on("keydown", this.onKeyDown, this);
28895 el.on("mousedown", this.toFront, this);
28896 Roo.EventManager.onWindowResize(this.adjustViewport, this, true);
28898 Roo.DialogManager.register(this);
28899 Roo.BasicDialog.superclass.constructor.call(this);
28902 Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
28903 shadowOffset: Roo.isIE ? 6 : 5,
28906 minButtonWidth: 75,
28907 defaultButton: null,
28908 buttonAlign: "right",
28913 * Sets the dialog title text
28914 * @param {String} text The title text to display
28915 * @return {Roo.BasicDialog} this
28917 setTitle : function(B){
28918 this.header.update(B);
28923 closeClick : function(){
28928 collapseClick : function(){
28929 this[this.collapsed ? "expand" : "collapse"]();
28933 * Collapses the dialog to its minimized state (only the title bar is visible).
28934 * Equivalent to the user clicking the collapse dialog button.
28936 collapse : function(){
28937 if(!this.collapsed){
28938 this.collapsed = true;
28939 this.el.addClass("x-dlg-collapsed");
28940 this.restoreHeight = this.el.getHeight();
28941 this.resizeTo(this.el.getWidth(), this.header.getHeight());
28946 * Expands a collapsed dialog back to its normal state. Equivalent to the user
28947 * clicking the expand dialog button.
28949 expand : function(){
28950 if(this.collapsed){
28951 this.collapsed = false;
28952 this.el.removeClass("x-dlg-collapsed");
28953 this.resizeTo(this.el.getWidth(), this.restoreHeight);
28958 * Reinitializes the tabs component, clearing out old tabs and finding new ones.
28959 * @return {Roo.TabPanel} The tabs component
28961 initTabs : function(){
28962 var C = this.getTabs();
28963 while(C.getTab(0)){
28967 this.el.select(this.tabTag+'.x-dlg-tab').each(function(el){
28969 C.addTab(Roo.id(D), D.title);
28977 beforeResize : function(){
28978 this.resizer.minHeight = Math.max(this.minHeight, this.getHeaderFooterHeight(true)+40);
28982 onResize : function(){
28983 this.refreshSize();
28984 this.syncBodyHeight();
28985 this.adjustAssets();
28987 this.fireEvent("resize", this, this.size.width, this.size.height);
28991 onKeyDown : function(e){
28992 if(this.isVisible()){
28993 this.fireEvent("keydown", this, e);
28998 * Resizes the dialog.
28999 * @param {Number} width
29000 * @param {Number} height
29001 * @return {Roo.BasicDialog} this
29003 resizeTo : function(D, E){
29004 this.el.setSize(D, E);
29005 this.size = {width: D, height: E};
29006 this.syncBodyHeight();
29007 if(this.fixedcenter){
29010 if(this.isVisible()){
29011 this.constrainXY();
29012 this.adjustAssets();
29015 this.fireEvent("resize", this, D, E);
29021 * Resizes the dialog to fit the specified content size.
29022 * @param {Number} width
29023 * @param {Number} height
29024 * @return {Roo.BasicDialog} this
29026 setContentSize : function(w, h){
29027 h += this.getHeaderFooterHeight() + this.body.getMargins("tb");
29028 w += this.body.getMargins("lr") + this.bwrap.getMargins("lr") + this.centerBg.getPadding("lr");
29029 //if(!this.el.isBorderBox()){
29030 h += this.body.getPadding("tb") + this.bwrap.getBorderWidth("tb") + this.body.getBorderWidth("tb") + this.el.getBorderWidth("tb");
29031 w += this.body.getPadding("lr") + this.bwrap.getBorderWidth("lr") + this.body.getBorderWidth("lr") + this.bwrap.getPadding("lr") + this.el.getBorderWidth("lr");
29034 h += this.tabs.stripWrap.getHeight() + this.tabs.bodyEl.getMargins("tb") + this.tabs.bodyEl.getPadding("tb");
29035 w += this.tabs.bodyEl.getMargins("lr") + this.tabs.bodyEl.getPadding("lr");
29038 this.resizeTo(w, h);
29043 * Adds a key listener for when this dialog is displayed. This allows you to hook in a function that will be
29044 * executed in response to a particular key being pressed while the dialog is active.
29045 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the following options:
29046 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
29047 * @param {Function} fn The function to call
29048 * @param {Object} scope (optional) The scope of the function
29049 * @return {Roo.BasicDialog} this
29051 addKeyListener : function(F, fn, G){
29053 if(typeof F == "object" && !(F instanceof Array)){
29061 var L = function(M, e){
29062 if((!I || e.shiftKey) && (!J || e.ctrlKey) && (!K || e.altKey)){
29063 var k = e.getKey();
29064 if(H instanceof Array){
29065 for(var i = 0, len = H.length; i < len; i++){
29067 fn.call(G || window, M, k, e);
29073 fn.call(G || window, M, k, e);
29078 this.on("keydown", L);
29083 * Returns the TabPanel component (creates it if it doesn't exist).
29084 * Note: If you wish to simply check for the existence of tabs without creating them,
29085 * check for a null 'tabs' property.
29086 * @return {Roo.TabPanel} The tabs component
29088 getTabs : function(){
29090 this.el.addClass("x-dlg-auto-tabs");
29091 this.body.addClass(this.tabPosition == "bottom" ? "x-tabs-bottom" : "x-tabs-top");
29092 this.tabs = new Roo.TabPanel(this.body.dom, this.tabPosition == "bottom");
29098 * Adds a button to the footer section of the dialog.
29099 * @param {String/Object} config A string becomes the button text, an object can either be a Button config
29100 * object or a valid Roo.DomHelper element config
29101 * @param {Function} handler The function called when the button is clicked
29102 * @param {Object} scope (optional) The scope of the handler function (accepts position as a property)
29103 * @return {Roo.Button} The new button
29105 addButton : function(M, N, O){
29106 var dh = Roo.DomHelper;
29108 this.footer = dh.append(this.bwrap, {tag: "div", cls:"x-dlg-ft"}, true);
29110 if(!this.btnContainer){
29111 var tb = this.footer.createChild({
29113 cls:"x-dlg-btns x-dlg-btns-"+this.buttonAlign,
29114 html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
29116 this.btnContainer = tb.firstChild.firstChild.firstChild;
29121 minWidth: this.minButtonWidth,
29124 if(typeof M == "string"){
29134 if ((typeof(P.position) != 'undefined') && P.position < this.btnContainer.childNodes.length-1) {
29135 P.position = Math.max(0, P.position);
29136 fc = this.btnContainer.childNodes[P.position];
29139 var Q = new Roo.Button(
29141 this.btnContainer.insertBefore(document.createElement("td"),fc)
29142 : this.btnContainer.appendChild(document.createElement("td")),
29143 //Roo.get(this.btnContainer).createChild( { tag: 'td'}, fc ),
29146 this.syncBodyHeight();
29149 * Array of all the buttons that have been added to this dialog via addButton
29155 this.buttons.push(Q);
29160 * Sets the default button to be focused when the dialog is displayed.
29161 * @param {Roo.BasicDialog.Button} btn The button object returned by {@link #addButton}
29162 * @return {Roo.BasicDialog} this
29164 setDefaultButton : function(R){
29165 this.defaultButton = R;
29170 getHeaderFooterHeight : function(S){
29173 T += this.header.getHeight();
29176 var fm = this.footer.getMargins();
29177 T += (this.footer.getHeight()+fm.top+fm.bottom);
29180 T += this.bwrap.getPadding("tb")+this.bwrap.getBorderWidth("tb");
29181 T += this.centerBg.getPadding("tb");
29186 syncBodyHeight : function(){
29187 var bd = this.body, cb = this.centerBg, bw = this.bwrap;
29188 var U = this.size.height - this.getHeaderFooterHeight(false);
29189 bd.setHeight(U-bd.getMargins("tb"));
29190 var hh = this.header.getHeight();
29191 var h = this.size.height-hh;
29193 bw.setLeftTop(cb.getPadding("l"), hh+cb.getPadding("t"));
29194 bw.setHeight(h-cb.getPadding("tb"));
29195 bw.setWidth(this.el.getWidth(true)-cb.getPadding("lr"));
29196 bd.setWidth(bw.getWidth(true));
29198 this.tabs.syncHeight();
29200 this.tabs.el.repaint();
29206 * Restores the previous state of the dialog if Roo.state is configured.
29207 * @return {Roo.BasicDialog} this
29209 restoreState : function(){
29210 var V = Roo.state.Manager.get(this.stateId || (this.el.id + "-state"));
29212 this.xy = [V.x, V.y];
29213 this.resizeTo(V.width, V.height);
29219 beforeShow : function(){
29221 if(this.fixedcenter){
29222 this.xy = this.el.getCenterXY(true);
29225 Roo.get(document.body).addClass("x-body-masked");
29226 this.mask.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
29230 this.constrainXY();
29234 animShow : function(){
29235 var b = Roo.get(this.animateTarget, true).getBox();
29236 this.proxy.setSize(b.width, b.height);
29237 this.proxy.setLocation(b.x, b.y);
29239 this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height,
29240 true, .35, this.showEl.createDelegate(this));
29244 * Shows the dialog.
29245 * @param {String/HTMLElement/Roo.Element} animateTarget (optional) Reset the animation target
29246 * @return {Roo.BasicDialog} this
29248 show : function(W){
29249 if (this.fireEvent("beforeshow", this) === false){
29252 if(this.syncHeightBeforeShow){
29253 this.syncBodyHeight();
29254 }else if(this.firstShow){
29255 this.firstShow = false;
29256 this.syncBodyHeight(); // sync the height on the first show instead of in the constructor
29259 this.animateTarget = W || this.animateTarget;
29260 if(!this.el.isVisible()){
29262 if(this.animateTarget){
29272 showEl : function(){
29274 this.el.setXY(this.xy);
29276 this.adjustAssets(true);
29279 // IE peekaboo bug - fix found by Dave Fenwick
29284 this.fireEvent("show", this);
29288 * Focuses the dialog. If a defaultButton is set, it will receive focus, otherwise the
29289 * dialog itself will receive focus.
29291 focus : function(){
29292 if(this.defaultButton){
29293 this.defaultButton.focus();
29295 this.focusEl.focus();
29300 constrainXY : function(){
29301 if(this.constraintoviewport !== false){
29302 if(!this.viewSize){
29303 if(this.container){
29304 var s = this.container.getSize();
29305 this.viewSize = [s.width, s.height];
29307 this.viewSize = [Roo.lib.Dom.getViewWidth(),Roo.lib.Dom.getViewHeight()];
29310 var s = Roo.get(this.container||document).getScroll();
29312 var x = this.xy[0], y = this.xy[1];
29313 var w = this.size.width, h = this.size.height;
29314 var vw = this.viewSize[0], vh = this.viewSize[1];
29315 // only move it if it needs it
29317 // first validate right/bottom
29318 if(x + w > vw+s.left){
29322 if(y + h > vh+s.top){
29326 // then make sure top/left isn't negative
29338 if(this.isVisible()){
29339 this.el.setLocation(x, y);
29340 this.adjustAssets();
29347 onDrag : function(){
29348 if(!this.proxyDrag){
29349 this.xy = this.el.getXY();
29350 this.adjustAssets();
29355 adjustAssets : function(X){
29356 var x = this.xy[0], y = this.xy[1];
29357 var w = this.size.width, h = this.size.height;
29360 this.shadow.show(this.el);
29366 if(this.shadow && this.shadow.isVisible()){
29367 this.shadow.show(this.el);
29369 if(this.shim && this.shim.isVisible()){
29370 this.shim.setBounds(x, y, w, h);
29375 adjustViewport : function(w, h){
29377 w = Roo.lib.Dom.getViewWidth();
29378 h = Roo.lib.Dom.getViewHeight();
29382 this.viewSize = [w, h];
29383 if(this.modal && this.mask.isVisible()){
29384 this.mask.setSize(w, h); // first make sure the mask isn't causing overflow
29385 this.mask.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
29387 if(this.isVisible()){
29388 this.constrainXY();
29393 * Destroys this dialog and all its supporting elements (including any tabs, shim,
29394 * shadow, proxy, mask, etc.) Also removes all event listeners.
29395 * @param {Boolean} removeEl (optional) true to remove the element from the DOM
29397 destroy : function(Y){
29398 if(this.isVisible()){
29399 this.animateTarget = null;
29403 Roo.EventManager.removeResizeListener(this.adjustViewport, this);
29405 this.tabs.destroy(Y);
29419 for(var i = 0, len = this.buttons.length; i < len; i++){
29420 this.buttons[i].destroy();
29424 this.el.removeAllListeners();
29426 this.el.update("");
29430 Roo.DialogManager.unregister(this);
29434 startMove : function(){
29435 if(this.proxyDrag){
29438 if(this.constraintoviewport !== false){
29439 this.dd.constrainTo(document.body, {right: this.shadowOffset, bottom: this.shadowOffset});
29444 endMove : function(){
29445 if(!this.proxyDrag){
29446 Roo.dd.DD.prototype.endDrag.apply(this.dd, arguments);
29448 Roo.dd.DDProxy.prototype.endDrag.apply(this.dd, arguments);
29452 this.refreshSize();
29453 this.adjustAssets();
29455 this.fireEvent("move", this, this.xy[0], this.xy[1]);
29459 * Brings this dialog to the front of any other visible dialogs
29460 * @return {Roo.BasicDialog} this
29462 toFront : function(){
29463 Roo.DialogManager.bringToFront(this);
29468 * Sends this dialog to the back (under) of any other visible dialogs
29469 * @return {Roo.BasicDialog} this
29471 toBack : function(){
29472 Roo.DialogManager.sendToBack(this);
29477 * Centers this dialog in the viewport
29478 * @return {Roo.BasicDialog} this
29480 center : function(){
29481 var xy = this.el.getCenterXY(true);
29482 this.moveTo(xy[0], xy[1]);
29487 * Moves the dialog's top-left corner to the specified point
29488 * @param {Number} x
29489 * @param {Number} y
29490 * @return {Roo.BasicDialog} this
29492 moveTo : function(x, y){
29494 if(this.isVisible()){
29495 this.el.setXY(this.xy);
29496 this.adjustAssets();
29502 * Aligns the dialog to the specified element
29503 * @param {String/HTMLElement/Roo.Element} element The element to align to.
29504 * @param {String} position The position to align to (see {@link Roo.Element#alignTo} for more details).
29505 * @param {Array} offsets (optional) Offset the positioning by [x, y]
29506 * @return {Roo.BasicDialog} this
29508 alignTo : function(Z, a, c){
29509 this.xy = this.el.getAlignToXY(Z, a, c);
29510 if(this.isVisible()){
29511 this.el.setXY(this.xy);
29512 this.adjustAssets();
29518 * Anchors an element to another element and realigns it when the window is resized.
29519 * @param {String/HTMLElement/Roo.Element} element The element to align to.
29520 * @param {String} position The position to align to (see {@link Roo.Element#alignTo} for more details)
29521 * @param {Array} offsets (optional) Offset the positioning by [x, y]
29522 * @param {Boolean/Number} monitorScroll (optional) true to monitor body scroll and reposition. If this parameter
29523 * is a number, it is used as the buffer delay (defaults to 50ms).
29524 * @return {Roo.BasicDialog} this
29526 anchorTo : function(el, d, f, g){
29527 var j = function(){
29528 this.alignTo(el, d, f);
29530 Roo.EventManager.onWindowResize(j, this);
29532 if(tm != 'undefined'){
29533 Roo.EventManager.on(window, 'scroll', j, this,
29534 {buffer: tm == 'number' ? g : 50});
29542 * Returns true if the dialog is visible
29543 * @return {Boolean}
29545 isVisible : function(){
29546 return this.el.isVisible();
29550 animHide : function(l){
29551 var b = Roo.get(this.animateTarget).getBox();
29553 this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height);
29555 this.proxy.setBounds(b.x, b.y, b.width, b.height, true, .35,
29556 this.hideEl.createDelegate(this, [l]));
29560 * Hides the dialog.
29561 * @param {Function} callback (optional) Function to call when the dialog is hidden
29562 * @return {Roo.BasicDialog} this
29564 hide : function(m){
29565 if (this.fireEvent("beforehide", this) === false){
29569 this.shadow.hide();
29574 if(this.animateTarget){
29584 hideEl : function(n){
29588 Roo.get(document.body).removeClass("x-body-masked");
29591 this.fireEvent("hide", this);
29592 if(typeof n == "function"){
29598 hideAction : function(){
29599 this.setLeft("-10000px");
29600 this.setTop("-10000px");
29601 this.setStyle("visibility", "hidden");
29605 refreshSize : function(){
29606 this.size = this.el.getSize();
29607 this.xy = this.el.getXY();
29608 Roo.state.Manager.set(this.stateId || this.el.id + "-state", this.el.getBox());
29612 // z-index is managed by the DialogManager and may be overwritten at any time
29613 setZIndex : function(o){
29615 this.mask.setStyle("z-index", o);
29618 this.shim.setStyle("z-index", ++o);
29621 this.shadow.setZIndex(++o);
29624 this.el.setStyle("z-index", ++o);
29626 this.proxy.setStyle("z-index", ++o);
29629 this.resizer.proxy.setStyle("z-index", ++o);
29633 this.lastZIndex = o;
29637 * Returns the element for this dialog
29638 * @return {Roo.Element} The underlying dialog Element
29640 getEl : function(){
29646 * @class Roo.DialogManager
29647 * Provides global access to BasicDialogs that have been created and
29648 * support for z-indexing (layering) multiple open dialogs.
29650 Roo.DialogManager = function(){
29656 var t = function(d1, d2){
29657 return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
29661 var u = function(){
29663 var v = Roo.DialogManager.zseed;
29664 for(var i = 0, len = q.length; i < len; i++){
29667 dlg.setZIndex(v + (i*10));
29674 * The starting z-index for BasicDialogs (defaults to 9000)
29675 * @type Number The z-index value
29680 register : function(AD){
29686 unregister : function(AE){
29691 for( i = 0, AF = q.length; i < AF; i++){
29706 * Gets a registered dialog by id
29707 * @param {String/Object} id The id of the dialog or a dialog
29708 * @return {Roo.BasicDialog} this
29710 get : function(id){
29711 return typeof id == "object" ? id : p[id];
29715 * Brings the specified dialog to the front
29716 * @param {String/Object} dlg The id of the dialog or a dialog
29717 * @return {Roo.BasicDialog} this
29719 bringToFront : function(AG){
29723 AG._lastAccess = new Date().getTime();
29730 * Sends the specified dialog to the back
29731 * @param {String/Object} dlg The id of the dialog or a dialog
29732 * @return {Roo.BasicDialog} this
29734 sendToBack : function(AH){
29736 AH._lastAccess = -(new Date().getTime());
29742 * Hides all dialogs
29744 hideAll : function(){
29746 if(p[id] && typeof p[id] != "function" && p[id].isVisible()){
29755 * @class Roo.LayoutDialog
29756 * @extends Roo.BasicDialog
29757 * Dialog which provides adjustments for working with a layout in a Dialog.
29758 * Add your necessary layout config options to the dialog's config.<br>
29759 * Example usage (including a nested layout):
29762 dialog = new Roo.LayoutDialog("download-dlg", {
29771 // layout config merges with the dialog config
29773 tabPosition: "top",
29774 alwaysShowTabs: true
29777 dialog.addKeyListener(27, dialog.hide, dialog);
29778 dialog.setDefaultButton(dialog.addButton("Close", dialog.hide, dialog));
29779 dialog.addButton("Build It!", this.getDownload, this);
29781 // we can even add nested layouts
29782 var innerLayout = new Roo.BorderLayout("dl-inner", {
29792 innerLayout.beginUpdate();
29793 innerLayout.add("east", new Roo.ContentPanel("dl-details"));
29794 innerLayout.add("center", new Roo.ContentPanel("selection-panel"));
29795 innerLayout.endUpdate(true);
29797 var layout = dialog.getLayout();
29798 layout.beginUpdate();
29799 layout.add("center", new Roo.ContentPanel("standard-panel",
29800 {title: "Download the Source", fitToFrame:true}));
29801 layout.add("center", new Roo.NestedLayoutPanel(innerLayout,
29802 {title: "Build your own roo.js"}));
29803 layout.getRegion("center").showPanel(sp);
29804 layout.endUpdate();
29808 * @param {String/HTMLElement/Roo.Element} el The id of or container element, or config
29809 * @param {Object} config configuration options
29811 Roo.LayoutDialog = function(el, v){
29814 if (typeof(v) == 'undefined') {
29815 z = Roo.apply({}, el);
29816 el = Roo.get( document.documentElement || document.body).createChild();
29817 //config.autoCreate = true;
29822 z.autoTabs = false;
29823 Roo.LayoutDialog.superclass.constructor.call(this, el, z);
29824 this.body.setStyle({overflow:"hidden", position:"relative"});
29825 this.layout = new Roo.BorderLayout(this.body.dom, z);
29826 this.layout.monitorWindowResize = false;
29827 this.el.addClass("x-dlg-auto-layout");
29828 // fix case when center region overwrites center function
29829 this.center = Roo.BasicDialog.prototype.center;
29830 this.on("show", this.layout.layout, this.layout, true);
29832 var xitems = z.items;
29834 Roo.each(xitems, this.addxtype, this);
29839 Roo.extend(Roo.LayoutDialog, Roo.BasicDialog, {
29841 * Ends update of the layout <strike>and resets display to none</strike>. Use standard beginUpdate/endUpdate on the layout.
29844 endUpdate : function(){
29845 this.layout.endUpdate();
29849 * Begins an update of the layout <strike>and sets display to block and visibility to hidden</strike>. Use standard beginUpdate/endUpdate on the layout.
29852 beginUpdate : function(){
29853 this.layout.beginUpdate();
29857 * Get the BorderLayout for this dialog
29858 * @return {Roo.BorderLayout}
29860 getLayout : function(){
29861 return this.layout;
29864 showEl : function(){
29865 Roo.LayoutDialog.superclass.showEl.apply(this, arguments);
29867 this.layout.layout();
29872 // Use the syncHeightBeforeShow config option to control this automatically
29873 syncBodyHeight : function(){
29874 Roo.LayoutDialog.superclass.syncBodyHeight.call(this);
29875 if(this.layout){this.layout.layout();}
29879 * Add an xtype element (actually adds to the layout.)
29880 * @return {Object} xdata xtype object data.
29883 addxtype : function(c) {
29884 return this.layout.addxtype(c);
29889 * Ext JS Library 1.1.1
29890 * Copyright(c) 2006-2007, Ext JS, LLC.
29892 * Originally Released Under LGPL - original licence link has changed is not relivant.
29895 * <script type="text/javascript">
29899 * @class Roo.MessageBox
29900 * Utility class for generating different styles of message boxes. The alias Roo.Msg can also be used.
29904 Roo.Msg.alert('Status', 'Changes saved successfully.');
29906 // Prompt for user data:
29907 Roo.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
29909 // process text value...
29913 // Show a dialog using config options:
29915 title:'Save Changes?',
29916 msg: 'Your are closing a tab that has unsaved changes. Would you like to save your changes?',
29917 buttons: Roo.Msg.YESNOCANCEL,
29924 Roo.MessageBox = function(){
29926 var E, F, G, H, I, pp;
29930 var M = function(Q){
29932 Roo.callback(B.fn, B.scope||window, [Q, K.dom.value], 1);
29936 var N = function(){
29938 A.el.removeClass(B.cls);
29941 Roo.TaskMgr.stop(D);
29947 var O = function(b){
29951 J["cancel"].hide();
29954 A.footer.dom.style.display = 'none';
29958 A.footer.dom.style.display = '';
29960 if(typeof J[k] != "function"){
29963 J[k].setText(typeof b[k] == "string" ? b[k] : Roo.MessageBox.buttonText[k]);
29964 Q += J[k].el.getWidth()+15;
29974 var P = function(d, k, e){
29975 if(B && B.closable !== false){
29985 * Returns a reference to the underlying {@link Roo.BasicDialog} element
29986 * @return {Roo.BasicDialog} The BasicDialog element
29988 getDialog : function(){
29990 A = new Roo.BasicDialog("x-msg-box", {
29995 constraintoviewport:false,
29997 collapsible : false,
30000 width:400, height:100,
30001 buttonAlign:"center",
30002 closeClick : function(){
30003 if(B && B.buttons && B.buttons.no && !B.buttons.cancel){
30012 A.addKeyListener(27, P);
30014 var bt = this.buttonText;
30015 J["ok"] = A.addButton(bt["ok"], M.createCallback("ok"));
30016 J["yes"] = A.addButton(bt["yes"], M.createCallback("yes"));
30017 J["no"] = A.addButton(bt["no"], M.createCallback("no"));
30018 J["cancel"] = A.addButton(bt["cancel"], M.createCallback("cancel"));
30019 E = A.body.createChild({
30021 html:'<span class="roo-mb-text"></span><br /><input type="text" class="roo-mb-input" /><textarea class="roo-mb-textarea"></textarea><div class="roo-mb-progress-wrap"><div class="roo-mb-progress"><div class="roo-mb-progress-bar"> </div></div></div>'
30023 F = E.dom.firstChild;
30024 G = Roo.get(E.dom.childNodes[2]);
30025 G.enableDisplayMode();
30026 G.addKeyListener([10,13], function(){
30027 if(A.isVisible() && B && B.buttons){
30030 }else if(B.buttons.yes){
30035 H = Roo.get(E.dom.childNodes[3]);
30036 H.enableDisplayMode();
30037 I = Roo.get(E.dom.childNodes[4]);
30038 I.enableDisplayMode();
30039 var pf = I.dom.firstChild;
30041 pp = Roo.get(pf.firstChild);
30042 pp.setHeight(pf.offsetHeight);
30050 * Updates the message box body text
30051 * @param {String} text (optional) Replaces the message box element's innerHTML with the specified string (defaults to
30052 * the XHTML-compliant non-breaking space character '&#160;')
30053 * @return {Roo.MessageBox} This message box
30055 updateText : function(j){
30056 if(!A.isVisible() && !B.width){
30057 A.resizeTo(this.maxWidth, 100); // resize first so content is never clipped from previous shows
30060 F.innerHTML = j || ' ';
30061 var w = Math.max(Math.min(B.width || F.offsetWidth, this.maxWidth),
30062 Math.max(B.minWidth || this.minWidth, L));
30067 A.fixedcenter = false;
30070 A.setContentSize(w, E.getHeight());
30072 A.fixedcenter = true;
30078 * Updates a progress-style message box's text and progress bar. Only relevant on message boxes
30079 * initiated via {@link Roo.MessageBox#progress} or by calling {@link Roo.MessageBox#show} with progress: true.
30080 * @param {Number} value Any number between 0 and 1 (e.g., .5)
30081 * @param {String} text (optional) If defined, the message box's body text is replaced with the specified string (defaults to undefined)
30082 * @return {Roo.MessageBox} This message box
30084 updateProgress : function(l, m){
30086 this.updateText(m);
30088 if (pp) { // weird bug on my firefox - for some reason this is not defined
30089 pp.setWidth(Math.floor(l*I.dom.firstChild.offsetWidth));
30095 * Returns true if the message box is currently displayed
30096 * @return {Boolean} True if the message box is visible, else false
30098 isVisible : function(){
30099 return A && A.isVisible();
30103 * Hides the message box if it is displayed
30106 if(this.isVisible()){
30112 * Displays a new message box, or reinitializes an existing message box, based on the config options
30113 * passed in. All functions (e.g. prompt, alert, etc) on MessageBox call this function internally.
30114 * The following config object properties are supported:
30116 Property Type Description
30117 ---------- --------------- ------------------------------------------------------------------------------------
30118 animEl String/Element An id or Element from which the message box should animate as it opens and
30119 closes (defaults to undefined)
30120 buttons Object/Boolean A button config object (e.g., Roo.MessageBox.OKCANCEL or {ok:'Foo',
30121 cancel:'Bar'}), or false to not show any buttons (defaults to false)
30122 closable Boolean False to hide the top-right close button (defaults to true). Note that
30123 progress and wait dialogs will ignore this property and always hide the
30124 close button as they can only be closed programmatically.
30125 cls String A custom CSS class to apply to the message box element
30126 defaultTextHeight Number The default height in pixels of the message box's multiline textarea if
30127 displayed (defaults to 75)
30128 fn Function A callback function to execute after closing the dialog. The arguments to the
30129 function will be btn (the name of the button that was clicked, if applicable,
30130 e.g. "ok"), and text (the value of the active text field, if applicable).
30131 Progress and wait dialogs will ignore this option since they do not respond to
30132 user actions and can only be closed programmatically, so any required function
30133 should be called by the same code after it closes the dialog.
30134 icon String A CSS class that provides a background image to be used as an icon for
30135 the dialog (e.g., Roo.MessageBox.WARNING or 'custom-class', defaults to '')
30136 maxWidth Number The maximum width in pixels of the message box (defaults to 600)
30137 minWidth Number The minimum width in pixels of the message box (defaults to 100)
30138 modal Boolean False to allow user interaction with the page while the message box is
30139 displayed (defaults to true)
30140 msg String A string that will replace the existing message box body text (defaults
30141 to the XHTML-compliant non-breaking space character ' ')
30142 multiline Boolean True to prompt the user to enter multi-line text (defaults to false)
30143 progress Boolean True to display a progress bar (defaults to false)
30144 progressText String The text to display inside the progress bar if progress = true (defaults to '')
30145 prompt Boolean True to prompt the user to enter single-line text (defaults to false)
30146 proxyDrag Boolean True to display a lightweight proxy while dragging (defaults to false)
30147 title String The title text
30148 value String The string value to set into the active textbox element if displayed
30149 wait Boolean True to display a progress bar (defaults to false)
30150 width Number The width of the dialog in pixels
30157 msg: 'Please enter your address:',
30159 buttons: Roo.MessageBox.OKCANCEL,
30162 animEl: 'addAddressBtn'
30165 * @param {Object} config Configuration options
30166 * @return {Roo.MessageBox} This message box
30168 show : function(n){
30169 if(this.isVisible()){
30172 var d = this.getDialog();
30174 d.setTitle(B.title || " ");
30175 d.close.setDisplayed(B.closable !== false);
30177 B.prompt = B.prompt || (B.multiline ? true : false);
30182 H.setHeight(typeof B.multiline == "number" ?
30183 B.multiline : this.defaultTextHeight);
30194 I.setDisplayed(B.progress === true);
30195 this.updateProgress(0);
30196 K.dom.value = B.value || "";
30198 A.setDefaultButton(K);
30200 var bs = B.buttons;
30204 }else if(bs && bs.yes){
30208 A.setDefaultButton(db);
30212 this.updateText(B.msg);
30214 d.el.addClass(B.cls);
30217 d.proxyDrag = B.proxyDrag === true;
30218 d.modal = B.modal !== false;
30219 d.mask = B.modal !== false ? C : false;
30220 if(!d.isVisible()){
30221 // force it to the end of the z-index stack so it gets a cursor in FF
30222 document.body.appendChild(A.el.dom);
30223 d.animateTarget = null;
30230 * Displays a message box with a progress bar. This message box has no buttons and is not closeable by
30231 * the user. You are responsible for updating the progress bar as needed via {@link Roo.MessageBox#updateProgress}
30232 * and closing the message box when the process is complete.
30233 * @param {String} title The title bar text
30234 * @param {String} msg The message box body text
30235 * @return {Roo.MessageBox} This message box
30237 progress : function(o, p){
30244 minWidth: this.minProgressWidth,
30251 * Displays a standard read-only message box with an OK button (comparable to the basic JavaScript Window.alert).
30252 * If a callback function is passed it will be called after the user clicks the button, and the
30253 * id of the button that was clicked will be passed as the only parameter to the callback
30254 * (could also be the top-right close button).
30255 * @param {String} title The title bar text
30256 * @param {String} msg The message box body text
30257 * @param {Function} fn (optional) The callback function invoked after the message box is closed
30258 * @param {Object} scope (optional) The scope of the callback function
30259 * @return {Roo.MessageBox} This message box
30261 alert : function(q, r, fn, s){
30274 * Displays a message box with an infinitely auto-updating progress bar. This can be used to block user
30275 * interaction while waiting for a long-running process to complete that does not have defined intervals.
30276 * You are responsible for closing the message box when the process is complete.
30277 * @param {String} msg The message box body text
30278 * @param {String} title (optional) The title bar text
30279 * @return {Roo.MessageBox} This message box
30281 wait : function(t, u){
30292 D = Roo.TaskMgr.start({
30294 Roo.MessageBox.updateProgress(((((i+20)%20)+1)*5)*.01);
30302 * Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's Window.confirm).
30303 * If a callback function is passed it will be called after the user clicks either button, and the id of the
30304 * button that was clicked will be passed as the only parameter to the callback (could also be the top-right close button).
30305 * @param {String} title The title bar text
30306 * @param {String} msg The message box body text
30307 * @param {Function} fn (optional) The callback function invoked after the message box is closed
30308 * @param {Object} scope (optional) The scope of the callback function
30309 * @return {Roo.MessageBox} This message box
30311 confirm : function(v, x, fn, y){
30315 buttons: this.YESNO,
30324 * Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to
30325 * JavaScript's Window.prompt). The prompt can be a single-line or multi-line textbox. If a callback function
30326 * is passed it will be called after the user clicks either button, and the id of the button that was clicked
30327 * (could also be the top-right close button) and the text that was entered will be passed as the two
30328 * parameters to the callback.
30329 * @param {String} title The title bar text
30330 * @param {String} msg The message box body text
30331 * @param {Function} fn (optional) The callback function invoked after the message box is closed
30332 * @param {Object} scope (optional) The scope of the callback function
30333 * @param {Boolean/Number} multiline (optional) True to create a multiline textbox using the defaultTextHeight
30334 * property, or the height in pixels to create the textbox (defaults to false / single-line)
30335 * @return {Roo.MessageBox} This message box
30337 prompt : function(z, AA, fn, AB, AC){
30341 buttons: this.OKCANCEL,
30353 * Button config that displays a single OK button
30358 * Button config that displays Yes and No buttons
30361 YESNO : {yes:true, no:true},
30363 * Button config that displays OK and Cancel buttons
30366 OKCANCEL : {ok:true, cancel:true},
30368 * Button config that displays Yes, No and Cancel buttons
30371 YESNOCANCEL : {yes:true, no:true, cancel:true},
30374 * The default height in pixels of the message box's multiline textarea if displayed (defaults to 75)
30377 defaultTextHeight : 75,
30379 * The maximum width in pixels of the message box (defaults to 600)
30384 * The minimum width in pixels of the message box (defaults to 100)
30389 * The minimum width in pixels of the message box if it is a progress-style dialog. This is useful
30390 * for setting a different minimum width than text-only dialogs may need (defaults to 250)
30393 minProgressWidth : 250,
30395 * An object containing the default button text strings that can be overriden for localized language support.
30396 * Supported properties are: ok, cancel, yes and no.
30397 * Customize the default text like so: Roo.MessageBox.buttonText.yes = "S?";
30410 * Shorthand for {@link Roo.MessageBox}
30412 Roo.Msg = Roo.MessageBox;
30415 * Ext JS Library 1.1.1
30416 * Copyright(c) 2006-2007, Ext JS, LLC.
30418 * Originally Released Under LGPL - original licence link has changed is not relivant.
30421 * <script type="text/javascript">
30424 * @class Roo.QuickTips
30425 * Provides attractive and customizable tooltips for any element.
30428 Roo.QuickTips = function(){
30429 var el, A, B, C, tm, D, E, F = {}, esc, removeCls = null, bdLeft, bdRight;
30430 var ce, bd, xy, dd;
30431 var G = false, H = true, I = false;
30432 var J = 1, K = 1, L = 1, M = [];
30434 var N = function(e){
30438 var t = e.getTarget();
30439 if(!t || t.nodeType !== 1 || t == document || t == document.body){
30442 if(ce && t == ce.el){
30448 J = S.defer(tm.showDelay, tm, [F[t.id]]);
30451 var W, et = Roo.fly(t);
30452 var ns = D.namespace;
30453 if(tm.interceptTitles && t.title){
30456 t.removeAttribute("title");
30457 e.preventDefault();
30459 W = t.qtip || et.getAttributeNS(ns, D.attribute);
30462 J = S.defer(tm.showDelay, tm, [{
30465 width: et.getAttributeNS(ns, D.width),
30466 autoHide: et.getAttributeNS(ns, D.hide) != "user",
30467 title: et.getAttributeNS(ns, D.title),
30468 cls: et.getAttributeNS(ns, D.cls)
30473 var O = function(e){
30475 var t = e.getTarget();
30476 if(t && ce && ce.el == t && (tm.autoHide && ce.autoHide !== false)){
30477 K = setTimeout(U, tm.hideDelay);
30481 var P = function(e){
30488 if(tm.trackMouse && ce){
30493 var Q = function(e){
30497 if(tm.hideOnClick){
30500 tm.enable.defer(100, tm);
30505 var R = function(){
30506 return 2;//bdLeft.getPadding('l')+bdRight.getPadding('r');
30509 var S = function(o){
30516 if(removeCls){ // in case manually hidden
30517 el.removeClass(removeCls);
30521 el.addClass(ce.cls);
30522 removeCls = ce.cls;
30525 C.update(ce.title);
30532 el.dom.style.width = tm.maxWidth+'px';
30533 //tipBody.dom.style.width = '';
30535 var p = R(), w = ce.width;
30538 var aw = Math.max(td.offsetWidth, td.clientWidth, td.scrollWidth);
30539 if(aw > tm.maxWidth){
30541 }else if(aw < tm.minWidth){
30548 //tipBody.setWidth(w);
30549 el.setWidth(parseInt(w, 10) + p);
30550 if(ce.autoHide === false){
30551 E.setDisplayed(true);
30556 E.setDisplayed(false);
30562 el.avoidY = xy[1]-18;
30567 el.setStyle("visibility", "visible");
30568 el.fadeIn({callback: T});
30574 var T = function(){
30578 if(tm.autoDismiss && ce.autoHide !== false){
30579 L = setTimeout(U, tm.autoDismissDelay);
30584 var U = function(W){
30588 if(el.isVisible()){
30590 if(W !== true && tm.animate){
30591 el.fadeOut({callback: V});
30598 var V = function(){
30601 el.removeClass(removeCls);
30608 * @cfg {Number} minWidth
30609 * The minimum width of the quick tip (defaults to 40)
30613 * @cfg {Number} maxWidth
30614 * The maximum width of the quick tip (defaults to 300)
30618 * @cfg {Boolean} interceptTitles
30619 * True to automatically use the element's DOM title value if available (defaults to false)
30621 interceptTitles : false,
30623 * @cfg {Boolean} trackMouse
30624 * True to have the quick tip follow the mouse as it moves over the target element (defaults to false)
30626 trackMouse : false,
30628 * @cfg {Boolean} hideOnClick
30629 * True to hide the quick tip if the user clicks anywhere in the document (defaults to true)
30631 hideOnClick : true,
30633 * @cfg {Number} showDelay
30634 * Delay in milliseconds before the quick tip displays after the mouse enters the target element (defaults to 500)
30638 * @cfg {Number} hideDelay
30639 * Delay in milliseconds before the quick tip hides when autoHide = true (defaults to 200)
30643 * @cfg {Boolean} autoHide
30644 * True to automatically hide the quick tip after the mouse exits the target element (defaults to true).
30645 * Used in conjunction with hideDelay.
30650 * True to automatically hide the quick tip after a set period of time, regardless of the user's actions
30651 * (defaults to true). Used in conjunction with autoDismissDelay.
30653 autoDismiss : true,
30656 * Delay in milliseconds before the quick tip hides when autoDismiss = true (defaults to 5000)
30658 autoDismissDelay : 5000,
30660 * @cfg {Boolean} animate
30661 * True to turn on fade animation. Defaults to false (ClearType/scrollbar flicker issues in IE7).
30666 * @cfg {String} title
30667 * Title text to display (defaults to ''). This can be any valid HTML markup.
30671 * @cfg {String} text
30672 * Body text to display (defaults to ''). This can be any valid HTML markup.
30676 * @cfg {String} cls
30677 * A CSS class to apply to the base quick tip element (defaults to '').
30681 * @cfg {Number} width
30682 * Width in pixels of the quick tip (defaults to auto). Width will be ignored if it exceeds the bounds of
30683 * minWidth or maxWidth.
30688 * Initialize and enable QuickTips for first use. This should be called once before the first attempt to access
30689 * or display QuickTips in a page.
30692 tm = Roo.QuickTips;
30695 if(!Roo.isReady){ // allow calling of init() before onReady
30696 Roo.onReady(Roo.QuickTips.init, Roo.QuickTips);
30700 el = new Roo.Layer({cls:"x-tip", shadow:"drop", shim: true, constrain:true, shadowOffset:4});
30701 el.fxDefaults = {stopFx: true};
30702 // maximum custom styling
30703 //el.update('<div class="x-tip-top-left"><div class="x-tip-top-right"><div class="x-tip-top"></div></div></div><div class="x-tip-bd-left"><div class="x-tip-bd-right"><div class="x-tip-bd"><div class="x-tip-close"></div><h3></h3><div class="x-tip-bd-inner"></div><div class="x-clear"></div></div></div></div><div class="x-tip-ft-left"><div class="x-tip-ft-right"><div class="x-tip-ft"></div></div></div>');
30704 el.update('<div class="x-tip-bd"><div class="x-tip-close"></div><h3></h3><div class="x-tip-bd-inner"></div><div class="x-clear"></div></div>');
30705 C = el.child('h3');
30706 C.enableDisplayMode("block");
30707 A = el.child('div.x-tip-bd');
30708 B = el.child('div.x-tip-bd-inner');
30709 //bdLeft = el.child('div.x-tip-bd-left');
30710 //bdRight = el.child('div.x-tip-bd-right');
30711 E = el.child('div.x-tip-close');
30712 E.enableDisplayMode("block");
30714 var d = Roo.get(document);
30715 d.on("mousedown", Q);
30716 d.on("mouseover", N);
30717 d.on("mouseout", O);
30718 d.on("mousemove", P);
30719 esc = d.addKeyListener(27, U);
30722 dd = el.initDD("default", null, {
30723 onDrag : function(){
30727 dd.setHandleElId(C.id);
30738 * Configures a new quick tip instance and assigns it to a target element. The following config options
30741 Property Type Description
30742 ---------- --------------------- ------------------------------------------------------------------------
30743 target Element/String/Array An Element, id or array of ids that this quick tip should be tied to
30745 * @param {Object} config The config object
30747 register : function(X){
30748 var cs = X instanceof Array ? X : arguments;
30749 for(var i = 0, len = cs.length; i < len; i++) {
30751 var target = c.target;
30753 if(target instanceof Array){
30754 for(var j = 0, jlen = target.length; j < jlen; j++){
30758 F[typeof target == 'string' ? target : Roo.id(target)] = c;
30765 * Removes this quick tip from its element and destroys it.
30766 * @param {String/HTMLElement/Element} el The element from which the quick tip is to be removed.
30768 unregister : function(el){
30769 delete F[Roo.id(el)];
30773 * Enable this quick tip.
30775 enable : function(){
30785 * Disable this quick tip.
30787 disable : function(){
30800 * Returns true if the quick tip is enabled, else false.
30802 isEnabled : function(){
30809 attribute : "qtip",
30819 // backwards compat
30820 Roo.QuickTips.tips = Roo.QuickTips.register;
30823 * Ext JS Library 1.1.1
30824 * Copyright(c) 2006-2007, Ext JS, LLC.
30826 * Originally Released Under LGPL - original licence link has changed is not relivant.
30829 * <script type="text/javascript">
30834 * @class Roo.tree.TreePanel
30835 * @extends Roo.data.Tree
30837 * @cfg {Boolean} rootVisible false to hide the root node (defaults to true)
30838 * @cfg {Boolean} lines false to disable tree lines (defaults to true)
30839 * @cfg {Boolean} enableDD true to enable drag and drop
30840 * @cfg {Boolean} enableDrag true to enable just drag
30841 * @cfg {Boolean} enableDrop true to enable just drop
30842 * @cfg {Object} dragConfig Custom config to pass to the {@link Roo.tree.TreeDragZone} instance
30843 * @cfg {Object} dropConfig Custom config to pass to the {@link Roo.tree.TreeDropZone} instance
30844 * @cfg {String} ddGroup The DD group this TreePanel belongs to
30845 * @cfg {String} ddAppendOnly True if the tree should only allow append drops (use for trees which are sorted)
30846 * @cfg {Boolean} ddScroll true to enable YUI body scrolling
30847 * @cfg {Boolean} containerScroll true to register this container with ScrollManager
30848 * @cfg {Boolean} hlDrop false to disable node highlight on drop (defaults to the value of Roo.enableFx)
30849 * @cfg {String} hlColor The color of the node highlight (defaults to C3DAF9)
30850 * @cfg {Boolean} animate true to enable animated expand/collapse (defaults to the value of Roo.enableFx)
30851 * @cfg {Boolean} singleExpand true if only 1 node per branch may be expanded
30852 * @cfg {Boolean} selModel A tree selection model to use with this TreePanel (defaults to a {@link Roo.tree.DefaultSelectionModel})
30853 * @cfg {Boolean} loader A TreeLoader for use with this TreePanel
30854 * @cfg {String} pathSeparator The token used to separate sub-paths in path strings (defaults to '/')
30855 * @cfg {Function} renderer Sets the rendering (formatting) function for the nodes. to return HTML markup for the tree view. The render function is called with the following parameters:<ul><li>The {Object} The data for the node.</li></ul>
30856 * @cfg {Function} rendererTip Sets the rendering (formatting) function for the nodes hovertip to return HTML markup for the tree view. The render function is called with the following parameters:<ul><li>The {Object} The data for the node.</li></ul>
30859 * @param {String/HTMLElement/Element} el The container element
30860 * @param {Object} config
30862 Roo.tree.TreePanel = function(el, A){
30875 Roo.apply(this, A);
30876 Roo.tree.TreePanel.superclass.constructor.call(this);
30877 this.el = Roo.get(el);
30878 this.el.addClass('x-tree');
30879 //console.log(root);
30881 this.setRootNode( Roo.factory(B, Roo.tree));
30884 this.loader = Roo.factory(C, Roo.tree);
30888 * Read-only. The id of the container element becomes this TreePanel's id.
30890 this.id = this.el.id;
30893 * @event beforeload
30894 * Fires before a node is loaded, return false to cancel
30895 * @param {Node} node The node being loaded
30897 "beforeload" : true,
30900 * Fires when a node is loaded
30901 * @param {Node} node The node that was loaded
30905 * @event textchange
30906 * Fires when the text for a node is changed
30907 * @param {Node} node The node
30908 * @param {String} text The new text
30909 * @param {String} oldText The old text
30911 "textchange" : true,
30913 * @event beforeexpand
30914 * Fires before a node is expanded, return false to cancel.
30915 * @param {Node} node The node
30916 * @param {Boolean} deep
30917 * @param {Boolean} anim
30919 "beforeexpand" : true,
30921 * @event beforecollapse
30922 * Fires before a node is collapsed, return false to cancel.
30923 * @param {Node} node The node
30924 * @param {Boolean} deep
30925 * @param {Boolean} anim
30927 "beforecollapse" : true,
30930 * Fires when a node is expanded
30931 * @param {Node} node The node
30935 * @event disabledchange
30936 * Fires when the disabled status of a node changes
30937 * @param {Node} node The node
30938 * @param {Boolean} disabled
30940 "disabledchange" : true,
30943 * Fires when a node is collapsed
30944 * @param {Node} node The node
30948 * @event beforeclick
30949 * Fires before click processing on a node. Return false to cancel the default action.
30950 * @param {Node} node The node
30951 * @param {Roo.EventObject} e The event object
30953 "beforeclick":true,
30955 * @event checkchange
30956 * Fires when a node with a checkbox's checked property changes
30957 * @param {Node} this This node
30958 * @param {Boolean} checked
30960 "checkchange":true,
30963 * Fires when a node is clicked
30964 * @param {Node} node The node
30965 * @param {Roo.EventObject} e The event object
30970 * Fires when a node is double clicked
30971 * @param {Node} node The node
30972 * @param {Roo.EventObject} e The event object
30976 * @event contextmenu
30977 * Fires when a node is right clicked
30978 * @param {Node} node The node
30979 * @param {Roo.EventObject} e The event object
30981 "contextmenu":true,
30983 * @event beforechildrenrendered
30984 * Fires right before the child nodes for a node are rendered
30985 * @param {Node} node The node
30987 "beforechildrenrendered":true,
30990 * Fires when a node starts being dragged
30991 * @param {Roo.tree.TreePanel} this
30992 * @param {Roo.tree.TreeNode} node
30993 * @param {event} e The raw browser event
30995 "startdrag" : true,
30998 * Fires when a drag operation is complete
30999 * @param {Roo.tree.TreePanel} this
31000 * @param {Roo.tree.TreeNode} node
31001 * @param {event} e The raw browser event
31006 * Fires when a dragged node is dropped on a valid DD target
31007 * @param {Roo.tree.TreePanel} this
31008 * @param {Roo.tree.TreeNode} node
31009 * @param {DD} dd The dd it was dropped on
31010 * @param {event} e The raw browser event
31014 * @event beforenodedrop
31015 * Fires when a DD object is dropped on a node in this tree for preprocessing. Return false to cancel the drop. The dropEvent
31016 * passed to handlers has the following properties:<br />
31017 * <ul style="padding:5px;padding-left:16px;">
31018 * <li>tree - The TreePanel</li>
31019 * <li>target - The node being targeted for the drop</li>
31020 * <li>data - The drag data from the drag source</li>
31021 * <li>point - The point of the drop - append, above or below</li>
31022 * <li>source - The drag source</li>
31023 * <li>rawEvent - Raw mouse event</li>
31024 * <li>dropNode - Drop node(s) provided by the source <b>OR</b> you can supply node(s)
31025 * to be inserted by setting them on this object.</li>
31026 * <li>cancel - Set this to true to cancel the drop.</li>
31028 * @param {Object} dropEvent
31030 "beforenodedrop" : true,
31033 * Fires after a DD object is dropped on a node in this tree. The dropEvent
31034 * passed to handlers has the following properties:<br />
31035 * <ul style="padding:5px;padding-left:16px;">
31036 * <li>tree - The TreePanel</li>
31037 * <li>target - The node being targeted for the drop</li>
31038 * <li>data - The drag data from the drag source</li>
31039 * <li>point - The point of the drop - append, above or below</li>
31040 * <li>source - The drag source</li>
31041 * <li>rawEvent - Raw mouse event</li>
31042 * <li>dropNode - Dropped node(s).</li>
31044 * @param {Object} dropEvent
31048 * @event nodedragover
31049 * Fires when a tree node is being targeted for a drag drop, return false to signal drop not allowed. The dragOverEvent
31050 * passed to handlers has the following properties:<br />
31051 * <ul style="padding:5px;padding-left:16px;">
31052 * <li>tree - The TreePanel</li>
31053 * <li>target - The node being targeted for the drop</li>
31054 * <li>data - The drag data from the drag source</li>
31055 * <li>point - The point of the drop - append, above or below</li>
31056 * <li>source - The drag source</li>
31057 * <li>rawEvent - Raw mouse event</li>
31058 * <li>dropNode - Drop node(s) provided by the source.</li>
31059 * <li>cancel - Set this to true to signal drop not allowed.</li>
31061 * @param {Object} dragOverEvent
31063 "nodedragover" : true
31066 if(this.singleExpand){
31067 this.on("beforeexpand", this.restrictExpand, this);
31070 Roo.extend(Roo.tree.TreePanel, Roo.data.Tree, {
31071 rootVisible : true,
31072 animate: Roo.enableFx,
31075 hlDrop : Roo.enableFx,
31079 rendererTip: false,
31081 restrictExpand : function(D){
31082 var p = D.parentNode;
31084 if(p.expandedChild && p.expandedChild.parentNode == p){
31085 p.expandedChild.collapse();
31088 p.expandedChild = D;
31092 // private override
31093 setRootNode : function(E){
31094 Roo.tree.TreePanel.superclass.setRootNode.call(this, E);
31095 if(!this.rootVisible){
31096 E.ui = new Roo.tree.RootTreeNodeUI(E);
31102 * Returns the container element for this TreePanel
31104 getEl : function(){
31109 * Returns the default TreeLoader for this TreePanel
31111 getLoader : function(){
31112 return this.loader;
31118 expandAll : function(){
31119 this.root.expand(true);
31123 * Collapse all nodes
31125 collapseAll : function(){
31126 this.root.collapse(true);
31130 * Returns the selection model used by this TreePanel
31132 getSelectionModel : function(){
31133 if(!this.selModel){
31134 this.selModel = new Roo.tree.DefaultSelectionModel();
31136 return this.selModel;
31140 * Retrieve an array of checked nodes, or an array of a specific attribute of checked nodes (e.g. "id")
31141 * @param {String} attribute (optional) Defaults to null (return the actual nodes)
31142 * @param {TreeNode} startNode (optional) The node to start from, defaults to the root
31145 getChecked : function(a, F){
31146 F = F || this.root;
31148 var f = function(){
31149 if(this.attributes.checked){
31150 r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
31159 * Expands a specified path in this TreePanel. A path can be retrieved from a node with {@link Roo.data.Node#getPath}
31160 * @param {String} path
31161 * @param {String} attr (optional) The attribute used in the path (see {@link Roo.data.Node#getPath} for more info)
31162 * @param {Function} callback (optional) The callback to call when the expand is complete. The callback will be called with
31163 * (bSuccess, oLastNode) where bSuccess is if the expand was successful and oLastNode is the last node that was expanded.
31165 expandPath : function(G, H, I){
31167 var J = G.split(this.pathSeparator);
31169 if(K.attributes[H] != J[1]){ // invalid root
31176 var f = function(){
31177 if(++L == J.length){
31183 var c = K.findChild(H, J[L]);
31192 c.expand(false, false, f);
31194 K.expand(false, false, f);
31198 * Selects the node in this tree at the specified path. A path can be retrieved from a node with {@link Roo.data.Node#getPath}
31199 * @param {String} path
31200 * @param {String} attr (optional) The attribute used in the path (see {@link Roo.data.Node#getPath} for more info)
31201 * @param {Function} callback (optional) The callback to call when the selection is complete. The callback will be called with
31202 * (bSuccess, oSelNode) where bSuccess is if the selection was successful and oSelNode is the selected node.
31204 selectPath : function(M, N, O){
31206 var P = M.split(this.pathSeparator);
31209 var f = function(Q, R){
31211 var n = R.findChild(N, v);
31226 this.expandPath(P.join(this.pathSeparator), N, f);
31228 this.root.select();
31230 O(true, this.root);
31235 getTreeEl : function(){
31240 * Trigger rendering of this TreePanel
31242 render : function(){
31243 if (this.innerCt) {
31244 return this; // stop it rendering more than once!!
31248 this.innerCt = this.el.createChild({tag:"ul",
31249 cls:"x-tree-root-ct " +
31250 (this.lines ? "x-tree-lines" : "x-tree-no-lines")});
31252 if(this.containerScroll){
31253 Roo.dd.ScrollManager.register(this.el);
31255 if((this.enableDD || this.enableDrop) && !this.dropZone){
31257 * The dropZone used by this tree if drop is enabled
31258 * @type Roo.tree.TreeDropZone
31260 this.dropZone = new Roo.tree.TreeDropZone(this, this.dropConfig || {
31261 ddGroup: this.ddGroup || "TreeDD", appendOnly: this.ddAppendOnly === true
31264 if((this.enableDD || this.enableDrag) && !this.dragZone){
31266 * The dragZone used by this tree if drag is enabled
31267 * @type Roo.tree.TreeDragZone
31269 this.dragZone = new Roo.tree.TreeDragZone(this, this.dragConfig || {
31270 ddGroup: this.ddGroup || "TreeDD",
31271 scroll: this.ddScroll
31275 this.getSelectionModel().init(this);
31277 console.log("ROOT not set in tree");
31281 this.root.render();
31282 if(!this.rootVisible){
31283 this.root.renderChildren();
31290 * Ext JS Library 1.1.1
31291 * Copyright(c) 2006-2007, Ext JS, LLC.
31293 * Originally Released Under LGPL - original licence link has changed is not relivant.
31296 * <script type="text/javascript">
31301 * @class Roo.tree.DefaultSelectionModel
31302 * @extends Roo.util.Observable
31303 * The default single selection for a TreePanel.
31305 Roo.tree.DefaultSelectionModel = function(){
31306 this.selNode = null;
31310 * @event selectionchange
31311 * Fires when the selected node changes
31312 * @param {DefaultSelectionModel} this
31313 * @param {TreeNode} node the new selection
31315 "selectionchange" : true,
31318 * @event beforeselect
31319 * Fires before the selected node changes, return false to cancel the change
31320 * @param {DefaultSelectionModel} this
31321 * @param {TreeNode} node the new selection
31322 * @param {TreeNode} node the old selection
31324 "beforeselect" : true
31328 Roo.extend(Roo.tree.DefaultSelectionModel, Roo.util.Observable, {
31329 init : function(A){
31331 A.getTreeEl().on("keydown", this.onKeyDown, this);
31332 A.on("click", this.onNodeClick, this);
31335 onNodeClick : function(B, e){
31336 if (e.ctrlKey && this.selNode == B) {
31346 * @param {TreeNode} node The node to select
31347 * @return {TreeNode} The selected node
31349 select : function(C){
31350 var D = this.selNode;
31351 if(D != C && this.fireEvent('beforeselect', this, C, D) !== false){
31353 D.ui.onSelectedChange(false);
31357 C.ui.onSelectedChange(true);
31358 this.fireEvent("selectionchange", this, C, D);
31365 * @param {TreeNode} node The node to unselect
31367 unselect : function(E){
31368 if(this.selNode == E){
31369 this.clearSelections();
31374 * Clear all selections
31376 clearSelections : function(){
31377 var n = this.selNode;
31379 n.ui.onSelectedChange(false);
31380 this.selNode = null;
31381 this.fireEvent("selectionchange", this, null);
31387 * Get the selected node
31388 * @return {TreeNode} The selected node
31390 getSelectedNode : function(){
31391 return this.selNode;
31395 * Returns true if the node is selected
31396 * @param {TreeNode} node The node to check
31397 * @return {Boolean}
31399 isSelected : function(F){
31400 return this.selNode == F;
31404 * Selects the node above the selected node in the tree, intelligently walking the nodes
31405 * @return TreeNode The new selection
31407 selectPrevious : function(){
31408 var s = this.selNode || this.lastSelNode;
31412 var ps = s.previousSibling;
31414 if(!ps.isExpanded() || ps.childNodes.length < 1){
31415 return this.select(ps);
31417 var lc = ps.lastChild;
31418 while(lc && lc.isExpanded() && lc.childNodes.length > 0){
31421 return this.select(lc);
31423 } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
31424 return this.select(s.parentNode);
31430 * Selects the node above the selected node in the tree, intelligently walking the nodes
31431 * @return TreeNode The new selection
31433 selectNext : function(){
31434 var s = this.selNode || this.lastSelNode;
31438 if(s.firstChild && s.isExpanded()){
31439 return this.select(s.firstChild);
31440 }else if(s.nextSibling){
31441 return this.select(s.nextSibling);
31442 }else if(s.parentNode){
31444 s.parentNode.bubble(function(){
31445 if(this.nextSibling){
31446 newS = this.getOwnerTree().selModel.select(this.nextSibling);
31455 onKeyDown : function(e){
31456 var s = this.selNode || this.lastSelNode;
31457 // undesirable, but required
31462 var k = e.getKey();
31470 this.selectPrevious();
31473 e.preventDefault();
31474 if(s.hasChildNodes()){
31475 if(!s.isExpanded()){
31477 }else if(s.firstChild){
31478 this.select(s.firstChild, e);
31483 e.preventDefault();
31484 if(s.hasChildNodes() && s.isExpanded()){
31486 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
31487 this.select(s.parentNode, e);
31495 * @class Roo.tree.MultiSelectionModel
31496 * @extends Roo.util.Observable
31497 * Multi selection for a TreePanel.
31499 Roo.tree.MultiSelectionModel = function(){
31500 this.selNodes = [];
31504 * @event selectionchange
31505 * Fires when the selected nodes change
31506 * @param {MultiSelectionModel} this
31507 * @param {Array} nodes Array of the selected nodes
31509 "selectionchange" : true
31513 Roo.extend(Roo.tree.MultiSelectionModel, Roo.util.Observable, {
31514 init : function(G){
31516 G.getTreeEl().on("keydown", this.onKeyDown, this);
31517 G.on("click", this.onNodeClick, this);
31520 onNodeClick : function(H, e){
31521 this.select(H, e, e.ctrlKey);
31526 * @param {TreeNode} node The node to select
31527 * @param {EventObject} e (optional) An event associated with the selection
31528 * @param {Boolean} keepExisting True to retain existing selections
31529 * @return {TreeNode} The selected node
31531 select : function(I, e, J){
31533 this.clearSelections(true);
31535 if(this.isSelected(I)){
31536 this.lastSelNode = I;
31540 this.selNodes.push(I);
31541 this.selMap[I.id] = I;
31542 this.lastSelNode = I;
31543 I.ui.onSelectedChange(true);
31544 this.fireEvent("selectionchange", this, this.selNodes);
31550 * @param {TreeNode} node The node to unselect
31552 unselect : function(K){
31553 if(this.selMap[K.id]){
31554 K.ui.onSelectedChange(false);
31555 var sn = this.selNodes;
31558 index = sn.indexOf(K);
31560 for(var i = 0, len = sn.length; i < len; i++){
31568 this.selNodes.splice(index, 1);
31570 delete this.selMap[K.id];
31571 this.fireEvent("selectionchange", this, this.selNodes);
31576 * Clear all selections
31578 clearSelections : function(L){
31579 var sn = this.selNodes;
31581 for(var i = 0, len = sn.length; i < len; i++){
31582 sn[i].ui.onSelectedChange(false);
31585 this.selNodes = [];
31588 this.fireEvent("selectionchange", this, this.selNodes);
31594 * Returns true if the node is selected
31595 * @param {TreeNode} node The node to check
31596 * @return {Boolean}
31598 isSelected : function(M){
31599 return this.selMap[M.id] ? true : false;
31603 * Returns an array of the selected nodes
31606 getSelectedNodes : function(){
31607 return this.selNodes;
31610 onKeyDown : Roo.tree.DefaultSelectionModel.prototype.onKeyDown,
31612 selectNext : Roo.tree.DefaultSelectionModel.prototype.selectNext,
31614 selectPrevious : Roo.tree.DefaultSelectionModel.prototype.selectPrevious
31618 * Ext JS Library 1.1.1
31619 * Copyright(c) 2006-2007, Ext JS, LLC.
31621 * Originally Released Under LGPL - original licence link has changed is not relivant.
31624 * <script type="text/javascript">
31628 * @class Roo.tree.TreeNode
31629 * @extends Roo.data.Node
31630 * @cfg {String} text The text for this node
31631 * @cfg {Boolean} expanded true to start the node expanded
31632 * @cfg {Boolean} allowDrag false to make this node undraggable if DD is on (defaults to true)
31633 * @cfg {Boolean} allowDrop false if this node cannot be drop on
31634 * @cfg {Boolean} disabled true to start the node disabled
31635 * @cfg {String} icon The path to an icon for the node. The preferred way to do this
31636 * is to use the cls or iconCls attributes and add the icon via a CSS background image.
31637 * @cfg {String} cls A css class to be added to the node
31638 * @cfg {String} iconCls A css class to be added to the nodes icon element for applying css background images
31639 * @cfg {String} href URL of the link used for the node (defaults to #)
31640 * @cfg {String} hrefTarget target frame for the link
31641 * @cfg {String} qtip An Ext QuickTip for the node
31642 * @cfg {String} qtipCfg An Ext QuickTip config for the node (used instead of qtip)
31643 * @cfg {Boolean} singleClickExpand True for single click expand on this node
31644 * @cfg {Function} uiProvider A UI <b>class</b> to use for this node (defaults to Roo.tree.TreeNodeUI)
31645 * @cfg {Boolean} checked True to render a checked checkbox for this node, false to render an unchecked checkbox
31646 * (defaults to undefined with no checkbox rendered)
31648 * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node
31650 Roo.tree.TreeNode = function(A){
31652 if(typeof A == "string"){
31656 this.childrenRendered = false;
31657 this.rendered = false;
31658 Roo.tree.TreeNode.superclass.constructor.call(this, A);
31659 this.expanded = A.expanded === true;
31660 this.isTarget = A.isTarget !== false;
31661 this.draggable = A.draggable !== false && A.allowDrag !== false;
31662 this.allowChildren = A.allowChildren !== false && A.allowDrop !== false;
31665 * Read-only. The text for this node. To change it use setText().
31668 this.text = A.text;
31670 * True if this node is disabled.
31673 this.disabled = A.disabled === true;
31677 * @event textchange
31678 * Fires when the text for this node is changed
31679 * @param {Node} this This node
31680 * @param {String} text The new text
31681 * @param {String} oldText The old text
31683 "textchange" : true,
31685 * @event beforeexpand
31686 * Fires before this node is expanded, return false to cancel.
31687 * @param {Node} this This node
31688 * @param {Boolean} deep
31689 * @param {Boolean} anim
31691 "beforeexpand" : true,
31693 * @event beforecollapse
31694 * Fires before this node is collapsed, return false to cancel.
31695 * @param {Node} this This node
31696 * @param {Boolean} deep
31697 * @param {Boolean} anim
31699 "beforecollapse" : true,
31702 * Fires when this node is expanded
31703 * @param {Node} this This node
31707 * @event disabledchange
31708 * Fires when the disabled status of this node changes
31709 * @param {Node} this This node
31710 * @param {Boolean} disabled
31712 "disabledchange" : true,
31715 * Fires when this node is collapsed
31716 * @param {Node} this This node
31720 * @event beforeclick
31721 * Fires before click processing. Return false to cancel the default action.
31722 * @param {Node} this This node
31723 * @param {Roo.EventObject} e The event object
31725 "beforeclick":true,
31727 * @event checkchange
31728 * Fires when a node with a checkbox's checked property changes
31729 * @param {Node} this This node
31730 * @param {Boolean} checked
31732 "checkchange":true,
31735 * Fires when this node is clicked
31736 * @param {Node} this This node
31737 * @param {Roo.EventObject} e The event object
31742 * Fires when this node is double clicked
31743 * @param {Node} this This node
31744 * @param {Roo.EventObject} e The event object
31748 * @event contextmenu
31749 * Fires when this node is right clicked
31750 * @param {Node} this This node
31751 * @param {Roo.EventObject} e The event object
31753 "contextmenu":true,
31755 * @event beforechildrenrendered
31756 * Fires right before the child nodes for this node are rendered
31757 * @param {Node} this This node
31759 "beforechildrenrendered":true
31762 var B = this.attributes.uiProvider || Roo.tree.TreeNodeUI;
31765 * Read-only. The UI for this node
31768 this.ui = new B(this);
31770 Roo.extend(Roo.tree.TreeNode, Roo.data.Node, {
31771 preventHScroll: true,
31773 * Returns true if this node is expanded
31774 * @return {Boolean}
31776 isExpanded : function(){
31777 return this.expanded;
31781 * Returns the UI object for this node
31782 * @return {TreeNodeUI}
31784 getUI : function(){
31788 // private override
31789 setFirstChild : function(C){
31790 var of = this.firstChild;
31791 Roo.tree.TreeNode.superclass.setFirstChild.call(this, C);
31792 if(this.childrenRendered && of && C != of){
31793 of.renderIndent(true, true);
31796 this.renderIndent(true, true);
31800 // private override
31801 setLastChild : function(D){
31802 var ol = this.lastChild;
31803 Roo.tree.TreeNode.superclass.setLastChild.call(this, D);
31804 if(this.childrenRendered && ol && D != ol){
31805 ol.renderIndent(true, true);
31808 this.renderIndent(true, true);
31812 // these methods are overridden to provide lazy rendering support
31813 // private override
31814 appendChild : function(){
31815 var E = Roo.tree.TreeNode.superclass.appendChild.apply(this, arguments);
31816 if(E && this.childrenRendered){
31820 this.ui.updateExpandIcon();
31824 // private override
31825 removeChild : function(F){
31826 this.ownerTree.getSelectionModel().unselect(F);
31827 Roo.tree.TreeNode.superclass.removeChild.apply(this, arguments);
31828 // if it's been rendered remove dom node
31829 if(this.childrenRendered){
31832 if(this.childNodes.length < 1){
31833 this.collapse(false, false);
31835 this.ui.updateExpandIcon();
31837 if(!this.firstChild) {
31838 this.childrenRendered = false;
31843 // private override
31844 insertBefore : function(G, H){
31845 var I = Roo.tree.TreeNode.superclass.insertBefore.apply(this, arguments);
31846 if(I && H && this.childrenRendered){
31850 this.ui.updateExpandIcon();
31855 * Sets the text for this node
31856 * @param {String} text
31858 setText : function(J){
31861 this.attributes.text = J;
31862 if(this.rendered){ // event without subscribing
31863 this.ui.onTextChange(this, J, K);
31866 this.fireEvent("textchange", this, J, K);
31870 * Triggers selection of this node
31872 select : function(){
31873 this.getOwnerTree().getSelectionModel().select(this);
31877 * Triggers deselection of this node
31879 unselect : function(){
31880 this.getOwnerTree().getSelectionModel().unselect(this);
31884 * Returns true if this node is selected
31885 * @return {Boolean}
31887 isSelected : function(){
31888 return this.getOwnerTree().getSelectionModel().isSelected(this);
31892 * Expand this node.
31893 * @param {Boolean} deep (optional) True to expand all children as well
31894 * @param {Boolean} anim (optional) false to cancel the default animation
31895 * @param {Function} callback (optional) A callback to be called when
31896 * expanding this node completes (does not wait for deep expand to complete).
31897 * Called with 1 parameter, this node.
31899 expand : function(L, M, N){
31900 if(!this.expanded){
31901 if(this.fireEvent("beforeexpand", this, L, M) === false){
31904 if(!this.childrenRendered){
31905 this.renderChildren();
31908 this.expanded = true;
31909 if(!this.isHiddenRoot() && (this.getOwnerTree().animate && M !== false) || M){
31910 this.ui.animExpand(function(){
31911 this.fireEvent("expand", this);
31912 if(typeof N == "function"){
31916 this.expandChildNodes(true);
31918 }.createDelegate(this));
31922 this.fireEvent("expand", this);
31923 if(typeof N == "function"){
31928 if(typeof N == "function"){
31933 this.expandChildNodes(true);
31937 isHiddenRoot : function(){
31938 return this.isRoot && !this.getOwnerTree().rootVisible;
31942 * Collapse this node.
31943 * @param {Boolean} deep (optional) True to collapse all children as well
31944 * @param {Boolean} anim (optional) false to cancel the default animation
31946 collapse : function(O, P){
31947 if(this.expanded && !this.isHiddenRoot()){
31948 if(this.fireEvent("beforecollapse", this, O, P) === false){
31952 this.expanded = false;
31953 if((this.getOwnerTree().animate && P !== false) || P){
31954 this.ui.animCollapse(function(){
31955 this.fireEvent("collapse", this);
31957 this.collapseChildNodes(true);
31959 }.createDelegate(this));
31962 this.ui.collapse();
31963 this.fireEvent("collapse", this);
31967 var cs = this.childNodes;
31968 for(var i = 0, len = cs.length; i < len; i++) {
31969 cs[i].collapse(true, false);
31975 delayedExpand : function(Q){
31976 if(!this.expandProcId){
31977 this.expandProcId = this.expand.defer(Q, this);
31982 cancelExpand : function(){
31983 if(this.expandProcId){
31984 clearTimeout(this.expandProcId);
31987 this.expandProcId = false;
31991 * Toggles expanded/collapsed state of the node
31993 toggle : function(){
32002 * Ensures all parent nodes are expanded
32004 ensureVisible : function(R){
32005 var S = this.getOwnerTree();
32006 S.expandPath(this.parentNode.getPath(), false, function(){
32007 S.getTreeEl().scrollChildIntoView(this.ui.anchor);
32009 }.createDelegate(this));
32013 * Expand all child nodes
32014 * @param {Boolean} deep (optional) true if the child nodes should also expand their child nodes
32016 expandChildNodes : function(T){
32017 var cs = this.childNodes;
32018 for(var i = 0, len = cs.length; i < len; i++) {
32024 * Collapse all child nodes
32025 * @param {Boolean} deep (optional) true if the child nodes should also collapse their child nodes
32027 collapseChildNodes : function(U){
32028 var cs = this.childNodes;
32029 for(var i = 0, len = cs.length; i < len; i++) {
32035 * Disables this node
32037 disable : function(){
32038 this.disabled = true;
32040 if(this.rendered && this.ui.onDisableChange){ // event without subscribing
32041 this.ui.onDisableChange(this, true);
32044 this.fireEvent("disabledchange", this, true);
32048 * Enables this node
32050 enable : function(){
32051 this.disabled = false;
32052 if(this.rendered && this.ui.onDisableChange){ // event without subscribing
32053 this.ui.onDisableChange(this, false);
32056 this.fireEvent("disabledchange", this, false);
32060 renderChildren : function(V){
32062 this.fireEvent("beforechildrenrendered", this);
32064 var cs = this.childNodes;
32065 for(var i = 0, len = cs.length; i < len; i++){
32066 cs[i].render(true);
32069 this.childrenRendered = true;
32073 sort : function(fn, W){
32074 Roo.tree.TreeNode.superclass.sort.apply(this, arguments);
32075 if(this.childrenRendered){
32076 var cs = this.childNodes;
32077 for(var i = 0, len = cs.length; i < len; i++){
32078 cs[i].render(true);
32084 render : function(X){
32086 if(!this.rendered){
32087 this.rendered = true;
32089 this.expanded = false;
32090 this.expand(false, false);
32096 renderIndent : function(Y, Z){
32098 this.ui.childIndent = null;
32101 this.ui.renderIndent();
32102 if(Y === true && this.childrenRendered){
32103 var cs = this.childNodes;
32104 for(var i = 0, len = cs.length; i < len; i++){
32105 cs[i].renderIndent(true, Z);
32112 * Ext JS Library 1.1.1
32113 * Copyright(c) 2006-2007, Ext JS, LLC.
32115 * Originally Released Under LGPL - original licence link has changed is not relivant.
32118 * <script type="text/javascript">
32122 * @class Roo.tree.AsyncTreeNode
32123 * @extends Roo.tree.TreeNode
32124 * @cfg {TreeLoader} loader A TreeLoader to be used by this node (defaults to the loader defined on the tree)
32126 * @param {Object/String} attributes The attributes/config for the node or just a string with the text for the node
32128 Roo.tree.AsyncTreeNode = function(A){
32129 this.loaded = false;
32130 this.loading = false;
32131 Roo.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
32133 * @event beforeload
32134 * Fires before this node is loaded, return false to cancel
32135 * @param {Node} this This node
32137 this.addEvents({'beforeload':true, 'load': true});
32140 * Fires when this node is loaded
32141 * @param {Node} this This node
32144 * The loader used by this node (defaults to using the tree's defined loader)
32149 Roo.extend(Roo.tree.AsyncTreeNode, Roo.tree.TreeNode, {
32150 expand : function(B, C, D){
32151 if(this.loading){ // if an async load is already running, waiting til it's done
32153 var f = function(){
32154 if(!this.loading){ // done loading
32155 clearInterval(timer);
32156 this.expand(B, C, D);
32158 }.createDelegate(this);
32159 timer = setInterval(f, 200);
32163 if(this.fireEvent("beforeload", this) === false){
32167 this.loading = true;
32168 this.ui.beforeLoad(this);
32169 var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
32171 loader.load(this, this.loadComplete.createDelegate(this, [B, C, D]));
32176 Roo.tree.AsyncTreeNode.superclass.expand.call(this, B, C, D);
32180 * Returns true if this node is currently loading
32181 * @return {Boolean}
32183 isLoading : function(){
32184 return this.loading;
32187 loadComplete : function(E, F, G){
32188 this.loading = false;
32189 this.loaded = true;
32190 this.ui.afterLoad(this);
32191 this.fireEvent("load", this);
32192 this.expand(E, F, G);
32196 * Returns true if this node has been loaded
32197 * @return {Boolean}
32199 isLoaded : function(){
32200 return this.loaded;
32203 hasChildNodes : function(){
32204 if(!this.isLeaf() && !this.loaded){
32207 return Roo.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
32212 * Trigger a reload for this node
32213 * @param {Function} callback
32215 reload : function(H){
32216 this.collapse(false, false);
32217 while(this.firstChild){
32218 this.removeChild(this.firstChild);
32221 this.childrenRendered = false;
32222 this.loaded = false;
32223 if(this.isHiddenRoot()){
32224 this.expanded = false;
32227 this.expand(false, false, H);
32232 * Ext JS Library 1.1.1
32233 * Copyright(c) 2006-2007, Ext JS, LLC.
32235 * Originally Released Under LGPL - original licence link has changed is not relivant.
32238 * <script type="text/javascript">
32242 * @class Roo.tree.TreeNodeUI
32244 * @param {Object} node The node to render
32245 * The TreeNode UI implementation is separate from the
32246 * tree implementation. Unless you are customizing the tree UI,
32247 * you should never have to use this directly.
32249 Roo.tree.TreeNodeUI = function(A){
32251 this.rendered = false;
32252 this.animating = false;
32253 this.emptyIcon = Roo.BLANK_IMAGE_URL;
32256 Roo.tree.TreeNodeUI.prototype = {
32257 removeChild : function(B){
32259 this.ctNode.removeChild(B.ui.getEl());
32263 beforeLoad : function(){
32264 this.addClass("x-tree-node-loading");
32267 afterLoad : function(){
32268 this.removeClass("x-tree-node-loading");
32271 onTextChange : function(C, D, E){
32273 this.textNode.innerHTML = D;
32277 onDisableChange : function(F, G){
32280 this.addClass("x-tree-node-disabled");
32282 this.removeClass("x-tree-node-disabled");
32286 onSelectedChange : function(H){
32289 this.addClass("x-tree-selected");
32292 this.removeClass("x-tree-selected");
32296 onMove : function(I, J, K, L, M, N){
32297 this.childIndent = null;
32299 var targetNode = L.ui.getContainer();
32300 if(!targetNode){//target not rendered
32301 this.holder = document.createElement("div");
32302 this.holder.appendChild(this.wrap);
32305 var insertBefore = N ? N.ui.getEl() : null;
32307 targetNode.insertBefore(this.wrap, insertBefore);
32309 targetNode.appendChild(this.wrap);
32312 this.node.renderIndent(true);
32316 addClass : function(O){
32318 Roo.fly(this.elNode).addClass(O);
32322 removeClass : function(P){
32324 Roo.fly(this.elNode).removeClass(P);
32328 remove : function(){
32330 this.holder = document.createElement("div");
32331 this.holder.appendChild(this.wrap);
32335 fireEvent : function(){
32336 return this.node.fireEvent.apply(this.node, arguments);
32339 initEvents : function(){
32340 this.node.on("move", this.onMove, this);
32341 var E = Roo.EventManager;
32342 var a = this.anchor;
32344 var el = Roo.fly(a, '_treeui');
32346 if(Roo.isOpera){ // opera render bug ignores the CSS
32347 el.setStyle("text-decoration", "none");
32351 el.on("click", this.onClick, this);
32352 el.on("dblclick", this.onDblClick, this);
32355 Roo.EventManager.on(this.checkbox,
32356 Roo.isIE ? 'click' : 'change', this.onCheckChange, this);
32360 el.on("contextmenu", this.onContextMenu, this);
32362 var Q = Roo.fly(this.iconNode);
32363 Q.on("click", this.onClick, this);
32364 Q.on("dblclick", this.onDblClick, this);
32365 Q.on("contextmenu", this.onContextMenu, this);
32366 E.on(this.ecNode, "click", this.ecClick, this, true);
32368 if(this.node.disabled){
32369 this.addClass("x-tree-node-disabled");
32371 if(this.node.hidden){
32372 this.addClass("x-tree-node-disabled");
32374 var ot = this.node.getOwnerTree();
32375 var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
32376 if(dd && (!this.node.isRoot || ot.rootVisible)){
32377 Roo.dd.Registry.register(this.elNode, {
32379 handles: this.getDDHandles(),
32385 getDDHandles : function(){
32386 return [this.iconNode, this.textNode];
32391 this.wrap.style.display = "none";
32397 this.wrap.style.display = "";
32401 onContextMenu : function(e){
32402 if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
32403 e.preventDefault();
32405 this.fireEvent("contextmenu", this.node, e);
32409 onClick : function(e){
32414 if(this.fireEvent("beforeclick", this.node, e) !== false){
32415 if(!this.disabled && this.node.attributes.href){
32416 this.fireEvent("click", this.node, e);
32420 e.preventDefault();
32425 if(this.node.attributes.singleClickExpand && !this.animating && this.node.hasChildNodes()){
32426 this.node.toggle();
32430 this.fireEvent("click", this.node, e);
32436 onDblClick : function(e){
32437 e.preventDefault();
32442 this.toggleCheck();
32444 if(!this.animating && this.node.hasChildNodes()){
32445 this.node.toggle();
32448 this.fireEvent("dblclick", this.node, e);
32451 onCheckChange : function(){
32452 var R = this.checkbox.checked;
32453 this.node.attributes.checked = R;
32454 this.fireEvent('checkchange', this.node, R);
32457 ecClick : function(e){
32458 if(!this.animating && this.node.hasChildNodes()){
32459 this.node.toggle();
32463 startDrop : function(){
32464 this.dropping = true;
32467 // delayed drop so the click event doesn't get fired on a drop
32468 endDrop : function(){
32469 setTimeout(function(){
32470 this.dropping = false;
32471 }.createDelegate(this), 50);
32474 expand : function(){
32475 this.updateExpandIcon();
32476 this.ctNode.style.display = "";
32479 focus : function(){
32480 if(!this.node.preventHScroll){
32481 try{this.anchor.focus();
32483 }else if(!Roo.isIE){
32485 var noscroll = this.node.getOwnerTree().getTreeEl().dom;
32486 var l = noscroll.scrollLeft;
32487 this.anchor.focus();
32488 noscroll.scrollLeft = l;
32493 toggleCheck : function(S){
32494 var cb = this.checkbox;
32496 cb.checked = (S === undefined ? !cb.checked : S);
32502 this.anchor.blur();
32506 animExpand : function(T){
32507 var ct = Roo.get(this.ctNode);
32509 if(!this.node.hasChildNodes()){
32510 this.updateExpandIcon();
32511 this.ctNode.style.display = "";
32516 this.animating = true;
32517 this.updateExpandIcon();
32520 callback : function(){
32521 this.animating = false;
32525 duration: this.node.ownerTree.duration || .25
32529 highlight : function(){
32530 var U = this.node.getOwnerTree();
32531 Roo.fly(this.wrap).highlight(
32532 U.hlColor || "C3DAF9",
32533 {endColor: U.hlBaseColor}
32537 collapse : function(){
32538 this.updateExpandIcon();
32539 this.ctNode.style.display = "none";
32542 animCollapse : function(V){
32543 var ct = Roo.get(this.ctNode);
32544 ct.enableDisplayMode('block');
32547 this.animating = true;
32548 this.updateExpandIcon();
32551 callback : function(){
32552 this.animating = false;
32556 duration: this.node.ownerTree.duration || .25
32560 getContainer : function(){
32561 return this.ctNode;
32564 getEl : function(){
32568 appendDDGhost : function(W){
32569 W.appendChild(this.elNode.cloneNode(true));
32572 getDDRepairXY : function(){
32573 return Roo.lib.Dom.getXY(this.iconNode);
32576 onRender : function(){
32580 render : function(X){
32581 var n = this.node, a = n.attributes;
32582 var Y = n.parentNode ?
32583 n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
32585 if(!this.rendered){
32586 this.rendered = true;
32588 this.renderElements(n, a, Y, X);
32591 if(this.textNode.setAttributeNS){
32592 this.textNode.setAttributeNS("ext", "qtip", a.qtip);
32594 this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
32597 this.textNode.setAttribute("ext:qtip", a.qtip);
32599 this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
32602 }else if(a.qtipCfg){
32603 a.qtipCfg.target = Roo.id(this.textNode);
32604 Roo.QuickTips.register(a.qtipCfg);
32608 if(!this.node.expanded){
32609 this.updateExpandIcon();
32613 Y.appendChild(this.wrap);
32618 renderElements : function(n, a, Z, b){
32619 // add some indent caching, this helps performance when rendering a large tree
32620 this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
32621 var t = n.getOwnerTree();
32622 var c = t.renderer ? t.renderer(n.attributes) : Roo.util.Format.htmlEncode(n.text);
32623 var d = t.rendererTip ? t.rendererTip(n.attributes) : c;
32624 var cb = typeof a.checked == 'boolean';
32625 var f = a.href ? a.href : Roo.isGecko ? "" : "#";
32626 var g = ['<li class="x-tree-node"><div class="x-tree-node-el ', a.cls,'">',
32627 '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
32628 '<img src="', this.emptyIcon, '" class="x-tree-ec-icon" />',
32629 '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
32630 cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : ' />')) : '',
32631 '<a hidefocus="on" href="',f,'" tabIndex="1" ',
32632 a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "",
32633 '><span unselectable="on" qtip="' , d ,'">',c,"</span></a></div>",
32634 '<ul class="x-tree-node-ct" style="display:none;"></ul>',
32637 if(b !== true && n.nextSibling && n.nextSibling.ui.getEl()){
32638 this.wrap = Roo.DomHelper.insertHtml("beforeBegin",
32639 n.nextSibling.ui.getEl(), g.join(""));
32641 this.wrap = Roo.DomHelper.insertHtml("beforeEnd", Z, g.join(""));
32645 this.elNode = this.wrap.childNodes[0];
32646 this.ctNode = this.wrap.childNodes[1];
32647 var cs = this.elNode.childNodes;
32648 this.indentNode = cs[0];
32649 this.ecNode = cs[1];
32650 this.iconNode = cs[2];
32653 this.checkbox = cs[3];
32657 this.anchor = cs[h];
32658 this.textNode = cs[h].firstChild;
32661 getAnchor : function(){
32662 return this.anchor;
32665 getTextEl : function(){
32666 return this.textNode;
32669 getIconEl : function(){
32670 return this.iconNode;
32673 isChecked : function(){
32674 return this.checkbox ? this.checkbox.checked : false;
32677 updateExpandIcon : function(){
32679 var n = this.node, c1, c2;
32680 var P = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow";
32681 var hasChild = n.hasChildNodes();
32685 c1 = "x-tree-node-collapsed";
32686 c2 = "x-tree-node-expanded";
32689 c1 = "x-tree-node-expanded";
32690 c2 = "x-tree-node-collapsed";
32693 this.removeClass("x-tree-node-leaf");
32694 this.wasLeaf = false;
32696 if(this.c1 != c1 || this.c2 != c2){
32697 Roo.fly(this.elNode).replaceClass(c1, c2);
32698 this.c1 = c1; this.c2 = c2;
32702 Roo.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-leaf");
32705 this.wasLeaf = true;
32708 var ecc = "x-tree-ec-icon "+P;
32709 if(this.ecc != ecc){
32710 this.ecNode.className = ecc;
32716 getChildIndent : function(){
32717 if(!this.childIndent){
32721 if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
32723 g.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
32725 g.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
32732 this.childIndent = g.join("");
32734 return this.childIndent;
32737 renderIndent : function(){
32740 var p = this.node.parentNode;
32742 indent = p.ui.getChildIndent();
32744 if(this.indentMarkup != indent){ // don't rerender if not required
32745 this.indentNode.innerHTML = indent;
32746 this.indentMarkup = indent;
32749 this.updateExpandIcon();
32754 Roo.tree.RootTreeNodeUI = function(){
32755 Roo.tree.RootTreeNodeUI.superclass.constructor.apply(this, arguments);
32757 Roo.extend(Roo.tree.RootTreeNodeUI, Roo.tree.TreeNodeUI, {
32758 render : function(){
32759 if(!this.rendered){
32760 var Z = this.node.ownerTree.innerCt.dom;
32761 this.node.expanded = true;
32762 Z.innerHTML = '<div class="x-tree-root-node"></div>';
32763 this.wrap = this.ctNode = Z.firstChild;
32766 collapse : function(){
32768 expand : function(){
32773 * Ext JS Library 1.1.1
32774 * Copyright(c) 2006-2007, Ext JS, LLC.
32776 * Originally Released Under LGPL - original licence link has changed is not relivant.
32779 * <script type="text/javascript">
32782 * @class Roo.tree.TreeLoader
32783 * @extends Roo.util.Observable
32784 * A TreeLoader provides for lazy loading of an {@link Roo.tree.TreeNode}'s child
32785 * nodes from a specified URL. The response must be a javascript Array definition
32786 * who's elements are node definition objects. eg:
32788 [{ 'id': 1, 'text': 'A folder Node', 'leaf': false },
32789 { 'id': 2, 'text': 'A leaf Node', 'leaf': true }]
32792 * A server request is sent, and child nodes are loaded only when a node is expanded.
32793 * The loading node's id is passed to the server under the parameter name "node" to
32794 * enable the server to produce the correct child nodes.
32796 * To pass extra parameters, an event handler may be attached to the "beforeload"
32797 * event, and the parameters specified in the TreeLoader's baseParams property:
32799 myTreeLoader.on("beforeload", function(treeLoader, node) {
32800 this.baseParams.category = node.attributes.category;
32803 * This would pass an HTTP parameter called "category" to the server containing
32804 * the value of the Node's "category" attribute.
32806 * Creates a new Treeloader.
32807 * @param {Object} config A config object containing config properties.
32809 Roo.tree.TreeLoader = function(A){
32810 this.baseParams = {};
32811 this.requestMethod = "POST";
32812 Roo.apply(this, A);
32816 * @event beforeload
32817 * Fires before a network request is made to retrieve the Json text which specifies a node's children.
32818 * @param {Object} This TreeLoader object.
32819 * @param {Object} node The {@link Roo.tree.TreeNode} object being loaded.
32820 * @param {Object} callback The callback function specified in the {@link #load} call.
32822 "beforeload" : true,
32825 * Fires when the node has been successfuly loaded.
32826 * @param {Object} This TreeLoader object.
32827 * @param {Object} node The {@link Roo.tree.TreeNode} object being loaded.
32828 * @param {Object} response The response object containing the data from the server.
32832 * @event loadexception
32833 * Fires if the network request failed.
32834 * @param {Object} This TreeLoader object.
32835 * @param {Object} node The {@link Roo.tree.TreeNode} object being loaded.
32836 * @param {Object} response The response object containing the data from the server.
32838 "loadexception" : true,
32841 * Fires before a node is created, enabling you to return custom Node types
32842 * @param {Object} This TreeLoader object.
32843 * @param {Object} attr - the data returned from the AJAX call (modify it to suit)
32848 Roo.tree.TreeLoader.superclass.constructor.call(this);
32851 Roo.extend(Roo.tree.TreeLoader, Roo.util.Observable, {
32853 * @cfg {String} dataUrl The URL from which to request a Json string which
32854 * specifies an array of node definition object representing the child nodes
32858 * @cfg {Object} baseParams (optional) An object containing properties which
32859 * specify HTTP parameters to be passed to each request for child nodes.
32862 * @cfg {Object} baseAttrs (optional) An object containing attributes to be added to all nodes
32863 * created by this loader. If the attributes sent by the server have an attribute in this object,
32864 * they take priority.
32867 * @cfg {Object} uiProviders (optional) An object containing properties which
32869 * DEPRECIATED - use 'create' event handler to modify attributes - which affect creation.
32870 * specify custom {@link Roo.tree.TreeNodeUI} implementations. If the optional
32871 * <i>uiProvider</i> attribute of a returned child node is a string rather
32872 * than a reference to a TreeNodeUI implementation, this that string value
32873 * is used as a property name in the uiProviders object. You can define the provider named
32874 * 'default' , and this will be used for all nodes (if no uiProvider is delivered by the node data)
32879 * @cfg {Boolean} clearOnLoad (optional) Default to true. Remove previously existing
32880 * child nodes before loading.
32882 clearOnLoad : true,
32885 * @cfg {String} root (optional) Default to false. Use this to read data from an object
32886 * property on loading, rather than expecting an array. (eg. more compatible to a standard
32887 * Grid query { data : [ .....] }
32892 * @cfg {String} queryParam (optional)
32893 * Name of the query as it will be passed on the querystring (defaults to 'node')
32894 * eg. the request will be ?node=[id]
32901 * Load an {@link Roo.tree.TreeNode} from the URL specified in the constructor.
32902 * This is called automatically when a node is expanded, but may be used to reload
32903 * a node (or append new children if the {@link #clearOnLoad} option is false.)
32904 * @param {Roo.tree.TreeNode} node
32905 * @param {Function} callback
32907 load : function(B, C){
32908 if(this.clearOnLoad){
32909 while(B.firstChild){
32910 B.removeChild(B.firstChild);
32913 if(B.attributes.children){ // preloaded json children
32914 var cs = B.attributes.children;
32915 for(var i = 0, len = cs.length; i < len; i++){
32916 B.appendChild(this.createNode(cs[i]));
32918 if(typeof C == "function"){
32921 }else if(this.dataUrl){
32922 this.requestData(B, C);
32926 getParams: function(D){
32927 var E = [], bp = this.baseParams;
32928 for(var key in bp){
32929 if(typeof bp[key] != "function"){
32930 E.push(encodeURIComponent(key), "=", encodeURIComponent(bp[key]), "&");
32933 var n = this.queryParam === false ? 'node' : this.queryParam;
32934 E.push(n + "=", encodeURIComponent(D.id));
32938 requestData : function(F, G){
32939 if(this.fireEvent("beforeload", this, F, G) !== false){
32940 this.transId = Roo.Ajax.request({
32941 method:this.requestMethod,
32942 url: this.dataUrl||this.url,
32943 success: this.handleResponse,
32944 failure: this.handleFailure,
32946 argument: {callback: G, node: F},
32947 params: this.getParams(F)
32950 // if the load is cancelled, make sure we notify
32951 // the node that we are done
32952 if(typeof G == "function"){
32958 isLoading : function(){
32959 return this.transId ? true : false;
32962 abort : function(){
32963 if(this.isLoading()){
32964 Roo.Ajax.abort(this.transId);
32969 * Override this function for custom TreeNode node implementation
32971 createNode : function(H){
32972 // apply baseAttrs, nice idea Corey!
32973 if(this.baseAttrs){
32974 Roo.applyIf(H, this.baseAttrs);
32976 if(this.applyLoader !== false){
32979 // uiProvider = depreciated..
32981 if(typeof(H.uiProvider) == 'string'){
32982 H.uiProvider = this.uiProviders[H.uiProvider] ||
32983 /** eval:var:attr */ eval(H.uiProvider);
32985 if(typeof(this.uiProviders['default']) != 'undefined') {
32986 H.uiProvider = this.uiProviders['default'];
32990 this.fireEvent('create', this, H);
32992 H.leaf = typeof(H.leaf) == 'string' ? H.leaf * 1 : H.leaf;
32994 new Roo.tree.TreeNode(H) :
32995 new Roo.tree.AsyncTreeNode(H));
32998 processResponse : function(I, J, K){
32999 var L = I.responseText;
33002 var o = /** eval:var:zzzzzzzzzz */ eval("("+L+")");
33003 if (this.root !== false) {
33007 for(var i = 0, len = o.length; i < len; i++){
33008 var n = this.createNode(o[i]);
33013 if(typeof K == "function"){
33017 this.handleFailure(response);
33021 handleResponse : function(M){
33022 this.transId = false;
33023 var a = M.argument;
33024 this.processResponse(M, a.node, a.callback);
33025 this.fireEvent("load", this, a.node, M);
33028 handleFailure : function(N){
33029 this.transId = false;
33030 var a = N.argument;
33031 this.fireEvent("loadexception", this, a.node, N);
33032 if(typeof a.callback == "function"){
33033 a.callback(this, a.node);
33039 * Ext JS Library 1.1.1
33040 * Copyright(c) 2006-2007, Ext JS, LLC.
33042 * Originally Released Under LGPL - original licence link has changed is not relivant.
33045 * <script type="text/javascript">
33049 * @class Roo.tree.TreeFilter
33050 * Note this class is experimental and doesn't update the indent (lines) or expand collapse icons of the nodes
33051 * @param {TreePanel} tree
33052 * @param {Object} config (optional)
33054 Roo.tree.TreeFilter = function(A, B){
33056 this.filtered = {};
33057 Roo.apply(this, B);
33060 Roo.tree.TreeFilter.prototype = {
33067 * Filter the data by a specific attribute.
33068 * @param {String/RegExp} value Either string that the attribute value
33069 * should start with or a RegExp to test against the attribute
33070 * @param {String} attr (optional) The attribute passed in your node's attributes collection. Defaults to "text".
33071 * @param {TreeNode} startNode (optional) The node to start the filter at.
33073 filter : function(C, D, E){
33076 if(typeof C == "string"){
33077 var vlen = C.length;
33078 // auto clear empty filter
33079 if(vlen == 0 && this.clearBlank){
33084 C = C.toLowerCase();
33086 return n.attributes[D].substr(0, vlen).toLowerCase() == C;
33088 }else if(C.exec){ // regex?
33090 return C.test(n.attributes[D]);
33093 throw 'Illegal filter type, must be string or regex';
33096 this.filterBy(f, null, E);
33100 * Filter by a function. The passed function will be called with each
33101 * node in the tree (or from the startNode). If the function returns true, the node is kept
33102 * otherwise it is filtered. If a node is filtered, its children are also filtered.
33103 * @param {Function} fn The filter function
33104 * @param {Object} scope (optional) The scope of the function (defaults to the current node)
33106 filterBy : function(fn, F, G){
33107 G = G || this.tree.root;
33108 if(this.autoClear){
33111 var af = this.filtered, rv = this.reverse;
33112 var f = function(n){
33119 var m = fn.call(F || n, n);
33130 if(typeof id != "function"){
33132 if(n && n.parentNode){
33133 n.parentNode.removeChild(n);
33141 * Clears the current filter. Note: with the "remove" option
33142 * set a filter cannot be cleared.
33144 clear : function(){
33146 var af = this.filtered;
33148 if(typeof id != "function"){
33156 this.filtered = {};
33162 * Ext JS Library 1.1.1
33163 * Copyright(c) 2006-2007, Ext JS, LLC.
33165 * Originally Released Under LGPL - original licence link has changed is not relivant.
33168 * <script type="text/javascript">
33173 * @class Roo.tree.TreeSorter
33174 * Provides sorting of nodes in a TreePanel
33176 * @cfg {Boolean} folderSort True to sort leaf nodes under non leaf nodes
33177 * @cfg {String} property The named attribute on the node to sort by (defaults to text)
33178 * @cfg {String} dir The direction to sort (asc or desc) (defaults to asc)
33179 * @cfg {String} leafAttr The attribute used to determine leaf nodes in folder sort (defaults to "leaf")
33180 * @cfg {Boolean} caseSensitive true for case sensitive sort (defaults to false)
33181 * @cfg {Function} sortType A custom "casting" function used to convert node values before sorting
33183 * @param {TreePanel} tree
33184 * @param {Object} config
33186 Roo.tree.TreeSorter = function(A, B){
33187 Roo.apply(this, B);
33188 A.on("beforechildrenrendered", this.doSort, this);
33189 A.on("append", this.updateSort, this);
33190 A.on("insert", this.updateSort, this);
33192 var C = this.dir && this.dir.toLowerCase() == "desc";
33193 var p = this.property || "text";
33194 var D = this.sortType;
33195 var fs = this.folderSort;
33196 var cs = this.caseSensitive === true;
33197 var E = this.leafAttr || 'leaf';
33199 this.sortFn = function(n1, n2){
33201 if(n1.attributes[E] && !n2.attributes[E]){
33204 if(!n1.attributes[E] && n2.attributes[E]){
33208 var v1 = D ? D(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
33209 var v2 = D ? D(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
33211 return C ? +1 : -1;
33213 return C ? -1 : +1;
33220 Roo.tree.TreeSorter.prototype = {
33221 doSort : function(F){
33222 F.sort(this.sortFn);
33225 compareNodes : function(n1, n2){
33226 return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
33229 updateSort : function(G, H){
33230 if(H.childrenRendered){
33231 this.doSort.defer(1, this, [H]);
33237 * Ext JS Library 1.1.1
33238 * Copyright(c) 2006-2007, Ext JS, LLC.
33240 * Originally Released Under LGPL - original licence link has changed is not relivant.
33243 * <script type="text/javascript">
33246 if(Roo.dd.DropZone){
33248 Roo.tree.TreeDropZone = function(A, B){
33249 this.allowParentInsert = false;
33250 this.allowContainerDrop = false;
33251 this.appendOnly = false;
33252 Roo.tree.TreeDropZone.superclass.constructor.call(this, A.innerCt, B);
33254 this.lastInsertClass = "x-tree-no-status";
33255 this.dragOverData = {};
33258 Roo.extend(Roo.tree.TreeDropZone, Roo.dd.DropZone, {
33259 ddGroup : "TreeDD",
33261 expandDelay : 1000,
33263 expandNode : function(C){
33264 if(C.hasChildNodes() && !C.isExpanded()){
33265 C.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
33269 queueExpand : function(D){
33270 this.expandProcId = this.expandNode.defer(this.expandDelay, this, [D]);
33273 cancelExpand : function(){
33274 if(this.expandProcId){
33275 clearTimeout(this.expandProcId);
33276 this.expandProcId = false;
33280 isValidDropPoint : function(n, pt, dd, e, E){
33281 if(!n || !E){ return false; }
33284 // default drop rules
33285 if(!(F && F.isTarget && pt)){
33288 if(pt == "append" && F.allowChildren === false){
33291 if((pt == "above" || pt == "below") && (F.parentNode && F.parentNode.allowChildren === false)){
33294 if(G && (F == G || G.contains(F))){
33297 // reuse the object
33298 var H = this.dragOverData;
33299 H.tree = this.tree;
33307 var I = this.tree.fireEvent("nodedragover", H);
33308 return H.cancel === false && I !== false;
33311 getDropPoint : function(e, n, dd){
33314 return tn.allowChildren !== false ? "append" : false; // always append for root
33317 var t = Roo.lib.Dom.getY(J), b = t + J.offsetHeight;
33318 var y = Roo.lib.Event.getPageY(e);
33319 var K = tn.allowChildren === false || tn.isLeaf();
33320 if(this.appendOnly || tn.parentNode.allowChildren === false){
33321 return K ? false : "append";
33324 if(!this.allowParentInsert){
33325 L = tn.hasChildNodes() && tn.isExpanded();
33327 var q = (b - t) / (K ? 2 : 3);
33328 if(y >= t && y < (t + q)){
33330 }else if(!L && (K || y >= b-q && y <= b)){
33337 onNodeEnter : function(n, dd, e, M){
33338 this.cancelExpand();
33341 onNodeOver : function(n, dd, e, N){
33342 var pt = this.getDropPoint(e, n, dd);
33345 // auto node expand check
33346 if(!this.expandProcId && pt == "append" && O.hasChildNodes() && !n.node.isExpanded()){
33347 this.queueExpand(O);
33348 }else if(pt != "append"){
33349 this.cancelExpand();
33352 // set the insert point style on the target node
33353 var P = this.dropNotAllowed;
33354 if(this.isValidDropPoint(n, pt, dd, e, N)){
33359 P = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
33360 cls = "x-tree-drag-insert-above";
33361 }else if(pt == "below"){
33362 P = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
33363 cls = "x-tree-drag-insert-below";
33365 P = "x-tree-drop-ok-append";
33366 cls = "x-tree-drag-append";
33368 if(this.lastInsertClass != cls){
33369 Roo.fly(el).replaceClass(this.lastInsertClass, cls);
33370 this.lastInsertClass = cls;
33377 onNodeOut : function(n, dd, e, Q){
33378 this.cancelExpand();
33379 this.removeDropIndicators(n);
33382 onNodeDrop : function(n, dd, e, R){
33383 var S = this.getDropPoint(e, n, dd);
33386 if(!this.isValidDropPoint(n, S, dd, e, R)){
33390 // first try to find the drop node
33391 var U = R.node || (dd.getTreeNode ? dd.getTreeNode(R, T, S, e) : null);
33402 var W = this.tree.fireEvent("beforenodedrop", V);
33403 if(W === false || V.cancel === true || !V.dropNode){
33408 // allow target changing
33410 if(S == "append" && !T.isExpanded()){
33411 T.expand(false, null, function(){
33412 this.completeDrop(V);
33413 }.createDelegate(this));
33415 this.completeDrop(V);
33420 completeDrop : function(de){
33421 var ns = de.dropNode, p = de.point, t = de.target;
33422 if(!(ns instanceof Array)){
33426 for(var i = 0, len = ns.length; i < len; i++){
33429 t.parentNode.insertBefore(n, t);
33430 }else if(p == "below"){
33431 t.parentNode.insertBefore(n, t.nextSibling);
33438 if(this.tree.hlDrop){
33443 this.tree.fireEvent("nodedrop", de);
33446 afterNodeMoved : function(dd, X, e, Y, Z){
33447 if(this.tree.hlDrop){
33452 this.tree.fireEvent("nodedrop", this.tree, Y, X, dd, e);
33455 getTree : function(){
33459 removeDropIndicators : function(n){
33462 Roo.fly(el).removeClass([
33463 "x-tree-drag-insert-above",
33464 "x-tree-drag-insert-below",
33465 "x-tree-drag-append"]);
33466 this.lastInsertClass = "_noclass";
33470 beforeDragDrop : function(a, e, id){
33471 this.cancelExpand();
33475 afterRepair : function(c){
33476 if(c && Roo.enableFx){
33477 c.node.ui.highlight();
33487 * Ext JS Library 1.1.1
33488 * Copyright(c) 2006-2007, Ext JS, LLC.
33490 * Originally Released Under LGPL - original licence link has changed is not relivant.
33493 * <script type="text/javascript">
33497 if(Roo.dd.DragZone){
33498 Roo.tree.TreeDragZone = function(A, B){
33499 Roo.tree.TreeDragZone.superclass.constructor.call(this, A.getTreeEl(), B);
33503 Roo.extend(Roo.tree.TreeDragZone, Roo.dd.DragZone, {
33504 ddGroup : "TreeDD",
33506 onBeforeDrag : function(C, e){
33508 return n && n.draggable && !n.disabled;
33511 onInitDrag : function(e){
33512 var D = this.dragData;
33513 this.tree.getSelectionModel().select(D.node);
33514 this.proxy.update("");
33515 D.node.ui.appendDDGhost(this.proxy.ghost.dom);
33516 this.tree.fireEvent("startdrag", this.tree, D.node, e);
33519 getRepairXY : function(e, E){
33520 return E.node.ui.getDDRepairXY();
33523 onEndDrag : function(F, e){
33524 this.tree.fireEvent("enddrag", this.tree, F.node, e);
33527 onValidDrop : function(dd, e, id){
33528 this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
33532 beforeInvalidDrop : function(e, id){
33533 // this scrolls the original position back into view
33534 var sm = this.tree.getSelectionModel();
33535 sm.clearSelections();
33536 sm.select(this.dragData.node);
33542 * Ext JS Library 1.1.1
33543 * Copyright(c) 2006-2007, Ext JS, LLC.
33545 * Originally Released Under LGPL - original licence link has changed is not relivant.
33548 * <script type="text/javascript">
33551 * @class Roo.tree.TreeEditor
33552 * @extends Roo.Editor
33553 * Provides editor functionality for inline tree node editing. Any valid {@link Roo.form.Field} can be used
33554 * as the editor field.
33556 * @param {TreePanel} tree
33557 * @param {Object} config Either a prebuilt {@link Roo.form.Field} instance or a Field config object
33559 Roo.tree.TreeEditor = function(A, B){
33561 var C = B.events ? B : new Roo.form.TextField(B);
33562 Roo.tree.TreeEditor.superclass.constructor.call(this, C);
33566 A.on('beforeclick', this.beforeNodeClick, this);
33567 A.getTreeEl().on('mousedown', this.hide, this);
33568 this.on('complete', this.updateNode, this);
33569 this.on('beforestartedit', this.fitToTree, this);
33570 this.on('startedit', this.bindScroll, this, {delay:10});
33571 this.on('specialkey', this.onSpecialKey, this);
33574 Roo.extend(Roo.tree.TreeEditor, Roo.Editor, {
33576 * @cfg {String} alignment
33577 * The position to align to (see {@link Roo.Element#alignTo} for more details, defaults to "l-l").
33583 * @cfg {Boolean} hideEl
33584 * True to hide the bound element while the editor is displayed (defaults to false)
33588 * @cfg {String} cls
33589 * CSS class to apply to the editor (defaults to "x-small-editor x-tree-editor")
33591 cls: "x-small-editor x-tree-editor",
33593 * @cfg {Boolean} shim
33594 * True to shim the editor if selects/iframes could be displayed beneath it (defaults to false)
33600 * @cfg {Number} maxWidth
33601 * The maximum width in pixels of the editor field (defaults to 250). Note that if the maxWidth would exceed
33602 * the containing tree element's size, it will be automatically limited for you to the container width, taking
33603 * scroll and client offsets into account prior to each edit.
33610 fitToTree : function(ed, el){
33611 var td = this.tree.getTreeEl().dom, nd = el.dom;
33612 if(td.scrollLeft > nd.offsetLeft){ // ensure the node left point is visible
33613 td.scrollLeft = nd.offsetLeft;
33617 (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - /*cushion*/5);
33618 this.setSize(w, '');
33622 triggerEdit : function(D){
33623 this.completeEdit();
33625 this.startEdit(D.ui.textNode, D.text);
33629 bindScroll : function(){
33630 this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
33634 beforeNodeClick : function(E, e){
33635 var F = (this.lastClick ? this.lastClick.getElapsed() : 0);
33636 this.lastClick = new Date();
33637 if(F > this.editDelay && this.tree.getSelectionModel().isSelected(E)){
33639 this.triggerEdit(E);
33645 updateNode : function(ed, G){
33646 this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
33647 this.editNode.setText(G);
33651 onHide : function(){
33652 Roo.tree.TreeEditor.superclass.onHide.call(this);
33654 this.editNode.ui.focus();
33659 onSpecialKey : function(H, e){
33660 var k = e.getKey();
33664 }else if(k == e.ENTER && !e.hasModifier()){
33666 this.completeEdit();
33670 //<Script type="text/javascript">
33673 * Ext JS Library 1.1.1
33674 * Copyright(c) 2006-2007, Ext JS, LLC.
33676 * Originally Released Under LGPL - original licence link has changed is not relivant.
33679 * <script type="text/javascript">
33683 * Not documented??? - probably should be...
33686 Roo.tree.ColumnNodeUI = Roo.extend(Roo.tree.TreeNodeUI, {
33687 //focus: Roo.emptyFn, // prevent odd scrolling behavior
33689 renderElements : function(n, a, A, B){
33690 //consel.log("renderElements?");
33691 this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
33693 var t = n.getOwnerTree();
33694 var C = Pman.Tab.Document_TypesTree.tree.el.id;
33697 var bw = t.borderWidth;
33699 var E = a.href ? a.href : Roo.isGecko ? "" : "#";
33700 var cb = typeof a.checked == "boolean";
33701 var tx = String.format('{0}',n.text || (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]));
33702 var F = 'x-t-' + C + '-c0';
33704 '<li class="x-tree-node">',
33707 '<div class="x-tree-node-el ', a.cls,'">',
33709 '<div class="x-tree-col ', F, '" style="width:', c.width-bw, 'px;">',
33712 '<span class="x-tree-node-indent">',this.indentMarkup,'</span>',
33713 '<img src="', this.emptyIcon, '" class="x-tree-ec-icon " />',
33714 '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',
33715 (a.icon ? ' x-tree-node-inline-icon' : ''),
33716 (a.iconCls ? ' '+a.iconCls : ''),
33717 '" unselectable="on" />',
33718 (cb ? ('<input class="x-tree-node-cb" type="checkbox" ' +
33719 (a.checked ? 'checked="checked" />' : ' />')) : ''),
33721 '<a class="x-tree-node-anchor" hidefocus="on" href="',E,'" tabIndex="1" ',
33722 (a.hrefTarget ? ' target="' +a.hrefTarget + '"' : ''), '>',
33723 '<span unselectable="on" qtip="' + tx + '">',
33727 '<a class="x-tree-node-anchor" hidefocus="on" href="',E,'" tabIndex="1" ',
33728 (a.hrefTarget ? ' target="' +a.hrefTarget + '"' : ''), '>',
33731 for(var i = 1, len = D.length; i < len; i++){
33733 F = 'x-t-' + C + '-c' +i;
33734 tx = String.format('{0}', (c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]));
33735 G.push('<div class="x-tree-col ', F, ' ' ,(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
33736 '<div class="x-tree-col-text" qtip="' + tx +'">',tx,"</div>",
33743 '<div class="x-clear"></div></div>',
33744 '<ul class="x-tree-node-ct" style="display:none;"></ul>',
33747 if(B !== true && n.nextSibling && n.nextSibling.ui.getEl()){
33748 this.wrap = Roo.DomHelper.insertHtml("beforeBegin",
33749 n.nextSibling.ui.getEl(), G.join(""));
33751 this.wrap = Roo.DomHelper.insertHtml("beforeEnd", A, G.join(""));
33753 var el = this.wrap.firstChild;
33755 this.elNode = el.firstChild;
33756 this.ranchor = el.childNodes[1];
33757 this.ctNode = this.wrap.childNodes[1];
33758 var cs = el.firstChild.childNodes;
33759 this.indentNode = cs[0];
33760 this.ecNode = cs[1];
33761 this.iconNode = cs[2];
33764 this.checkbox = cs[3];
33768 this.anchor = cs[H];
33770 this.textNode = cs[H].firstChild;
33772 //el.on("click", this.onClick, this);
33773 //el.on("dblclick", this.onDblClick, this);
33776 // console.log(this);
33778 initEvents : function(){
33779 Roo.tree.ColumnNodeUI.superclass.initEvents.call(this);
33782 var a = this.ranchor;
33784 var el = Roo.get(a);
33786 if(Roo.isOpera){ // opera render bug ignores the CSS
33787 el.setStyle("text-decoration", "none");
33791 el.on("click", this.onClick, this);
33792 el.on("dblclick", this.onDblClick, this);
33793 el.on("contextmenu", this.onContextMenu, this);
33797 /*onSelectedChange : function(state){
33800 this.addClass("x-tree-selected");
33803 this.removeClass("x-tree-selected");
33806 addClass : function(I){
33808 Roo.fly(this.elRow).addClass(I);
33814 removeClass : function(J){
33816 Roo.fly(this.elRow).removeClass(J);
33823 //<Script type="text/javascript">
33827 * Ext JS Library 1.1.1
33828 * Copyright(c) 2006-2007, Ext JS, LLC.
33830 * Originally Released Under LGPL - original licence link has changed is not relivant.
33833 * <script type="text/javascript">
33838 * @class Roo.tree.ColumnTree
33839 * @extends Roo.data.TreePanel
33840 * @cfg {Object} columns Including width, header, renderer, cls, dataIndex
33841 * @cfg {int} borderWidth compined right/left border allowance
33843 * @param {String/HTMLElement/Element} el The container element
33844 * @param {Object} config
33846 Roo.tree.ColumnTree = function(el, A)
33848 Roo.tree.ColumnTree.superclass.constructor.call(this, el , A);
33852 * Fire this event on a container when it resizes
33853 * @param {int} w Width
33854 * @param {int} h Height
33858 this.on('resize', this.onResize, this);
33861 Roo.extend(Roo.tree.ColumnTree, Roo.tree.TreePanel, {
33865 borderWidth: Roo.isBorderBox ? 0 : 2,
33868 render : function(){
33869 // add the header.....
33871 Roo.tree.ColumnTree.superclass.render.apply(this);
33873 this.el.addClass('x-column-tree');
33875 this.headers = this.el.createChild(
33876 {cls:'x-tree-headers'},this.innerCt.dom);
33878 var B = this.columns, c;
33882 for(var i = 0; i < D; i++){
33885 this.headEls.push(this.headers.createChild({
33886 cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
33888 cls:'x-tree-hd-text',
33891 style:'width:'+(c.width-this.borderWidth)+'px;'
33895 this.headers.createChild({cls:'x-clear'});
33896 // prevent floats from wrapping when clipped
33897 this.headers.setWidth(C);
33898 //this.innerCt.setWidth(totalWidth);
33899 this.innerCt.setStyle({ overflow: 'auto' });
33900 this.onResize(this.width, this.height);
33904 onResize : function(w,h)
33909 this.innerCt.setWidth(this.width);
33910 this.innerCt.setHeight(this.height-20);
33913 var E = this.columns, c;
33917 for(var i = 0; i < H; i++){
33919 if (this.autoExpandColumn !== false && c.dataIndex == this.autoExpandColumn) {
33920 // it's the expander..
33921 G = this.headEls[i];
33929 G.setWidth( ((w - F)-this.borderWidth - 20));
33932 this.headers.setWidth(w-20);
33942 * Ext JS Library 1.1.1
33943 * Copyright(c) 2006-2007, Ext JS, LLC.
33945 * Originally Released Under LGPL - original licence link has changed is not relivant.
33948 * <script type="text/javascript">
33952 * @class Roo.menu.Menu
33953 * @extends Roo.util.Observable
33954 * A menu object. This is the container to which you add all other menu items. Menu can also serve a as a base class
33955 * when you want a specialzed menu based off of another component (like {@link Roo.menu.DateMenu} for example).
33957 * Creates a new Menu
33958 * @param {Object} config Configuration options
33960 Roo.menu.Menu = function(A){
33961 Roo.apply(this, A);
33962 this.id = this.id || Roo.id();
33965 * @event beforeshow
33966 * Fires before this menu is displayed
33967 * @param {Roo.menu.Menu} this
33971 * @event beforehide
33972 * Fires before this menu is hidden
33973 * @param {Roo.menu.Menu} this
33978 * Fires after this menu is displayed
33979 * @param {Roo.menu.Menu} this
33984 * Fires after this menu is hidden
33985 * @param {Roo.menu.Menu} this
33990 * Fires when this menu is clicked (or when the enter key is pressed while it is active)
33991 * @param {Roo.menu.Menu} this
33992 * @param {Roo.menu.Item} menuItem The menu item that was clicked
33993 * @param {Roo.EventObject} e
33998 * Fires when the mouse is hovering over this menu
33999 * @param {Roo.menu.Menu} this
34000 * @param {Roo.EventObject} e
34001 * @param {Roo.menu.Item} menuItem The menu item that was clicked
34006 * Fires when the mouse exits this menu
34007 * @param {Roo.menu.Menu} this
34008 * @param {Roo.EventObject} e
34009 * @param {Roo.menu.Item} menuItem The menu item that was clicked
34014 * Fires when a menu item contained in this menu is clicked
34015 * @param {Roo.menu.BaseItem} baseItem The BaseItem that was clicked
34016 * @param {Roo.EventObject} e
34020 if (this.registerMenu) {
34021 Roo.menu.MenuMgr.register(this);
34024 var B = this.items;
34025 this.items = new Roo.util.MixedCollection();
34027 this.add.apply(this, B);
34031 Roo.extend(Roo.menu.Menu, Roo.util.Observable, {
34033 * @cfg {Number} minWidth The minimum width of the menu in pixels (defaults to 120)
34037 * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop"
34038 * for bottom-right shadow (defaults to "sides")
34042 * @cfg {String} subMenuAlign The {@link Roo.Element#alignTo} anchor position value to use for submenus of
34043 * this menu (defaults to "tl-tr?")
34045 subMenuAlign : "tl-tr?",
34047 * @cfg {String} defaultAlign The default {@link Roo.Element#alignTo) anchor position value for this menu
34048 * relative to its element of origin (defaults to "tl-bl?")
34050 defaultAlign : "tl-bl?",
34052 * @cfg {Boolean} allowOtherMenus True to allow multiple menus to be displayed at the same time (defaults to false)
34054 allowOtherMenus : false,
34056 * @cfg {Boolean} registerMenu True (default) - means that clicking on screen etc. hides it.
34058 registerMenu : true,
34063 render : function(){
34067 var el = this.el = new Roo.Layer({
34069 shadow:this.shadow,
34071 parentEl: this.parentEl || document.body,
34075 this.keyNav = new Roo.menu.MenuNav(this);
34078 el.addClass("x-menu-plain");
34081 el.addClass(this.cls);
34084 // generic focus element
34085 this.focusEl = el.createChild({
34086 tag: "a", cls: "x-menu-focus", href: "#", onclick: "return false;", tabIndex:"-1"
34088 var ul = el.createChild({tag: "ul", cls: "x-menu-list"});
34089 ul.on("click", this.onClick, this);
34090 ul.on("mouseover", this.onMouseOver, this);
34091 ul.on("mouseout", this.onMouseOut, this);
34092 this.items.each(function(C){
34093 var li = document.createElement("li");
34094 li.className = "x-menu-list-item";
34095 ul.dom.appendChild(li);
34096 C.render(li, this);
34103 autoWidth : function(){
34104 var el = this.el, ul = this.ul;
34108 var w = this.width;
34111 }else if(Roo.isIE){
34112 el.setWidth(this.minWidth);
34113 var t = el.dom.offsetWidth; // force recalc
34114 el.setWidth(ul.getWidth()+el.getFrameWidth("lr"));
34119 delayAutoWidth : function(){
34122 this.awTask = new Roo.util.DelayedTask(this.autoWidth, this);
34125 this.awTask.delay(20);
34130 findTargetItem : function(e){
34131 var t = e.getTarget(".x-menu-list-item", this.ul, true);
34132 if(t && t.menuItemId){
34133 return this.items.get(t.menuItemId);
34138 onClick : function(e){
34140 if(t = this.findTargetItem(e)){
34142 this.fireEvent("click", this, t, e);
34147 setActiveItem : function(C, D){
34148 if(C != this.activeItem){
34149 if(this.activeItem){
34150 this.activeItem.deactivate();
34153 this.activeItem = C;
34161 tryActivate : function(E, F){
34162 var G = this.items;
34163 for(var i = E, len = G.length; i >= 0 && i < len; i+= F){
34165 if(!C.disabled && C.canActivate){
34166 this.setActiveItem(C, false);
34174 onMouseOver : function(e){
34176 if(t = this.findTargetItem(e)){
34177 if(t.canActivate && !t.disabled){
34178 this.setActiveItem(t, true);
34182 this.fireEvent("mouseover", this, e, t);
34186 onMouseOut : function(e){
34188 if(t = this.findTargetItem(e)){
34189 if(t == this.activeItem && t.shouldDeactivate(e)){
34190 this.activeItem.deactivate();
34191 delete this.activeItem;
34195 this.fireEvent("mouseout", this, e, t);
34199 * Read-only. Returns true if the menu is currently displayed, else false.
34202 isVisible : function(){
34203 return this.el && !this.hidden;
34207 * Displays this menu relative to another element
34208 * @param {String/HTMLElement/Roo.Element} element The element to align to
34209 * @param {String} position (optional) The {@link Roo.Element#alignTo} anchor position to use in aligning to
34210 * the element (defaults to this.defaultAlign)
34211 * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
34213 show : function(el, H, I){
34214 this.parentMenu = I;
34219 this.fireEvent("beforeshow", this);
34220 this.showAt(this.el.getAlignToXY(el, H || this.defaultAlign), I, false);
34224 * Displays this menu at a specific xy position
34225 * @param {Array} xyPosition Contains X & Y [x, y] values for the position at which to show the menu (coordinates are page-based)
34226 * @param {Roo.menu.Menu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
34228 showAt : function(xy, J, /* private: */_e){
34229 this.parentMenu = J;
34234 this.fireEvent("beforeshow", this);
34235 xy = this.el.adjustForConstraints(xy);
34240 this.hidden = false;
34242 this.fireEvent("show", this);
34245 focus : function(){
34247 this.doFocus.defer(50, this);
34251 doFocus : function(){
34253 this.focusEl.focus();
34258 * Hides this menu and optionally all parent menus
34259 * @param {Boolean} deep (optional) True to hide all parent menus recursively, if any (defaults to false)
34261 hide : function(K){
34262 if(this.el && this.isVisible()){
34263 this.fireEvent("beforehide", this);
34264 if(this.activeItem){
34265 this.activeItem.deactivate();
34266 this.activeItem = null;
34270 this.hidden = true;
34271 this.fireEvent("hide", this);
34273 if(K === true && this.parentMenu){
34274 this.parentMenu.hide(true);
34279 * Addds one or more items of any type supported by the Menu class, or that can be converted into menu items.
34280 * Any of the following are valid:
34282 * <li>Any menu item object based on {@link Roo.menu.Item}</li>
34283 * <li>An HTMLElement object which will be converted to a menu item</li>
34284 * <li>A menu item config object that will be created as a new menu item</li>
34285 * <li>A string, which can either be '-' or 'separator' to add a menu separator, otherwise
34286 * it will be converted into a {@link Roo.menu.TextItem} and added</li>
34291 var menu = new Roo.menu.Menu();
34293 // Create a menu item to add by reference
34294 var menuItem = new Roo.menu.Item({ text: 'New Item!' });
34296 // Add a bunch of items at once using different methods.
34297 // Only the last item added will be returned.
34298 var item = menu.add(
34299 menuItem, // add existing item by ref
34300 'Dynamic Item', // new TextItem
34301 '-', // new separator
34302 { text: 'Config Item' } // new item by config
34305 * @param {Mixed} args One or more menu items, menu item configs or other objects that can be converted to menu items
34306 * @return {Roo.menu.Item} The menu item that was added, or the last one if multiple items were added
34309 var a = arguments, l = a.length, L;
34310 for(var i = 0; i < l; i++){
34312 if(el.render){ // some kind of Item
34313 L = this.addItem(el);
34314 }else if(typeof el == "string"){ // string
34315 if(el == "separator" || el == "-"){
34316 L = this.addSeparator();
34318 L = this.addText(el);
34320 }else if(el.tagName || el.el){ // element
34321 L = this.addElement(el);
34322 }else if(typeof el == "object"){ // must be menu item config?
34323 L = this.addMenuItem(el);
34330 * Returns this menu's underlying {@link Roo.Element} object
34331 * @return {Roo.Element} The element
34333 getEl : function(){
34341 * Adds a separator bar to the menu
34342 * @return {Roo.menu.Item} The menu item that was added
34344 addSeparator : function(){
34345 return this.addItem(new Roo.menu.Separator());
34349 * Adds an {@link Roo.Element} object to the menu
34350 * @param {String/HTMLElement/Roo.Element} el The element or DOM node to add, or its id
34351 * @return {Roo.menu.Item} The menu item that was added
34353 addElement : function(el){
34354 return this.addItem(new Roo.menu.BaseItem(el));
34358 * Adds an existing object based on {@link Roo.menu.Item} to the menu
34359 * @param {Roo.menu.Item} item The menu item to add
34360 * @return {Roo.menu.Item} The menu item that was added
34362 addItem : function(M){
34365 var li = document.createElement("li");
34366 li.className = "x-menu-list-item";
34367 this.ul.dom.appendChild(li);
34368 M.render(li, this);
34369 this.delayAutoWidth();
34375 * Creates a new {@link Roo.menu.Item} based an the supplied config object and adds it to the menu
34376 * @param {Object} config A MenuItem config object
34377 * @return {Roo.menu.Item} The menu item that was added
34379 addMenuItem : function(N){
34380 if(!(N instanceof Roo.menu.Item)){
34381 if(typeof N.checked == "boolean"){ // must be check menu item config?
34382 N = new Roo.menu.CheckItem(N);
34384 N = new Roo.menu.Item(N);
34387 return this.addItem(N);
34391 * Creates a new {@link Roo.menu.TextItem} with the supplied text and adds it to the menu
34392 * @param {String} text The text to display in the menu item
34393 * @return {Roo.menu.Item} The menu item that was added
34395 addText : function(O){
34396 return this.addItem(new Roo.menu.TextItem(O));
34400 * Inserts an existing object based on {@link Roo.menu.Item} to the menu at a specified index
34401 * @param {Number} index The index in the menu's list of current items where the new item should be inserted
34402 * @param {Roo.menu.Item} item The menu item to add
34403 * @return {Roo.menu.Item} The menu item that was added
34405 insert : function(P, Q){
34406 this.items.insert(P, Q);
34408 var li = document.createElement("li");
34409 li.className = "x-menu-list-item";
34410 this.ul.dom.insertBefore(li, this.ul.dom.childNodes[P]);
34411 Q.render(li, this);
34412 this.delayAutoWidth();
34418 * Removes an {@link Roo.menu.Item} from the menu and destroys the object
34419 * @param {Roo.menu.Item} item The menu item to remove
34421 remove : function(R){
34422 this.items.removeKey(R.id);
34427 * Removes and destroys all items in the menu
34429 removeAll : function(){
34431 while(f = this.items.first()){
34437 // MenuNav is a private utility class used internally by the Menu
34438 Roo.menu.MenuNav = function(S){
34439 Roo.menu.MenuNav.superclass.constructor.call(this, S.el);
34440 this.scope = this.menu = S;
34443 Roo.extend(Roo.menu.MenuNav, Roo.KeyNav, {
34444 doRelay : function(e, h){
34445 var k = e.getKey();
34446 if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN ){
34447 this.menu.tryActivate(0, 1);
34450 return h.call(this.scope || this, e, this.menu);
34453 up : function(e, m){
34454 if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
34455 m.tryActivate(m.items.length-1, -1);
34459 down : function(e, m){
34460 if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
34461 m.tryActivate(0, 1);
34465 right : function(e, m){
34467 m.activeItem.expandMenu(true);
34471 left : function(e, m){
34473 if(m.parentMenu && m.parentMenu.activeItem){
34474 m.parentMenu.activeItem.activate();
34478 enter : function(e, m){
34480 e.stopPropagation();
34481 m.activeItem.onClick(e);
34482 m.fireEvent("click", this, m.activeItem);
34489 * Ext JS Library 1.1.1
34490 * Copyright(c) 2006-2007, Ext JS, LLC.
34492 * Originally Released Under LGPL - original licence link has changed is not relivant.
34495 * <script type="text/javascript">
34499 * @class Roo.menu.MenuMgr
34500 * Provides a common registry of all menu items on a page so that they can be easily accessed by id.
34503 Roo.menu.MenuMgr = function(){
34504 var A, B, C = {}, attached = false, lastShow = new Date();
34506 // private - called when first menu is created
34509 B = new Roo.util.MixedCollection();
34510 Roo.get(document).addKeyListener(27, function(){
34519 if(B && B.length > 0){
34521 c.each(function(m){
34531 Roo.get(document).un("mousedown", J);
34539 lastShow = new Date();
34542 Roo.get(document).on("mousedown", J);
34546 m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
34547 m.parentMenu.activeChild = m;
34548 }else if(L && L.isVisible()){
34549 m.getEl().setZIndex(parseInt(L.getEl().getStyle("z-index"), 10) + 3);
34556 m.activeChild.hide();
34558 if(m.autoHideTimer){
34559 clearTimeout(m.autoHideTimer);
34560 delete m.autoHideTimer;
34566 var pm = m.parentMenu;
34567 if(!pm && !m.allowOtherMenus){
34569 }else if(pm && pm.activeChild && B != m){
34570 pm.activeChild.hide();
34576 if(lastShow.getElapsed() > 50 && B.length > 0 && !e.getTarget(".x-menu")){
34584 var g = C[mi.group];
34585 for(var i = 0, l = g.length; i < l; i++){
34587 g[i].setChecked(false);
34596 * Hides all menus that are currently visible
34598 hideAll : function(){
34603 register : function(Q){
34609 Q.on("beforehide", H);
34611 Q.on("beforeshow", I);
34614 if(g && Q.events["checkchange"]){
34620 Q.on("checkchange", onCheck);
34625 * Returns a {@link Roo.menu.Menu} object
34626 * @param {String/Object} menu The string menu id, an existing menu object reference, or a Menu config that will
34627 * be used to generate and return a new Menu instance.
34630 if(typeof R == "string"){ // menu id
34632 }else if(R.events){ // menu instance
34634 }else if(typeof R.length == 'number'){ // array of menu items?
34635 return new Roo.menu.Menu({items:R});
34636 }else { // otherwise, must be a config
34637 return new Roo.menu.Menu(R);
34642 unregister : function(S){
34644 S.un("beforehide", H);
34646 S.un("beforeshow", I);
34649 if(g && S.events["checkchange"]){
34651 S.un("checkchange", onCheck);
34656 registerCheckable : function(T){
34664 T.on("beforecheckchange", K);
34669 unregisterCheckable : function(U){
34673 U.un("beforecheckchange", K);
34680 * Ext JS Library 1.1.1
34681 * Copyright(c) 2006-2007, Ext JS, LLC.
34683 * Originally Released Under LGPL - original licence link has changed is not relivant.
34686 * <script type="text/javascript">
34691 * @class Roo.menu.BaseItem
34692 * @extends Roo.Component
34693 * The base class for all items that render into menus. BaseItem provides default rendering, activated state
34694 * management and base configuration options shared by all menu components.
34696 * Creates a new BaseItem
34697 * @param {Object} config Configuration options
34699 Roo.menu.BaseItem = function(A){
34700 Roo.menu.BaseItem.superclass.constructor.call(this, A);
34705 * Fires when this item is clicked
34706 * @param {Roo.menu.BaseItem} this
34707 * @param {Roo.EventObject} e
34712 * Fires when this item is activated
34713 * @param {Roo.menu.BaseItem} this
34717 * @event deactivate
34718 * Fires when this item is deactivated
34719 * @param {Roo.menu.BaseItem} this
34725 this.on("click", this.handler, this.scope, true);
34729 Roo.extend(Roo.menu.BaseItem, Roo.Component, {
34731 * @cfg {Function} handler
34732 * A function that will handle the click event of this menu item (defaults to undefined)
34735 * @cfg {Boolean} canActivate True if this item can be visually activated (defaults to false)
34737 canActivate : false,
34739 * @cfg {String} activeClass The CSS class to use when the item becomes activated (defaults to "x-menu-item-active")
34741 activeClass : "x-menu-item-active",
34743 * @cfg {Boolean} hideOnClick True to hide the containing menu after this item is clicked (defaults to true)
34745 hideOnClick : true,
34747 * @cfg {Number} hideDelay Length of time in milliseconds to wait before hiding after a click (defaults to 100)
34752 ctype: "Roo.menu.BaseItem",
34755 actionMode : "container",
34758 render : function(B, C){
34759 this.parentMenu = C;
34760 Roo.menu.BaseItem.superclass.render.call(this, B);
34761 this.container.menuItemId = this.id;
34765 onRender : function(D, E){
34766 this.el = Roo.get(this.el);
34767 D.dom.appendChild(this.el.dom);
34771 onClick : function(e){
34772 if(!this.disabled && this.fireEvent("click", this, e) !== false
34773 && this.parentMenu.fireEvent("itemclick", this, e) !== false){
34774 this.handleClick(e);
34781 activate : function(){
34785 var li = this.container;
34786 li.addClass(this.activeClass);
34787 this.region = li.getRegion().adjust(2, 2, -2, -2);
34788 this.fireEvent("activate", this);
34793 deactivate : function(){
34794 this.container.removeClass(this.activeClass);
34795 this.fireEvent("deactivate", this);
34799 shouldDeactivate : function(e){
34800 return !this.region || !this.region.contains(e.getPoint());
34804 handleClick : function(e){
34805 if(this.hideOnClick){
34806 this.parentMenu.hide.defer(this.hideDelay, this.parentMenu, [true]);
34811 expandMenu : function(F){
34816 hideMenu : function(){
34822 * Ext JS Library 1.1.1
34823 * Copyright(c) 2006-2007, Ext JS, LLC.
34825 * Originally Released Under LGPL - original licence link has changed is not relivant.
34828 * <script type="text/javascript">
34832 * @class Roo.menu.Adapter
34833 * @extends Roo.menu.BaseItem
34834 * A base utility class that adapts a non-menu component so that it can be wrapped by a menu item and added to a menu.
34835 * It provides basic rendering, activation management and enable/disable logic required to work in menus.
34837 * Creates a new Adapter
34838 * @param {Object} config Configuration options
34840 Roo.menu.Adapter = function(A, B){
34841 Roo.menu.Adapter.superclass.constructor.call(this, B);
34842 this.component = A;
34844 Roo.extend(Roo.menu.Adapter, Roo.menu.BaseItem, {
34846 canActivate : true,
34849 onRender : function(C, D){
34850 this.component.render(C);
34851 this.el = this.component.getEl();
34855 activate : function(){
34860 this.component.focus();
34861 this.fireEvent("activate", this);
34866 deactivate : function(){
34867 this.fireEvent("deactivate", this);
34871 disable : function(){
34872 this.component.disable();
34873 Roo.menu.Adapter.superclass.disable.call(this);
34877 enable : function(){
34878 this.component.enable();
34879 Roo.menu.Adapter.superclass.enable.call(this);
34884 * Ext JS Library 1.1.1
34885 * Copyright(c) 2006-2007, Ext JS, LLC.
34887 * Originally Released Under LGPL - original licence link has changed is not relivant.
34890 * <script type="text/javascript">
34894 * @class Roo.menu.TextItem
34895 * @extends Roo.menu.BaseItem
34896 * Adds a static text string to a menu, usually used as either a heading or group separator.
34898 * Creates a new TextItem
34899 * @param {String} text The text to display
34901 Roo.menu.TextItem = function(A){
34903 Roo.menu.TextItem.superclass.constructor.call(this);
34906 Roo.extend(Roo.menu.TextItem, Roo.menu.BaseItem, {
34908 * @cfg {Boolean} hideOnClick True to hide the containing menu after this item is clicked (defaults to false)
34910 hideOnClick : false,
34912 * @cfg {String} itemCls The default CSS class to use for text items (defaults to "x-menu-text")
34914 itemCls : "x-menu-text",
34917 onRender : function(){
34918 var s = document.createElement("span");
34919 s.className = this.itemCls;
34920 s.innerHTML = this.text;
34922 Roo.menu.TextItem.superclass.onRender.apply(this, arguments);
34927 * Ext JS Library 1.1.1
34928 * Copyright(c) 2006-2007, Ext JS, LLC.
34930 * Originally Released Under LGPL - original licence link has changed is not relivant.
34933 * <script type="text/javascript">
34937 * @class Roo.menu.Separator
34938 * @extends Roo.menu.BaseItem
34939 * Adds a separator bar to a menu, used to divide logical groups of menu items. Generally you will
34940 * add one of these by using "-" in you call to add() or in your items config rather than creating one directly.
34942 * @param {Object} config Configuration options
34944 Roo.menu.Separator = function(A){
34945 Roo.menu.Separator.superclass.constructor.call(this, A);
34948 Roo.extend(Roo.menu.Separator, Roo.menu.BaseItem, {
34950 * @cfg {String} itemCls The default CSS class to use for separators (defaults to "x-menu-sep")
34952 itemCls : "x-menu-sep",
34954 * @cfg {Boolean} hideOnClick True to hide the containing menu after this item is clicked (defaults to false)
34956 hideOnClick : false,
34959 onRender : function(li){
34960 var s = document.createElement("span");
34961 s.className = this.itemCls;
34962 s.innerHTML = " ";
34964 li.addClass("x-menu-sep-li");
34965 Roo.menu.Separator.superclass.onRender.apply(this, arguments);
34970 * Ext JS Library 1.1.1
34971 * Copyright(c) 2006-2007, Ext JS, LLC.
34973 * Originally Released Under LGPL - original licence link has changed is not relivant.
34976 * <script type="text/javascript">
34979 * @class Roo.menu.Item
34980 * @extends Roo.menu.BaseItem
34981 * A base class for all menu items that require menu-related functionality (like sub-menus) and are not static
34982 * display items. Item extends the base functionality of {@link Roo.menu.BaseItem} by adding menu-specific
34983 * activation and click handling.
34985 * Creates a new Item
34986 * @param {Object} config Configuration options
34988 Roo.menu.Item = function(A){
34989 Roo.menu.Item.superclass.constructor.call(this, A);
34991 this.menu = Roo.menu.MenuMgr.get(this.menu);
34994 Roo.extend(Roo.menu.Item, Roo.menu.BaseItem, {
34996 * @cfg {String} icon
34997 * The path to an icon to display in this menu item (defaults to Roo.BLANK_IMAGE_URL)
35000 * @cfg {String} itemCls The default CSS class to use for menu items (defaults to "x-menu-item")
35002 itemCls : "x-menu-item",
35004 * @cfg {Boolean} canActivate True if this item can be visually activated (defaults to true)
35006 canActivate : true,
35008 * @cfg {Number} showDelay Length of time in milliseconds to wait before showing this item (defaults to 200)
35011 // doc'd in BaseItem
35015 ctype: "Roo.menu.Item",
35018 onRender : function(B, C){
35019 var el = document.createElement("a");
35020 el.hideFocus = true;
35021 el.unselectable = "on";
35022 el.href = this.href || "#";
35023 if(this.hrefTarget){
35024 el.target = this.hrefTarget;
35027 el.className = this.itemCls + (this.menu ? " x-menu-item-arrow" : "") + (this.cls ? " " + this.cls : "");
35028 el.innerHTML = String.format(
35029 '<img src="{0}" class="x-menu-item-icon {2}" />{1}',
35030 this.icon || Roo.BLANK_IMAGE_URL, this.text, this.iconCls || '');
35032 Roo.menu.Item.superclass.onRender.call(this, B, C);
35036 * Sets the text to display in this menu item
35037 * @param {String} text The text to display
35039 setText : function(D){
35042 this.el.update(String.format(
35043 '<img src="{0}" class="x-menu-item-icon {2}">{1}',
35044 this.icon || Roo.BLANK_IMAGE_URL, this.text, this.iconCls || ''));
35045 this.parentMenu.autoWidth();
35050 handleClick : function(e){
35051 if(!this.href){ // if no link defined, stop the event automatically
35055 Roo.menu.Item.superclass.handleClick.apply(this, arguments);
35059 activate : function(E){
35060 if(Roo.menu.Item.superclass.activate.apply(this, arguments)){
35070 shouldDeactivate : function(e){
35071 if(Roo.menu.Item.superclass.shouldDeactivate.call(this, e)){
35072 if(this.menu && this.menu.isVisible()){
35073 return !this.menu.getEl().getRegion().contains(e.getPoint());
35081 deactivate : function(){
35082 Roo.menu.Item.superclass.deactivate.apply(this, arguments);
35087 expandMenu : function(F){
35088 if(!this.disabled && this.menu){
35089 clearTimeout(this.hideTimer);
35090 delete this.hideTimer;
35091 if(!this.menu.isVisible() && !this.showTimer){
35092 this.showTimer = this.deferExpand.defer(this.showDelay, this, [F]);
35093 }else if (this.menu.isVisible() && F){
35094 this.menu.tryActivate(0, 1);
35100 deferExpand : function(G){
35101 delete this.showTimer;
35102 this.menu.show(this.container, this.parentMenu.subMenuAlign || "tl-tr?", this.parentMenu);
35104 this.menu.tryActivate(0, 1);
35109 hideMenu : function(){
35110 clearTimeout(this.showTimer);
35111 delete this.showTimer;
35112 if(!this.hideTimer && this.menu && this.menu.isVisible()){
35113 this.hideTimer = this.deferHide.defer(this.hideDelay, this);
35118 deferHide : function(){
35119 delete this.hideTimer;
35125 * Ext JS Library 1.1.1
35126 * Copyright(c) 2006-2007, Ext JS, LLC.
35128 * Originally Released Under LGPL - original licence link has changed is not relivant.
35131 * <script type="text/javascript">
35135 * @class Roo.menu.CheckItem
35136 * @extends Roo.menu.Item
35137 * Adds a menu item that contains a checkbox by default, but can also be part of a radio group.
35139 * Creates a new CheckItem
35140 * @param {Object} config Configuration options
35142 Roo.menu.CheckItem = function(A){
35143 Roo.menu.CheckItem.superclass.constructor.call(this, A);
35146 * @event beforecheckchange
35147 * Fires before the checked value is set, providing an opportunity to cancel if needed
35148 * @param {Roo.menu.CheckItem} this
35149 * @param {Boolean} checked The new checked value that will be set
35151 "beforecheckchange" : true,
35153 * @event checkchange
35154 * Fires after the checked value has been set
35155 * @param {Roo.menu.CheckItem} this
35156 * @param {Boolean} checked The checked value that was set
35158 "checkchange" : true
35160 if(this.checkHandler){
35161 this.on('checkchange', this.checkHandler, this.scope);
35164 Roo.extend(Roo.menu.CheckItem, Roo.menu.Item, {
35166 * @cfg {String} group
35167 * All check items with the same group name will automatically be grouped into a single-select
35168 * radio button group (defaults to '')
35171 * @cfg {String} itemCls The default CSS class to use for check items (defaults to "x-menu-item x-menu-check-item")
35173 itemCls : "x-menu-item x-menu-check-item",
35175 * @cfg {String} groupClass The default CSS class to use for radio group check items (defaults to "x-menu-group-item")
35177 groupClass : "x-menu-group-item",
35180 * @cfg {Boolean} checked True to initialize this checkbox as checked (defaults to false). Note that
35181 * if this checkbox is part of a radio group (group = true) only the last item in the group that is
35182 * initialized with checked = true will be rendered as checked.
35187 ctype: "Roo.menu.CheckItem",
35190 onRender : function(c){
35191 Roo.menu.CheckItem.superclass.onRender.apply(this, arguments);
35193 this.el.addClass(this.groupClass);
35196 Roo.menu.MenuMgr.registerCheckable(this);
35198 this.checked = false;
35199 this.setChecked(true, true);
35204 destroy : function(){
35206 Roo.menu.MenuMgr.unregisterCheckable(this);
35209 Roo.menu.CheckItem.superclass.destroy.apply(this, arguments);
35213 * Set the checked state of this item
35214 * @param {Boolean} checked The new checked value
35215 * @param {Boolean} suppressEvent (optional) True to prevent the checkchange event from firing (defaults to false)
35217 setChecked : function(B, C){
35218 if(this.checked != B && this.fireEvent("beforecheckchange", this, B) !== false){
35219 if(this.container){
35220 this.container[B ? "addClass" : "removeClass"]("x-menu-item-checked");
35225 this.fireEvent("checkchange", this, B);
35231 handleClick : function(e){
35232 if(!this.disabled && !(this.checked && this.group)){// disable unselect on radio item
35233 this.setChecked(!this.checked);
35236 Roo.menu.CheckItem.superclass.handleClick.apply(this, arguments);
35241 * Ext JS Library 1.1.1
35242 * Copyright(c) 2006-2007, Ext JS, LLC.
35244 * Originally Released Under LGPL - original licence link has changed is not relivant.
35247 * <script type="text/javascript">
35251 * @class Roo.menu.DateItem
35252 * @extends Roo.menu.Adapter
35253 * A menu item that wraps the {@link Roo.DatPicker} component.
35255 * Creates a new DateItem
35256 * @param {Object} config Configuration options
35258 Roo.menu.DateItem = function(A){
35259 Roo.menu.DateItem.superclass.constructor.call(this, new Roo.DatePicker(A), A);
35260 /** The Roo.DatePicker object @type Roo.DatePicker */
35261 this.picker = this.component;
35262 this.addEvents({select: true});
35264 this.picker.on("render", function(B){
35265 B.getEl().swallowEvent("click");
35266 B.container.addClass("x-menu-date-item");
35269 this.picker.on("select", this.onSelect, this);
35272 Roo.extend(Roo.menu.DateItem, Roo.menu.Adapter, {
35274 onSelect : function(B, C){
35275 this.fireEvent("select", this, C, B);
35276 Roo.menu.DateItem.superclass.handleClick.call(this);
35281 * Ext JS Library 1.1.1
35282 * Copyright(c) 2006-2007, Ext JS, LLC.
35284 * Originally Released Under LGPL - original licence link has changed is not relivant.
35287 * <script type="text/javascript">
35291 * @class Roo.menu.ColorItem
35292 * @extends Roo.menu.Adapter
35293 * A menu item that wraps the {@link Roo.ColorPalette} component.
35295 * Creates a new ColorItem
35296 * @param {Object} config Configuration options
35298 Roo.menu.ColorItem = function(A){
35299 Roo.menu.ColorItem.superclass.constructor.call(this, new Roo.ColorPalette(A), A);
35300 /** The Roo.ColorPalette object @type Roo.ColorPalette */
35301 this.palette = this.component;
35302 this.relayEvents(this.palette, ["select"]);
35303 if(this.selectHandler){
35304 this.on('select', this.selectHandler, this.scope);
35307 Roo.extend(Roo.menu.ColorItem, Roo.menu.Adapter);
35310 * Ext JS Library 1.1.1
35311 * Copyright(c) 2006-2007, Ext JS, LLC.
35313 * Originally Released Under LGPL - original licence link has changed is not relivant.
35316 * <script type="text/javascript">
35321 * @class Roo.menu.DateMenu
35322 * @extends Roo.menu.Menu
35323 * A menu containing a {@link Roo.menu.DateItem} component (which provides a date picker).
35325 * Creates a new DateMenu
35326 * @param {Object} config Configuration options
35328 Roo.menu.DateMenu = function(A){
35329 Roo.menu.DateMenu.superclass.constructor.call(this, A);
35331 var di = new Roo.menu.DateItem(A);
35334 * The {@link Roo.DatePicker} instance for this DateMenu
35337 this.picker = di.picker;
35340 * @param {DatePicker} picker
35341 * @param {Date} date
35343 this.relayEvents(di, ["select"]);
35345 this.on('beforeshow', function(){
35347 this.picker.hideMonthPicker(true);
35351 Roo.extend(Roo.menu.DateMenu, Roo.menu.Menu, {
35356 * Ext JS Library 1.1.1
35357 * Copyright(c) 2006-2007, Ext JS, LLC.
35359 * Originally Released Under LGPL - original licence link has changed is not relivant.
35362 * <script type="text/javascript">
35367 * @class Roo.menu.ColorMenu
35368 * @extends Roo.menu.Menu
35369 * A menu containing a {@link Roo.menu.ColorItem} component (which provides a basic color picker).
35371 * Creates a new ColorMenu
35372 * @param {Object} config Configuration options
35374 Roo.menu.ColorMenu = function(A){
35375 Roo.menu.ColorMenu.superclass.constructor.call(this, A);
35377 var ci = new Roo.menu.ColorItem(A);
35380 * The {@link Roo.ColorPalette} instance for this ColorMenu
35381 * @type ColorPalette
35383 this.palette = ci.palette;
35386 * @param {ColorPalette} palette
35387 * @param {String} color
35389 this.relayEvents(ci, ["select"]);
35391 Roo.extend(Roo.menu.ColorMenu, Roo.menu.Menu);
35394 * Ext JS Library 1.1.1
35395 * Copyright(c) 2006-2007, Ext JS, LLC.
35397 * Originally Released Under LGPL - original licence link has changed is not relivant.
35400 * <script type="text/javascript">
35404 * @class Roo.form.Field
35405 * @extends Roo.BoxComponent
35406 * Base class for form fields that provides default event handling, sizing, value handling and other functionality.
35408 * Creates a new Field
35409 * @param {Object} config Configuration options
35411 Roo.form.Field = function(A){
35412 Roo.form.Field.superclass.constructor.call(this, A);
35415 Roo.extend(Roo.form.Field, Roo.BoxComponent, {
35417 * @cfg {String} fieldLabel Label to use when rendering a form.
35420 * @cfg {String} qtip Mouse over tip
35424 * @cfg {String} invalidClass The CSS class to use when marking a field invalid (defaults to "x-form-invalid")
35426 invalidClass : "x-form-invalid",
35428 * @cfg {String} invalidText The error text to use when marking a field invalid and no message is provided (defaults to "The value in this field is invalid")
35430 invalidText : "The value in this field is invalid",
35432 * @cfg {String} focusClass The CSS class to use when the field receives focus (defaults to "x-form-focus")
35434 focusClass : "x-form-focus",
35436 * @cfg {String/Boolean} validationEvent The event that should initiate field validation. Set to false to disable
35437 automatic validation (defaults to "keyup").
35439 validationEvent : "keyup",
35441 * @cfg {Boolean} validateOnBlur Whether the field should validate when it loses focus (defaults to true).
35443 validateOnBlur : true,
35445 * @cfg {Number} validationDelay The length of time in milliseconds after user input begins until validation is initiated (defaults to 250)
35447 validationDelay : 250,
35449 * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
35450 * {tag: "input", type: "text", size: "20", autocomplete: "off"})
35452 defaultAutoCreate : {tag: "input", type: "text", size: "20", autocomplete: "off"},
35454 * @cfg {String} fieldClass The default CSS class for the field (defaults to "x-form-field")
35456 fieldClass : "x-form-field",
35458 * @cfg {String} msgTarget The location where error text should display. Should be one of the following values (defaults to 'qtip'):
35461 ----------- ----------------------------------------------------------------------
35462 qtip Display a quick tip when the user hovers over the field
35463 title Display a default browser title attribute popup
35464 under Add a block div beneath the field containing the error text
35465 side Add an error icon to the right of the field with a popup on hover
35466 [element id] Add the error text directly to the innerHTML of the specified element
35469 msgTarget : 'qtip',
35471 * @cfg {String} msgFx <b>Experimental</b> The effect used when displaying a validation message under the field (defaults to 'normal').
35476 * @cfg {Boolean} readOnly True to mark the field as readOnly in HTML (defaults to false) -- Note: this only sets the element's readOnly DOM attribute.
35481 * @cfg {Boolean} disabled True to disable the field (defaults to false).
35486 * @cfg {String} inputType The type attribute for input fields -- e.g. radio, text, password (defaults to "text").
35488 inputType : undefined,
35491 * @cfg {Number} tabIndex The tabIndex for this field. Note this only applies to fields that are rendered, not those which are built via applyTo (defaults to undefined).
35493 tabIndex : undefined,
35496 isFormField : true,
35501 * @property {Roo.Element} fieldEl
35502 * Element Containing the rendered Field (with label etc.)
35505 * @cfg {Mixed} value A value to initialize this field with.
35510 * @cfg {String} name The field's HTML name attribute.
35513 * @cfg {String} cls A CSS class to apply to the field's underlying element.
35517 initComponent : function(){
35518 Roo.form.Field.superclass.initComponent.call(this);
35522 * Fires when this field receives input focus.
35523 * @param {Roo.form.Field} this
35528 * Fires when this field loses input focus.
35529 * @param {Roo.form.Field} this
35533 * @event specialkey
35534 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
35535 * {@link Roo.EventObject#getKey} to determine which key was pressed.
35536 * @param {Roo.form.Field} this
35537 * @param {Roo.EventObject} e The event object
35542 * Fires just before the field blurs if the field value has changed.
35543 * @param {Roo.form.Field} this
35544 * @param {Mixed} newValue The new value
35545 * @param {Mixed} oldValue The original value
35550 * Fires after the field has been marked as invalid.
35551 * @param {Roo.form.Field} this
35552 * @param {String} msg The validation message
35557 * Fires after the field has been validated with no errors.
35558 * @param {Roo.form.Field} this
35565 * Returns the name attribute of the field if available
35566 * @return {String} name The field name
35568 getName: function(){
35569 return this.rendered && this.el.dom.name ? this.el.dom.name : (this.hiddenName || '');
35573 onRender : function(ct, B){
35574 Roo.form.Field.superclass.onRender.call(this, ct, B);
35576 var cfg = this.getAutoCreate();
35578 cfg.name = this.name || this.id;
35580 if(this.inputType){
35581 cfg.type = this.inputType;
35584 this.el = ct.createChild(cfg, B);
35586 var C = this.el.dom.type;
35588 if(C == 'password'){
35592 this.el.addClass('x-form-'+C);
35595 this.el.dom.readOnly = true;
35597 if(this.tabIndex !== undefined){
35598 this.el.dom.setAttribute('tabIndex', this.tabIndex);
35602 this.el.addClass([this.fieldClass, this.cls]);
35607 * Apply the behaviors of this component to an existing element. <b>This is used instead of render().</b>
35608 * @param {String/HTMLElement/Element} el The id of the node, a DOM node or an existing Element
35609 * @return {Roo.form.Field} this
35611 applyTo : function(D){
35612 this.allowDomMove = false;
35613 this.el = Roo.get(D);
35614 this.render(this.el.dom.parentNode);
35619 initValue : function(){
35620 if(this.value !== undefined){
35621 this.setValue(this.value);
35622 }else if(this.el.dom.value.length > 0){
35623 this.setValue(this.el.dom.value);
35628 * Returns true if this field has been changed since it was originally loaded and is not disabled.
35630 isDirty : function() {
35631 if(this.disabled) {
35634 return String(this.getValue()) !== String(this.originalValue);
35638 afterRender : function(){
35639 Roo.form.Field.superclass.afterRender.call(this);
35644 fireKey : function(e){
35645 if(e.isNavKeyPress()){
35646 this.fireEvent("specialkey", this, e);
35651 * Resets the current field value to the originally loaded value and clears any validation messages
35653 reset : function(){
35654 this.setValue(this.originalValue);
35655 this.clearInvalid();
35659 initEvents : function(){
35660 this.el.on(Roo.isIE ? "keydown" : "keypress", this.fireKey, this);
35661 this.el.on("focus", this.onFocus, this);
35662 this.el.on("blur", this.onBlur, this);
35664 // reference to original value for reset
35665 this.originalValue = this.getValue();
35669 onFocus : function(){
35670 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
35671 this.el.addClass(this.focusClass);
35673 if(!this.hasFocus){
35674 this.hasFocus = true;
35675 this.startValue = this.getValue();
35676 this.fireEvent("focus", this);
35680 beforeBlur : Roo.emptyFn,
35683 onBlur : function(){
35685 if(!Roo.isOpera && this.focusClass){ // don't touch in Opera
35686 this.el.removeClass(this.focusClass);
35689 this.hasFocus = false;
35690 if(this.validationEvent !== false && this.validateOnBlur && this.validationEvent != "blur"){
35693 var v = this.getValue();
35694 if(String(v) !== String(this.startValue)){
35695 this.fireEvent('change', this, v, this.startValue);
35698 this.fireEvent("blur", this);
35702 * Returns whether or not the field value is currently valid
35703 * @param {Boolean} preventMark True to disable marking the field invalid
35704 * @return {Boolean} True if the value is valid, else false
35706 isValid : function(E){
35710 var F = this.preventMark;
35711 this.preventMark = E === true;
35712 var v = this.validateValue(this.processValue(this.getRawValue()));
35713 this.preventMark = F;
35718 * Validates the field value
35719 * @return {Boolean} True if the value is valid, else false
35721 validate : function(){
35722 if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
35723 this.clearInvalid();
35729 processValue : function(G){
35734 // Subclasses should provide the validation implementation by overriding this
35735 validateValue : function(H){
35740 * Mark this field as invalid
35741 * @param {String} msg The validation message
35743 markInvalid : function(I){
35744 if(!this.rendered || this.preventMark){ // not rendered
35748 this.el.addClass(this.invalidClass);
35749 I = I || this.invalidText;
35750 switch(this.msgTarget){
35752 this.el.dom.qtip = I;
35753 this.el.dom.qclass = 'x-form-invalid-tip';
35754 if(Roo.QuickTips){ // fix for floating editors interacting with DND
35755 Roo.QuickTips.enable();
35759 this.el.dom.title = I;
35763 var elp = this.el.findParent('.x-form-element', 5, true);
35764 this.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
35765 this.errorEl.setWidth(elp.getWidth(true)-20);
35768 this.errorEl.update(I);
35769 Roo.form.Field.msgFx[this.msgFx].show(this.errorEl, this);
35772 if(!this.errorIcon){
35773 var elp = this.el.findParent('.x-form-element', 5, true);
35774 this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
35777 this.alignErrorIcon();
35778 this.errorIcon.dom.qtip = I;
35779 this.errorIcon.dom.qclass = 'x-form-invalid-tip';
35780 this.errorIcon.show();
35781 this.on('resize', this.alignErrorIcon, this);
35784 var t = Roo.getDom(this.msgTarget);
35786 t.style.display = this.msgDisplay;
35790 this.fireEvent('invalid', this, I);
35794 alignErrorIcon : function(){
35795 this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
35799 * Clear any invalid styles/messages for this field
35801 clearInvalid : function(){
35802 if(!this.rendered || this.preventMark){ // not rendered
35806 this.el.removeClass(this.invalidClass);
35807 switch(this.msgTarget){
35809 this.el.dom.qtip = '';
35812 this.el.dom.title = '';
35816 Roo.form.Field.msgFx[this.msgFx].hide(this.errorEl, this);
35820 if(this.errorIcon){
35821 this.errorIcon.dom.qtip = '';
35822 this.errorIcon.hide();
35823 this.un('resize', this.alignErrorIcon, this);
35827 var t = Roo.getDom(this.msgTarget);
35829 t.style.display = 'none';
35833 this.fireEvent('valid', this);
35837 * Returns the raw data value which may or may not be a valid, defined value. To return a normalized value see {@link #getValue}.
35838 * @return {Mixed} value The field value
35840 getRawValue : function(){
35841 var v = this.el.getValue();
35842 if(v === this.emptyText){
35849 * Returns the normalized data value (undefined or emptyText will be returned as ''). To return the raw value see {@link #getRawValue}.
35850 * @return {Mixed} value The field value
35852 getValue : function(){
35853 var v = this.el.getValue();
35854 if(v === this.emptyText || v === undefined){
35861 * Sets the underlying DOM field's value directly, bypassing validation. To set the value with validation see {@link #setValue}.
35862 * @param {Mixed} value The value to set
35864 setRawValue : function(v){
35865 return this.el.dom.value = (v === null || v === undefined ? '' : v);
35869 * Sets a data value into the field and validates it. To set the value directly without validation see {@link #setRawValue}.
35870 * @param {Mixed} value The value to set
35872 setValue : function(v){
35875 this.el.dom.value = (v === null || v === undefined ? '' : v);
35880 adjustSize : function(w, h){
35881 var s = Roo.form.Field.superclass.adjustSize.call(this, w, h);
35882 s.width = this.adjustWidth(this.el.dom.tagName, s.width);
35886 adjustWidth : function(J, w){
35887 J = J.toLowerCase();
35888 if(typeof w == 'number' && Roo.isStrict && !Roo.isSafari){
35889 if(Roo.isIE && (J == 'input' || J == 'textarea')){
35893 if(J = 'textarea'){
35896 }else if(Roo.isOpera){
35900 if(J = 'textarea'){
35910 // anything other than normal should be considered experimental
35911 Roo.form.Field.msgFx = {
35913 show: function(K, f){
35914 K.setDisplayed('block');
35917 hide : function(L, f){
35918 L.setDisplayed(false).update('');
35923 show: function(M, f){
35924 M.slideIn('t', {stopFx:true});
35927 hide : function(N, f){
35928 N.slideOut('t', {stopFx:true,useDisplay:true});
35933 show: function(O, f){
35935 O.alignTo(f.el, 'tl-tr');
35936 O.slideIn('l', {stopFx:true});
35939 hide : function(P, f){
35940 P.slideOut('l', {stopFx:true,useDisplay:true});
35946 * Ext JS Library 1.1.1
35947 * Copyright(c) 2006-2007, Ext JS, LLC.
35949 * Originally Released Under LGPL - original licence link has changed is not relivant.
35952 * <script type="text/javascript">
35957 * @class Roo.form.TextField
35958 * @extends Roo.form.Field
35959 * Basic text field. Can be used as a direct replacement for traditional text inputs, or as the base
35960 * class for more sophisticated input controls (like {@link Roo.form.TextArea} and {@link Roo.form.ComboBox}).
35962 * Creates a new TextField
35963 * @param {Object} config Configuration options
35965 Roo.form.TextField = function(A){
35966 Roo.form.TextField.superclass.constructor.call(this, A);
35970 * Fires when the autosize function is triggered. The field may or may not have actually changed size
35971 * according to the default logic, but this event provides a hook for the developer to apply additional
35972 * logic at runtime to resize the field if needed.
35973 * @param {Roo.form.Field} this This text field
35974 * @param {Number} width The new field width
35980 Roo.extend(Roo.form.TextField, Roo.form.Field, {
35982 * @cfg {Boolean} grow True if this field should automatically grow and shrink to its content
35986 * @cfg {Number} growMin The minimum width to allow when grow = true (defaults to 30)
35990 * @cfg {Number} growMax The maximum width to allow when grow = true (defaults to 800)
35994 * @cfg {String} vtype A validation type name as defined in {@link Roo.form.VTypes} (defaults to null)
35998 * @cfg {String} maskRe An input mask regular expression that will be used to filter keystrokes that don't match (defaults to null)
36002 * @cfg {Boolean} disableKeyFilter True to disable input keystroke filtering (defaults to false)
36004 disableKeyFilter : false,
36006 * @cfg {Boolean} allowBlank False to validate that the value length > 0 (defaults to true)
36010 * @cfg {Number} minLength Minimum input field length required (defaults to 0)
36014 * @cfg {Number} maxLength Maximum input field length allowed (defaults to Number.MAX_VALUE)
36016 maxLength : Number.MAX_VALUE,
36018 * @cfg {String} minLengthText Error text to display if the minimum length validation fails (defaults to "The minimum length for this field is {minLength}")
36020 minLengthText : "The minimum length for this field is {0}",
36022 * @cfg {String} maxLengthText Error text to display if the maximum length validation fails (defaults to "The maximum length for this field is {maxLength}")
36024 maxLengthText : "The maximum length for this field is {0}",
36026 * @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
36028 selectOnFocus : false,
36030 * @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
36032 blankText : "This field is required",
36034 * @cfg {Function} validator A custom validation function to be called during field validation (defaults to null).
36035 * If available, this function will be called only after the basic validators all return true, and will be passed the
36036 * current field value and expected to return boolean true if the value is valid or a string error message if invalid.
36040 * @cfg {RegExp} regex A JavaScript RegExp object to be tested against the field value during validation (defaults to null).
36041 * If available, this regex will be evaluated only after the basic validators all return true, and will be passed the
36042 * current field value. If the test fails, the field will be marked invalid using {@link #regexText}.
36046 * @cfg {String} regexText The error text to display if {@link #regex} is used and the test fails during validation (defaults to "")
36050 * @cfg {String} emptyText The default text to display in an empty field (defaults to null).
36054 * @cfg {String} emptyClass The CSS class to apply to an empty field to style the {@link #emptyText} (defaults to
36055 * 'x-form-empty-field'). This class is automatically added and removed as needed depending on the current field value.
36057 emptyClass : 'x-form-empty-field',
36060 initEvents : function(){
36061 Roo.form.TextField.superclass.initEvents.call(this);
36062 if(this.validationEvent == 'keyup'){
36063 this.validationTask = new Roo.util.DelayedTask(this.validate, this);
36064 this.el.on('keyup', this.filterValidation, this);
36066 else if(this.validationEvent !== false){
36067 this.el.on(this.validationEvent, this.validate, this, {buffer: this.validationDelay});
36069 if(this.selectOnFocus || this.emptyText){
36070 this.on("focus", this.preFocus, this);
36071 if(this.emptyText){
36072 this.on('blur', this.postBlur, this);
36073 this.applyEmptyText();
36076 if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
36077 this.el.on("keypress", this.filterKeys, this);
36080 this.el.on("keyup", this.onKeyUp, this, {buffer:50});
36081 this.el.on("click", this.autoSize, this);
36085 processValue : function(B){
36086 if(this.stripCharsRe){
36087 var newValue = B.replace(this.stripCharsRe, '');
36088 if(newValue !== B){
36089 this.setRawValue(newValue);
36096 filterValidation : function(e){
36097 if(!e.isNavKeyPress()){
36098 this.validationTask.delay(this.validationDelay);
36103 onKeyUp : function(e){
36104 if(!e.isNavKeyPress()){
36110 * Resets the current field value to the originally-loaded value and clears any validation messages.
36111 * Also adds emptyText and emptyClass if the original value was blank.
36113 reset : function(){
36114 Roo.form.TextField.superclass.reset.call(this);
36115 this.applyEmptyText();
36118 applyEmptyText : function(){
36119 if(this.rendered && this.emptyText && this.getRawValue().length < 1){
36120 this.setRawValue(this.emptyText);
36121 this.el.addClass(this.emptyClass);
36126 preFocus : function(){
36127 if(this.emptyText){
36128 if(this.el.dom.value == this.emptyText){
36129 this.setRawValue('');
36132 this.el.removeClass(this.emptyClass);
36134 if(this.selectOnFocus){
36135 this.el.dom.select();
36140 postBlur : function(){
36141 this.applyEmptyText();
36145 filterKeys : function(e){
36146 var k = e.getKey();
36147 if(!Roo.isIE && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
36150 var c = e.getCharCode(), cc = String.fromCharCode(c);
36151 if(Roo.isIE && (e.isSpecialKey() || !cc)){
36154 if(!this.maskRe.test(cc)){
36159 setValue : function(v){
36160 if(this.emptyText && this.el && v !== undefined && v !== null && v !== ''){
36161 this.el.removeClass(this.emptyClass);
36164 Roo.form.TextField.superclass.setValue.apply(this, arguments);
36165 this.applyEmptyText();
36170 * Validates a value according to the field's validation rules and marks the field as invalid
36171 * if the validation fails
36172 * @param {Mixed} value The value to validate
36173 * @return {Boolean} True if the value is valid, else false
36175 validateValue : function(C){
36176 if(C.length < 1 || C === this.emptyText){ // if it's blank
36177 if(this.allowBlank){
36178 this.clearInvalid();
36181 this.markInvalid(this.blankText);
36185 if(C.length < this.minLength){
36186 this.markInvalid(String.format(this.minLengthText, this.minLength));
36189 if(C.length > this.maxLength){
36190 this.markInvalid(String.format(this.maxLengthText, this.maxLength));
36194 var vt = Roo.form.VTypes;
36195 if(!vt[this.vtype](C, this)){
36196 this.markInvalid(this.vtypeText || vt[this.vtype +'Text']);
36200 if(typeof this.validator == "function"){
36201 var msg = this.validator(C);
36203 this.markInvalid(msg);
36207 if(this.regex && !this.regex.test(C)){
36208 this.markInvalid(this.regexText);
36215 * Selects text in this field
36216 * @param {Number} start (optional) The index where the selection should start (defaults to 0)
36217 * @param {Number} end (optional) The index where the selection should end (defaults to the text length)
36219 selectText : function(D, E){
36220 var v = this.getRawValue();
36222 D = D === undefined ? 0 : D;
36223 E = E === undefined ? v.length : E;
36224 var d = this.el.dom;
36225 if(d.setSelectionRange){
36226 d.setSelectionRange(D, E);
36227 }else if(d.createTextRange){
36228 var range = d.createTextRange();
36229 range.moveStart("character", D);
36230 range.moveEnd("character", v.length-E);
36237 * Automatically grows the field to accomodate the width of the text up to the maximum field width allowed.
36238 * This only takes effect if grow = true, and fires the autosize event.
36240 autoSize : function(){
36241 if(!this.grow || !this.rendered){
36245 this.metrics = Roo.util.TextMetrics.createInstance(this.el);
36248 var v = el.dom.value;
36249 var d = document.createElement('div');
36250 d.appendChild(document.createTextNode(v));
36254 var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) + /* add extra padding */ 10, this.growMin));
36255 this.el.setWidth(w);
36256 this.fireEvent("autosize", this, w);
36261 * Ext JS Library 1.1.1
36262 * Copyright(c) 2006-2007, Ext JS, LLC.
36264 * Originally Released Under LGPL - original licence link has changed is not relivant.
36267 * <script type="text/javascript">
36271 * @class Roo.form.Hidden
36272 * @extends Roo.form.TextField
36273 * Simple Hidden element used on forms
36275 * usage: form.add(new Roo.form.HiddenField({ 'name' : 'test1' }));
36278 * Creates a new Hidden form element.
36279 * @param {Object} config Configuration options
36284 // easy hidden field...
36285 Roo.form.Hidden = function(A){
36286 Roo.form.Hidden.superclass.constructor.call(this, A);
36289 Roo.extend(Roo.form.Hidden, Roo.form.TextField, {
36291 inputType: 'hidden',
36294 labelSeparator: '',
36296 itemCls : 'x-form-item-display-none'
36305 * Ext JS Library 1.1.1
36306 * Copyright(c) 2006-2007, Ext JS, LLC.
36308 * Originally Released Under LGPL - original licence link has changed is not relivant.
36311 * <script type="text/javascript">
36315 * @class Roo.form.TriggerField
36316 * @extends Roo.form.TextField
36317 * Provides a convenient wrapper for TextFields that adds a clickable trigger button (looks like a combobox by default).
36318 * The trigger has no default action, so you must assign a function to implement the trigger click handler by
36319 * overriding {@link #onTriggerClick}. You can create a TriggerField directly, as it renders exactly like a combobox
36320 * for which you can provide a custom implementation. For example:
36322 var trigger = new Roo.form.TriggerField();
36323 trigger.onTriggerClick = myTriggerFn;
36324 trigger.applyTo('my-field');
36327 * However, in general you will most likely want to use TriggerField as the base class for a reusable component.
36328 * {@link Roo.form.DateField} and {@link Roo.form.ComboBox} are perfect examples of this.
36329 * @cfg {String} triggerClass An additional CSS class used to style the trigger button. The trigger will always get the
36330 * class 'x-form-trigger' by default and triggerClass will be <b>appended</b> if specified.
36332 * Create a new TriggerField.
36333 * @param {Object} config Configuration options (valid {@Roo.form.TextField} config options will also be applied
36334 * to the base TextField)
36336 Roo.form.TriggerField = function(A){
36337 this.mimicing = false;
36338 Roo.form.TriggerField.superclass.constructor.call(this, A);
36341 Roo.extend(Roo.form.TriggerField, Roo.form.TextField, {
36343 * @cfg {String} triggerClass A CSS class to apply to the trigger
36346 * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
36347 * {tag: "input", type: "text", size: "16", autocomplete: "off"})
36349 defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
36351 * @cfg {Boolean} hideTrigger True to hide the trigger element and display only the base text field (defaults to false)
36355 /** @cfg {Boolean} grow @hide */
36356 /** @cfg {Number} growMin @hide */
36357 /** @cfg {Number} growMax @hide */
36363 autoSize: Roo.emptyFn,
36367 deferHeight : true,
36370 actionMode : 'wrap',
36372 onResize : function(w, h){
36373 Roo.form.TriggerField.superclass.onResize.apply(this, arguments);
36374 if(typeof w == 'number'){
36375 this.el.setWidth(this.adjustWidth('input', w - this.trigger.getWidth()));
36380 adjustSize : Roo.BoxComponent.prototype.adjustSize,
36383 getResizeEl : function(){
36388 getPositionEl : function(){
36393 alignErrorIcon : function(){
36394 this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
36398 onRender : function(ct, B){
36399 Roo.form.TriggerField.superclass.onRender.call(this, ct, B);
36400 this.wrap = this.el.wrap({cls: "x-form-field-wrap"});
36401 this.trigger = this.wrap.createChild(this.triggerConfig ||
36402 {tag: "img", src: Roo.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
36403 if(this.hideTrigger){
36404 this.trigger.setDisplayed(false);
36407 this.initTrigger();
36409 this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
36414 initTrigger : function(){
36415 this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});
36416 this.trigger.addClassOnOver('x-form-trigger-over');
36417 this.trigger.addClassOnClick('x-form-trigger-click');
36421 onDestroy : function(){
36423 this.trigger.removeAllListeners();
36424 this.trigger.remove();
36427 this.wrap.remove();
36430 Roo.form.TriggerField.superclass.onDestroy.call(this);
36434 onFocus : function(){
36435 Roo.form.TriggerField.superclass.onFocus.call(this);
36436 if(!this.mimicing){
36437 this.wrap.addClass('x-trigger-wrap-focus');
36438 this.mimicing = true;
36439 Roo.get(Roo.isIE ? document.body : document).on("mousedown", this.mimicBlur, this);
36440 if(this.monitorTab){
36441 this.el.on("keydown", this.checkTab, this);
36447 checkTab : function(e){
36448 if(e.getKey() == e.TAB){
36449 this.triggerBlur();
36454 onBlur : function(){
36459 mimicBlur : function(e, t){
36460 if(!this.wrap.contains(t) && this.validateBlur()){
36461 this.triggerBlur();
36466 triggerBlur : function(){
36467 this.mimicing = false;
36468 Roo.get(Roo.isIE ? document.body : document).un("mousedown", this.mimicBlur);
36469 if(this.monitorTab){
36470 this.el.un("keydown", this.checkTab, this);
36473 this.wrap.removeClass('x-trigger-wrap-focus');
36474 Roo.form.TriggerField.superclass.onBlur.call(this);
36478 // This should be overriden by any subclass that needs to check whether or not the field can be blurred.
36479 validateBlur : function(e, t){
36484 onDisable : function(){
36485 Roo.form.TriggerField.superclass.onDisable.call(this);
36487 this.wrap.addClass('x-item-disabled');
36492 onEnable : function(){
36493 Roo.form.TriggerField.superclass.onEnable.call(this);
36495 this.wrap.removeClass('x-item-disabled');
36500 onShow : function(){
36501 var ae = this.getActionEl();
36504 ae.dom.style.display = '';
36505 ae.dom.style.visibility = 'visible';
36511 onHide : function(){
36512 var ae = this.getActionEl();
36513 ae.dom.style.display = 'none';
36517 * The function that should handle the trigger's click event. This method does nothing by default until overridden
36518 * by an implementing function.
36520 * @param {EventObject} e
36522 onTriggerClick : Roo.emptyFn
36525 // TwinTriggerField is not a public class to be used directly. It is meant as an abstract base class
36526 // to be extended by an implementing class. For an example of implementing this class, see the custom
36527 // SearchField implementation here: http://extjs.com/deploy/ext/examples/form/custom.html
36528 Roo.form.TwinTriggerField = Roo.extend(Roo.form.TriggerField, {
36529 initComponent : function(){
36530 Roo.form.TwinTriggerField.superclass.initComponent.call(this);
36532 this.triggerConfig = {
36533 tag:'span', cls:'x-form-twin-triggers', cn:[
36534 {tag: "img", src: Roo.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
36535 {tag: "img", src: Roo.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
36539 getTrigger : function(C){
36540 return this.triggers[C];
36543 initTrigger : function(){
36544 var ts = this.trigger.select('.x-form-trigger', true);
36545 this.wrap.setStyle('overflow', 'hidden');
36547 ts.each(function(t, E, F){
36548 t.hide = function(){
36549 var w = D.wrap.getWidth();
36550 this.dom.style.display = 'none';
36551 D.el.setWidth(w-D.trigger.getWidth());
36553 t.show = function(){
36554 var w = D.wrap.getWidth();
36555 this.dom.style.display = '';
36556 D.el.setWidth(w-D.trigger.getWidth());
36558 var G = 'Trigger'+(F+1);
36560 if(this['hide'+G]){
36561 t.dom.style.display = 'none';
36564 t.on("click", this['on'+G+'Click'], this, {preventDefault:true});
36565 t.addClassOnOver('x-form-trigger-over');
36566 t.addClassOnClick('x-form-trigger-click');
36568 this.triggers = ts.elements;
36571 onTrigger1Click : Roo.emptyFn,
36572 onTrigger2Click : Roo.emptyFn
36576 * Ext JS Library 1.1.1
36577 * Copyright(c) 2006-2007, Ext JS, LLC.
36579 * Originally Released Under LGPL - original licence link has changed is not relivant.
36582 * <script type="text/javascript">
36586 * @class Roo.form.TextArea
36587 * @extends Roo.form.TextField
36588 * Multiline text field. Can be used as a direct replacement for traditional textarea fields, plus adds
36589 * support for auto-sizing.
36591 * Creates a new TextArea
36592 * @param {Object} config Configuration options
36594 Roo.form.TextArea = function(A){
36595 Roo.form.TextArea.superclass.constructor.call(this, A);
36596 // these are provided exchanges for backwards compat
36597 // minHeight/maxHeight were replaced by growMin/growMax to be
36598 // compatible with TextField growing config values
36599 if(this.minHeight !== undefined){
36600 this.growMin = this.minHeight;
36602 if(this.maxHeight !== undefined){
36603 this.growMax = this.maxHeight;
36607 Roo.extend(Roo.form.TextArea, Roo.form.TextField, {
36609 * @cfg {Number} growMin The minimum height to allow when grow = true (defaults to 60)
36613 * @cfg {Number} growMax The maximum height to allow when grow = true (defaults to 1000)
36617 * @cfg {Boolean} preventScrollbars True to prevent scrollbars from appearing regardless of how much text is
36618 * in the field (equivalent to setting overflow: hidden, defaults to false)
36620 preventScrollbars: false,
36622 * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
36623 * {tag: "textarea", style: "width:300px;height:60px;", autocomplete: "off"})
36627 onRender : function(ct, B){
36629 this.defaultAutoCreate = {
36631 style:"width:300px;height:60px;",
36632 autocomplete: "off"
36636 Roo.form.TextArea.superclass.onRender.call(this, ct, B);
36638 this.textSizeEl = Roo.DomHelper.append(document.body, {
36639 tag: "pre", cls: "x-form-grow-sizer"
36641 if(this.preventScrollbars){
36642 this.el.setStyle("overflow", "hidden");
36645 this.el.setHeight(this.growMin);
36649 onDestroy : function(){
36650 if(this.textSizeEl){
36651 this.textSizeEl.parentNode.removeChild(this.textSizeEl);
36654 Roo.form.TextArea.superclass.onDestroy.call(this);
36658 onKeyUp : function(e){
36659 if(!e.isNavKeyPress() || e.getKey() == e.ENTER){
36665 * Automatically grows the field to accomodate the height of the text up to the maximum field height allowed.
36666 * This only takes effect if grow = true, and fires the autosize event if the height changes.
36668 autoSize : function(){
36669 if(!this.grow || !this.textSizeEl){
36673 var v = el.dom.value;
36674 var ts = this.textSizeEl;
36677 ts.appendChild(document.createTextNode(v));
36680 Roo.fly(ts).setWidth(this.el.getWidth());
36682 v = "  ";
36685 v = v.replace(/\n/g, '<p> </p>');
36688 v += " \n ";
36692 var h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
36693 if(h != this.lastHeight){
36694 this.lastHeight = h;
36695 this.el.setHeight(h);
36696 this.fireEvent("autosize", this, h);
36702 * Ext JS Library 1.1.1
36703 * Copyright(c) 2006-2007, Ext JS, LLC.
36705 * Originally Released Under LGPL - original licence link has changed is not relivant.
36708 * <script type="text/javascript">
36713 * @class Roo.form.NumberField
36714 * @extends Roo.form.TextField
36715 * Numeric text field that provides automatic keystroke filtering and numeric validation.
36717 * Creates a new NumberField
36718 * @param {Object} config Configuration options
36720 Roo.form.NumberField = function(A){
36721 Roo.form.NumberField.superclass.constructor.call(this, A);
36724 Roo.extend(Roo.form.NumberField, Roo.form.TextField, {
36726 * @cfg {String} fieldClass The default CSS class for the field (defaults to "x-form-field x-form-num-field")
36728 fieldClass: "x-form-field x-form-num-field",
36730 * @cfg {Boolean} allowDecimals False to disallow decimal values (defaults to true)
36732 allowDecimals : true,
36734 * @cfg {String} decimalSeparator Character(s) to allow as the decimal separator (defaults to '.')
36736 decimalSeparator : ".",
36738 * @cfg {Number} decimalPrecision The maximum precision to display after the decimal separator (defaults to 2)
36740 decimalPrecision : 2,
36742 * @cfg {Boolean} allowNegative False to prevent entering a negative sign (defaults to true)
36744 allowNegative : true,
36746 * @cfg {Number} minValue The minimum allowed value (defaults to Number.NEGATIVE_INFINITY)
36748 minValue : Number.NEGATIVE_INFINITY,
36750 * @cfg {Number} maxValue The maximum allowed value (defaults to Number.MAX_VALUE)
36752 maxValue : Number.MAX_VALUE,
36754 * @cfg {String} minText Error text to display if the minimum value validation fails (defaults to "The minimum value for this field is {minValue}")
36756 minText : "The minimum value for this field is {0}",
36758 * @cfg {String} maxText Error text to display if the maximum value validation fails (defaults to "The maximum value for this field is {maxValue}")
36760 maxText : "The maximum value for this field is {0}",
36762 * @cfg {String} nanText Error text to display if the value is not a valid number. For example, this can happen
36763 * if a valid character like '.' or '-' is left in the field with no number (defaults to "{value} is not a valid number")
36765 nanText : "{0} is not a valid number",
36768 initEvents : function(){
36769 Roo.form.NumberField.superclass.initEvents.call(this);
36770 var B = "0123456789";
36771 if(this.allowDecimals){
36772 B += this.decimalSeparator;
36774 if(this.allowNegative){
36778 this.stripCharsRe = new RegExp('[^'+B+']', 'gi');
36779 var C = function(e){
36780 var k = e.getKey();
36781 if(!Roo.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE )){
36784 var c = e.getCharCode();
36785 if(B.indexOf(String.fromCharCode(c)) === -1){
36789 this.el.on("keypress", C, this);
36793 validateValue : function(D){
36794 if(!Roo.form.NumberField.superclass.validateValue.call(this, D)){
36797 if(D.length < 1){ // if it's blank and textfield didn't flag it then it's valid
36800 var E = this.parseValue(D);
36802 this.markInvalid(String.format(this.nanText, D));
36805 if(E < this.minValue){
36806 this.markInvalid(String.format(this.minText, this.minValue));
36809 if(E > this.maxValue){
36810 this.markInvalid(String.format(this.maxText, this.maxValue));
36816 getValue : function(){
36817 return this.fixPrecision(this.parseValue(Roo.form.NumberField.superclass.getValue.call(this)));
36821 parseValue : function(F){
36822 F = parseFloat(String(F).replace(this.decimalSeparator, "."));
36823 return isNaN(F) ? '' : F;
36827 fixPrecision : function(G){
36829 if(!this.allowDecimals || this.decimalPrecision == -1 || H || !G){
36832 return parseFloat(G).toFixed(this.decimalPrecision);
36835 setValue : function(v){
36836 Roo.form.NumberField.superclass.setValue.call(this, String(v).replace(".", this.decimalSeparator));
36840 decimalPrecisionFcn : function(v){
36841 return Math.floor(v);
36844 beforeBlur : function(){
36845 var v = this.parseValue(this.getRawValue());
36847 this.setValue(this.fixPrecision(v));
36853 * Ext JS Library 1.1.1
36854 * Copyright(c) 2006-2007, Ext JS, LLC.
36856 * Originally Released Under LGPL - original licence link has changed is not relivant.
36859 * <script type="text/javascript">
36863 * @class Roo.form.DateField
36864 * @extends Roo.form.TriggerField
36865 * Provides a date input field with a {@link Roo.DatePicker} dropdown and automatic date validation.
36867 * Create a new DateField
36868 * @param {Object} config
36870 Roo.form.DateField = function(A){
36871 Roo.form.DateField.superclass.constructor.call(this, A);
36877 * Fires when a date is selected
36878 * @param {Roo.form.DateField} combo This combo box
36879 * @param {Date} date The date selected
36886 if(typeof this.minValue == "string") this.minValue = this.parseDate(this.minValue);
36887 if(typeof this.maxValue == "string") this.maxValue = this.parseDate(this.maxValue);
36888 this.ddMatch = null;
36889 if(this.disabledDates){
36890 var dd = this.disabledDates;
36892 for(var i = 0; i < dd.length; i++){
36894 if(i != dd.length-1) re += "|";
36897 this.ddMatch = new RegExp(re + ")");
36901 Roo.extend(Roo.form.DateField, Roo.form.TriggerField, {
36903 * @cfg {String} format
36904 * The default date format string which can be overriden for localization support. The format must be
36905 * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
36909 * @cfg {String} altFormats
36910 * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
36911 * format (defaults to 'm/d/Y|m-d-y|m-d-Y|m/d|m-d|d').
36913 altFormats : "m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d",
36915 * @cfg {Array} disabledDays
36916 * An array of days to disable, 0 based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
36918 disabledDays : null,
36920 * @cfg {String} disabledDaysText
36921 * The tooltip to display when the date falls on a disabled day (defaults to 'Disabled')
36923 disabledDaysText : "Disabled",
36925 * @cfg {Array} disabledDates
36926 * An array of "dates" to disable, as strings. These strings will be used to build a dynamic regular
36927 * expression so they are very powerful. Some examples:
36929 * <li>["03/08/2003", "09/16/2003"] would disable those exact dates</li>
36930 * <li>["03/08", "09/16"] would disable those days for every year</li>
36931 * <li>["^03/08"] would only match the beginning (useful if you are using short years)</li>
36932 * <li>["03/../2006"] would disable every day in March 2006</li>
36933 * <li>["^03"] would disable every day in every March</li>
36935 * In order to support regular expressions, if you are using a date format that has "." in it, you will have to
36936 * escape the dot when restricting dates. For example: ["03\\.08\\.03"].
36938 disabledDates : null,
36940 * @cfg {String} disabledDatesText
36941 * The tooltip text to display when the date falls on a disabled date (defaults to 'Disabled')
36943 disabledDatesText : "Disabled",
36945 * @cfg {Date/String} minValue
36946 * The minimum allowed date. Can be either a Javascript date object or a string date in a
36947 * valid format (defaults to null).
36951 * @cfg {Date/String} maxValue
36952 * The maximum allowed date. Can be either a Javascript date object or a string date in a
36953 * valid format (defaults to null).
36957 * @cfg {String} minText
36958 * The error text to display when the date in the cell is before minValue (defaults to
36959 * 'The date in this field must be after {minValue}').
36961 minText : "The date in this field must be equal to or after {0}",
36963 * @cfg {String} maxText
36964 * The error text to display when the date in the cell is after maxValue (defaults to
36965 * 'The date in this field must be before {maxValue}').
36967 maxText : "The date in this field must be equal to or before {0}",
36969 * @cfg {String} invalidText
36970 * The error text to display when the date in the field is invalid (defaults to
36971 * '{value} is not a valid date - it must be in the format {format}').
36973 invalidText : "{0} is not a valid date - it must be in the format {1}",
36975 * @cfg {String} triggerClass
36976 * An additional CSS class used to style the trigger button. The trigger will always get the
36977 * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified (defaults to 'x-form-date-trigger'
36978 * which displays a calendar icon).
36980 triggerClass : 'x-form-date-trigger',
36984 * @cfg {bool} useIso
36985 * if enabled, then the date field will use a hidden field to store the
36986 * real value as iso formated date. default (false)
36990 * @cfg {String/Object} autoCreate
36991 * A DomHelper element spec, or true for a default element spec (defaults to
36992 * {tag: "input", type: "text", size: "10", autocomplete: "off"})
36995 defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
36998 hiddenField: false,
37000 onRender : function(ct, B)
37002 Roo.form.DateField.superclass.onRender.call(this, ct, B);
37004 this.el.dom.removeAttribute('name');
37005 this.hiddenField = this.el.insertSibling({ tag:'input', type:'hidden', name: this.name },
37007 this.hiddenField.value = this.formatDate(this.value, 'Y-m-d');
37008 // prevent input submission
37009 this.hiddenName = this.name;
37016 validateValue : function(C)
37018 C = this.formatDate(C);
37019 if(!Roo.form.DateField.superclass.validateValue.call(this, C)){
37022 if(C.length < 1){ // if it's blank and textfield didn't flag it then it's valid
37026 C = this.parseDate(C);
37028 this.markInvalid(String.format(this.invalidText, D, this.format));
37031 var E = C.getTime();
37032 if(this.minValue && E < this.minValue.getTime()){
37033 this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
37036 if(this.maxValue && E > this.maxValue.getTime()){
37037 this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
37040 if(this.disabledDays){
37041 var day = C.getDay();
37042 for(var i = 0; i < this.disabledDays.length; i++) {
37043 if(day === this.disabledDays[i]){
37044 this.markInvalid(this.disabledDaysText);
37049 var F = this.formatDate(C);
37050 if(this.ddMatch && this.ddMatch.test(F)){
37051 this.markInvalid(String.format(this.disabledDatesText, F));
37058 // Provides logic to override the default TriggerField.validateBlur which just returns true
37059 validateBlur : function(){
37060 return !this.menu || !this.menu.isVisible();
37064 * Returns the current date value of the date field.
37065 * @return {Date} The date value
37067 getValue : function(){
37069 return this.hiddenField ? this.hiddenField.value : this.parseDate(Roo.form.DateField.superclass.getValue.call(this)) || "";
37073 * Sets the value of the date field. You can pass a date object or any string that can be parsed into a valid
37074 * date, using DateField.format as the date format, according to the same rules as {@link Date#parseDate}
37075 * (the default format used is "m/d/y").
37078 //All of these calls set the same date value (May 4, 2006)
37080 //Pass a date object:
37081 var dt = new Date('5/4/06');
37082 dateField.setValue(dt);
37084 //Pass a date string (default format):
37085 dateField.setValue('5/4/06');
37087 //Pass a date string (custom format):
37088 dateField.format = 'Y-m-d';
37089 dateField.setValue('2006-5-4');
37091 * @param {String/Date} date The date or valid date string
37093 setValue : function(G){
37094 if (this.hiddenField) {
37095 this.hiddenField.value = this.formatDate(this.parseDate(G), 'Y-m-d');
37098 Roo.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(G)));
37102 parseDate : function(H){
37103 if(!H || H instanceof Date){
37106 var v = Date.parseDate(H, this.format);
37107 if(!v && this.altFormats){
37108 if(!this.altFormatsArray){
37109 this.altFormatsArray = this.altFormats.split("|");
37111 for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
37112 v = Date.parseDate(H, this.altFormatsArray[i]);
37119 formatDate : function(I, J){
37120 return (!I || !(I instanceof Date)) ?
37121 I : I.dateFormat(J || this.format);
37126 select: function(m, d){
37128 this.fireEvent('select', this, d);
37130 show : function(){ // retain focus styling
37134 this.focus.defer(10, this);
37135 var ml = this.menuListeners;
37136 this.menu.un("select", ml.select, this);
37137 this.menu.un("show", ml.show, this);
37138 this.menu.un("hide", ml.hide, this);
37143 // Implements the default empty TriggerField.onTriggerClick function to display the DatePicker
37144 onTriggerClick : function(){
37148 if(this.menu == null){
37149 this.menu = new Roo.menu.DateMenu();
37152 Roo.apply(this.menu.picker, {
37153 showClear: this.allowBlank,
37154 minDate : this.minValue,
37155 maxDate : this.maxValue,
37156 disabledDatesRE : this.ddMatch,
37157 disabledDatesText : this.disabledDatesText,
37158 disabledDays : this.disabledDays,
37159 disabledDaysText : this.disabledDaysText,
37160 format : this.format,
37161 minText : String.format(this.minText, this.formatDate(this.minValue)),
37162 maxText : String.format(this.maxText, this.formatDate(this.maxValue))
37164 this.menu.on(Roo.apply({}, this.menuListeners, {
37167 this.menu.picker.setValue(this.getValue() || new Date());
37168 this.menu.show(this.el, "tl-bl?");
37171 beforeBlur : function(){
37172 var v = this.parseDate(this.getRawValue());
37178 /** @cfg {Boolean} grow @hide */
37179 /** @cfg {Number} growMin @hide */
37180 /** @cfg {Number} growMax @hide */
37188 * Ext JS Library 1.1.1
37189 * Copyright(c) 2006-2007, Ext JS, LLC.
37191 * Originally Released Under LGPL - original licence link has changed is not relivant.
37194 * <script type="text/javascript">
37199 * @class Roo.form.ComboBox
37200 * @extends Roo.form.TriggerField
37201 * A combobox control with support for autocomplete, remote-loading, paging and many other features.
37203 * Create a new ComboBox.
37204 * @param {Object} config Configuration options
37206 Roo.form.ComboBox = function(A){
37207 Roo.form.ComboBox.superclass.constructor.call(this, A);
37211 * Fires when the dropdown list is expanded
37212 * @param {Roo.form.ComboBox} combo This combo box
37217 * Fires when the dropdown list is collapsed
37218 * @param {Roo.form.ComboBox} combo This combo box
37222 * @event beforeselect
37223 * Fires before a list item is selected. Return false to cancel the selection.
37224 * @param {Roo.form.ComboBox} combo This combo box
37225 * @param {Roo.data.Record} record The data record returned from the underlying store
37226 * @param {Number} index The index of the selected item in the dropdown list
37228 'beforeselect' : true,
37231 * Fires when a list item is selected
37232 * @param {Roo.form.ComboBox} combo This combo box
37233 * @param {Roo.data.Record} record The data record returned from the underlying store (or false on clear)
37234 * @param {Number} index The index of the selected item in the dropdown list
37238 * @event beforequery
37239 * Fires before all queries are processed. Return false to cancel the query or set cancel to true.
37240 * The event object passed has these properties:
37241 * @param {Roo.form.ComboBox} combo This combo box
37242 * @param {String} query The query
37243 * @param {Boolean} forceAll true to force "all" query
37244 * @param {Boolean} cancel true to cancel the query
37245 * @param {Object} e The query event object
37247 'beforequery': true
37249 if(this.transform){
37250 this.allowDomMove = false;
37251 var s = Roo.getDom(this.transform);
37252 if(!this.hiddenName){
37253 this.hiddenName = s.name;
37256 this.mode = 'local';
37257 var d = [], opts = s.options;
37258 for(var i = 0, len = opts.length;i < len; i++){
37260 var value = (Roo.isIE ? o.getAttributeNode('value').specified : o.hasAttribute('value')) ? o.value : o.text;
37262 this.value = value;
37265 d.push([value, o.text]);
37268 this.store = new Roo.data.SimpleStore({
37270 fields: ['value', 'text'],
37273 this.valueField = 'value';
37274 this.displayField = 'text';
37277 s.name = Roo.id(); // wipe out the name in case somewhere else they have a reference
37278 if(!this.lazyRender){
37279 this.target = true;
37280 this.el = Roo.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
37281 s.parentNode.removeChild(s); // remove it
37282 this.render(this.el.parentNode);
37284 s.parentNode.removeChild(s); // remove it
37289 this.store = Roo.factory(this.store, Roo.data);
37293 this.selectedIndex = -1;
37294 if(this.mode == 'local'){
37295 if(A.queryDelay === undefined){
37296 this.queryDelay = 10;
37298 if(A.minChars === undefined){
37304 Roo.extend(Roo.form.ComboBox, Roo.form.TriggerField, {
37306 * @cfg {String/HTMLElement/Element} transform The id, DOM node or element of an existing select to convert to a ComboBox
37309 * @cfg {Boolean} lazyRender True to prevent the ComboBox from rendering until requested (should always be used when
37310 * rendering into an Roo.Editor, defaults to false)
37313 * @cfg {Boolean/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to:
37314 * {tag: "input", type: "text", size: "24", autocomplete: "off"})
37317 * @cfg {Roo.data.Store} store The data store to which this combo is bound (defaults to undefined)
37320 * @cfg {String} title If supplied, a header element is created containing this text and added into the top of
37321 * the dropdown list (defaults to undefined, with no header element)
37325 * @cfg {String/Roo.Template} tpl The template to use to render the output
37329 defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
37331 * @cfg {Number} listWidth The width in pixels of the dropdown list (defaults to the width of the ComboBox field)
37333 listWidth: undefined,
37335 * @cfg {String} displayField The underlying data field name to bind to this CombBox (defaults to undefined if
37336 * mode = 'remote' or 'text' if mode = 'local')
37338 displayField: undefined,
37340 * @cfg {String} valueField The underlying data value name to bind to this CombBox (defaults to undefined if
37341 * mode = 'remote' or 'value' if mode = 'local').
37342 * Note: use of a valueField requires the user make a selection
37343 * in order for a value to be mapped.
37345 valueField: undefined,
37347 * @cfg {String} hiddenName If specified, a hidden form field with this name is dynamically generated to store the
37348 * field's data value (defaults to the underlying DOM element's name)
37350 hiddenName: undefined,
37352 * @cfg {String} listClass CSS class to apply to the dropdown list element (defaults to '')
37356 * @cfg {String} selectedClass CSS class to apply to the selected item in the dropdown list (defaults to 'x-combo-selected')
37358 selectedClass: 'x-combo-selected',
37360 * @cfg {String} triggerClass An additional CSS class used to style the trigger button. The trigger will always get the
37361 * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified (defaults to 'x-form-arrow-trigger'
37362 * which displays a downward arrow icon).
37364 triggerClass : 'x-form-arrow-trigger',
37366 * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop" for bottom-right
37370 * @cfg {String} listAlign A valid anchor position value. See {@link Roo.Element#alignTo} for details on supported
37371 * anchor positions (defaults to 'tl-bl')
37373 listAlign: 'tl-bl?',
37375 * @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown (defaults to 300)
37379 * @cfg {String} triggerAction The action to execute when the trigger field is activated. Use 'all' to run the
37380 * query specified by the allQuery config option (defaults to 'query')
37382 triggerAction: 'query',
37384 * @cfg {Number} minChars The minimum number of characters the user must type before autocomplete and typeahead activate
37385 * (defaults to 4, does not apply if editable = false)
37389 * @cfg {Boolean} typeAhead True to populate and autoselect the remainder of the text being typed after a configurable
37390 * delay (typeAheadDelay) if it matches a known value (defaults to false)
37394 * @cfg {Number} queryDelay The length of time in milliseconds to delay between the start of typing and sending the
37395 * query to filter the dropdown list (defaults to 500 if mode = 'remote' or 10 if mode = 'local')
37399 * @cfg {Number} pageSize If greater than 0, a paging toolbar is displayed in the footer of the dropdown list and the
37400 * filter queries will execute with page start and limit parameters. Only applies when mode = 'remote' (defaults to 0)
37404 * @cfg {Boolean} selectOnFocus True to select any existing text in the field immediately on focus. Only applies
37405 * when editable = true (defaults to false)
37407 selectOnFocus:false,
37409 * @cfg {String} queryParam Name of the query as it will be passed on the querystring (defaults to 'query')
37411 queryParam: 'query',
37413 * @cfg {String} loadingText The text to display in the dropdown list while data is loading. Only applies
37414 * when mode = 'remote' (defaults to 'Loading...')
37416 loadingText: 'Loading...',
37418 * @cfg {Boolean} resizable True to add a resize handle to the bottom of the dropdown list (defaults to false)
37422 * @cfg {Number} handleHeight The height in pixels of the dropdown list resize handle if resizable = true (defaults to 8)
37426 * @cfg {Boolean} editable False to prevent the user from typing text directly into the field, just like a
37427 * traditional select (defaults to true)
37431 * @cfg {String} allQuery The text query to send to the server to return all records for the list with no filtering (defaults to '')
37435 * @cfg {String} mode Set to 'local' if the ComboBox loads local data (defaults to 'remote' which loads from the server)
37439 * @cfg {Number} minListWidth The minimum width of the dropdown list in pixels (defaults to 70, will be ignored if
37440 * listWidth has a higher value)
37444 * @cfg {Boolean} forceSelection True to restrict the selected value to one of the values in the list, false to
37445 * allow the user to set arbitrary text into the field (defaults to false)
37447 forceSelection:false,
37449 * @cfg {Number} typeAheadDelay The length of time in milliseconds to wait until the typeahead text is displayed
37450 * if typeAhead = true (defaults to 250)
37452 typeAheadDelay : 250,
37454 * @cfg {String} valueNotFoundText When using a name/value combo, if the value passed to setValue is not found in
37455 * the store, valueNotFoundText will be displayed as the field text if defined (defaults to undefined)
37457 valueNotFoundText : undefined,
37459 * @cfg {bool} blockFocus Prevents all focus calls, so it can work with things like HTML edtor bar
37461 blockFocus : false,
37464 * @cfg {bool} disableClear Disable showing of clear button.
37466 disableClear : false,
37469 onRender : function(ct, B){
37470 Roo.form.ComboBox.superclass.onRender.call(this, ct, B);
37471 if(this.hiddenName){
37472 this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
37474 this.hiddenField.value =
37475 this.hiddenValue !== undefined ? this.hiddenValue :
37476 this.value !== undefined ? this.value : '';
37478 // prevent input submission
37479 this.el.dom.removeAttribute('name');
37482 this.el.dom.setAttribute('autocomplete', 'off');
37485 var C = 'x-combo-list';
37487 this.list = new Roo.Layer({
37488 shadow: this.shadow, cls: [C, this.listClass].join(' '), constrain:false
37491 var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
37492 this.list.setWidth(lw);
37493 this.list.swallowEvent('mousewheel');
37494 this.assetHeight = 0;
37497 this.header = this.list.createChild({cls:C+'-hd', html: this.title});
37498 this.assetHeight += this.header.getHeight();
37502 this.innerList = this.list.createChild({cls:C+'-inner'});
37503 this.innerList.on('mouseover', this.onViewOver, this);
37504 this.innerList.on('mousemove', this.onViewMove, this);
37505 this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
37507 if(this.allowBlank && !this.pageSize && !this.disableClear){
37508 this.footer = this.list.createChild({cls:C+'-ft'});
37509 this.pageTb = new Roo.Toolbar(this.footer);
37513 this.footer = this.list.createChild({cls:C+'-ft'});
37514 this.pageTb = new Roo.PagingToolbar(this.footer, this.store,
37515 {pageSize: this.pageSize});
37519 if (this.pageTb && this.allowBlank && !this.disableClear) {
37521 this.pageTb.add(new Roo.Toolbar.Fill(), {
37522 cls: 'x-btn-icon x-btn-clear',
37524 handler: function()
37527 _this.clearValue();
37528 _this.onSelect(false, -1);
37533 this.assetHeight += this.footer.getHeight();
37538 this.tpl = '<div class="'+C+'-item">{' + this.displayField + '}</div>';
37542 this.view = new Roo.View(this.innerList, this.tpl, {
37543 singleSelect:true, store: this.store, selectedClass: this.selectedClass
37546 this.view.on('click', this.onViewClick, this);
37548 this.store.on('beforeload', this.onBeforeLoad, this);
37549 this.store.on('load', this.onLoad, this);
37550 this.store.on('loadexception', this.collapse, this);
37552 if(this.resizable){
37553 this.resizer = new Roo.Resizable(this.list, {
37554 pinned:true, handles:'se'
37556 this.resizer.on('resize', function(r, w, h){
37557 this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
37558 this.listWidth = w;
37559 this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
37560 this.restrictHeight();
37562 this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
37564 if(!this.editable){
37565 this.editable = true;
37566 this.setEditable(false);
37571 initEvents : function(){
37572 Roo.form.ComboBox.superclass.initEvents.call(this);
37574 this.keyNav = new Roo.KeyNav(this.el, {
37575 "up" : function(e){
37576 this.inKeyMode = true;
37580 "down" : function(e){
37581 if(!this.isExpanded()){
37582 this.onTriggerClick();
37584 this.inKeyMode = true;
37589 "enter" : function(e){
37590 this.onViewClick();
37594 "esc" : function(e){
37598 "tab" : function(e){
37599 this.onViewClick(false);
37605 doRelay : function(D, E, F){
37606 if(F == 'down' || this.scope.isExpanded()){
37607 return Roo.KeyNav.prototype.doRelay.apply(this, arguments);
37614 this.queryDelay = Math.max(this.queryDelay || 10,
37615 this.mode == 'local' ? 10 : 250);
37616 this.dqTask = new Roo.util.DelayedTask(this.initQuery, this);
37617 if(this.typeAhead){
37618 this.taTask = new Roo.util.DelayedTask(this.onTypeAhead, this);
37620 if(this.editable !== false){
37621 this.el.on("keyup", this.onKeyUp, this);
37623 if(this.forceSelection){
37624 this.on('blur', this.doForce, this);
37628 onDestroy : function(){
37630 this.view.setStore(null);
37631 this.view.el.removeAllListeners();
37632 this.view.el.remove();
37633 this.view.purgeListeners();
37636 this.list.destroy();
37639 this.store.un('beforeload', this.onBeforeLoad, this);
37640 this.store.un('load', this.onLoad, this);
37641 this.store.un('loadexception', this.collapse, this);
37644 Roo.form.ComboBox.superclass.onDestroy.call(this);
37648 fireKey : function(e){
37649 if(e.isNavKeyPress() && !this.list.isVisible()){
37650 this.fireEvent("specialkey", this, e);
37655 onResize: function(w, h){
37656 Roo.form.ComboBox.superclass.onResize.apply(this, arguments);
37657 if(this.list && this.listWidth === undefined){
37658 var lw = Math.max(w, this.minListWidth);
37659 this.list.setWidth(lw);
37660 this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
37665 * Allow or prevent the user from directly editing the field text. If false is passed,
37666 * the user will only be able to select from the items defined in the dropdown list. This method
37667 * is the runtime equivalent of setting the 'editable' config option at config time.
37668 * @param {Boolean} value True to allow the user to directly edit the field text
37670 setEditable : function(D){
37671 if(D == this.editable){
37677 this.el.dom.setAttribute('readOnly', true);
37678 this.el.on('mousedown', this.onTriggerClick, this);
37679 this.el.addClass('x-combo-noedit');
37681 this.el.dom.setAttribute('readOnly', false);
37682 this.el.un('mousedown', this.onTriggerClick, this);
37683 this.el.removeClass('x-combo-noedit');
37688 onBeforeLoad : function(){
37689 if(!this.hasFocus){
37693 this.innerList.update(this.loadingText ?
37694 '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
37695 this.restrictHeight();
37696 this.selectedIndex = -1;
37700 onLoad : function(){
37701 if(!this.hasFocus){
37704 if(this.store.getCount() > 0){
37706 this.restrictHeight();
37707 if(this.lastQuery == this.allQuery){
37709 this.el.dom.select();
37711 if(!this.selectByValue(this.value, true)){
37712 this.select(0, true);
37716 if(this.typeAhead && this.lastKey != Roo.EventObject.BACKSPACE && this.lastKey != Roo.EventObject.DELETE ){
37717 this.taTask.delay(this.typeAheadDelay);
37721 this.onEmptyResults();
37727 onTypeAhead : function(){
37728 if(this.store.getCount() > 0){
37729 var r = this.store.getAt(0);
37730 var newValue = r.data[this.displayField];
37731 var len = newValue.length;
37732 var selStart = this.getRawValue().length;
37733 if(selStart != len){
37734 this.setRawValue(newValue);
37735 this.selectText(selStart, newValue.length);
37741 onSelect : function(E, F){
37742 if(this.fireEvent('beforeselect', this, E, F) !== false){
37743 this.setFromData(F > -1 ? E.data : false);
37745 this.fireEvent('select', this, E, F);
37750 * Returns the currently selected field value or empty string if no value is set.
37751 * @return {String} value The selected value
37753 getValue : function(){
37754 if(this.valueField){
37755 return typeof this.value != 'undefined' ? this.value : '';
37757 return Roo.form.ComboBox.superclass.getValue.call(this);
37762 * Clears any text/value currently set in the field
37764 clearValue : function(){
37765 if(this.hiddenField){
37766 this.hiddenField.value = '';
37770 this.setRawValue('');
37771 this.lastSelectionText = '';
37772 this.applyEmptyText();
37776 * Sets the specified value into the field. If the value finds a match, the corresponding record text
37777 * will be displayed in the field. If the value does not match the data value of an existing item,
37778 * and the valueNotFoundText config option is defined, it will be displayed as the default field text.
37779 * Otherwise the field will be blank (although the value will still be set).
37780 * @param {String} value The value to match
37782 setValue : function(v){
37784 if(this.valueField){
37785 var r = this.findRecord(this.valueField, v);
37787 G = r.data[this.displayField];
37788 }else if(this.valueNotFoundText !== undefined){
37789 G = this.valueNotFoundText;
37793 this.lastSelectionText = G;
37794 if(this.hiddenField){
37795 this.hiddenField.value = v;
37798 Roo.form.ComboBox.superclass.setValue.call(this, G);
37802 * @property {Object} the last set data for the element
37807 * Sets the value of the field based on a object which is related to the record format for the store.
37808 * @param {Object} value the value to set as. or false on reset?
37810 setFromData : function(o){
37811 var dv = ''; // display value
37812 var vv = ''; // value value..
37814 if (this.displayField) {
37815 dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
37817 // this is an error condition!!!
37818 console.log('no value field set for '+ this.name);
37821 if(this.valueField){
37822 vv = !o || typeof(o[this.valueField]) == 'undefined' ? dv : o[this.valueField];
37824 if(this.hiddenField){
37825 this.hiddenField.value = vv;
37827 this.lastSelectionText = dv;
37828 Roo.form.ComboBox.superclass.setValue.call(this, dv);
37833 // no hidden field.. - we store the value in 'value', but still display
37834 // display field!!!!
37835 this.lastSelectionText = dv;
37836 Roo.form.ComboBox.superclass.setValue.call(this, dv);
37842 findRecord : function(H, I){
37844 if(this.store.getCount() > 0){
37845 this.store.each(function(r){
37846 if(r.data[H] == I){
37856 onViewMove : function(e, t){
37857 this.inKeyMode = false;
37861 onViewOver : function(e, t){
37862 if(this.inKeyMode){ // prevent key nav and mouse over conflicts
37865 var K = this.view.findItemFromChild(t);
37867 var F = this.view.indexOf(K);
37868 this.select(F, false);
37873 onViewClick : function(L){
37874 var M = this.view.getSelectedIndexes()[0];
37875 var r = this.store.getAt(M);
37877 this.onSelect(r, M);
37879 if(L !== false && !this.blockFocus){
37885 restrictHeight : function(){
37886 this.innerList.dom.style.height = '';
37887 var N = this.innerList.dom;
37888 var h = Math.max(N.clientHeight, N.offsetHeight, N.scrollHeight);
37889 this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
37890 this.list.beginUpdate();
37891 this.list.setHeight(this.innerList.getHeight()+this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight);
37892 this.list.alignTo(this.el, this.listAlign);
37893 this.list.endUpdate();
37897 onEmptyResults : function(){
37902 * Returns true if the dropdown list is expanded, else false.
37904 isExpanded : function(){
37905 return this.list.isVisible();
37909 * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.
37910 * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
37911 * @param {String} value The data value of the item to select
37912 * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
37913 * selected item if it is not currently in view (defaults to true)
37914 * @return {Boolean} True if the value matched an item in the list, else false
37916 selectByValue : function(v, O){
37917 if(v !== undefined && v !== null){
37918 var r = this.findRecord(this.valueField || this.displayField, v);
37920 this.select(this.store.indexOf(r), O);
37928 * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.
37929 * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
37930 * @param {Number} index The zero-based index of the list item to select
37931 * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
37932 * selected item if it is not currently in view (defaults to true)
37934 select : function(P, Q){
37935 this.selectedIndex = P;
37936 this.view.select(P);
37938 var el = this.view.getNode(P);
37940 this.innerList.scrollChildIntoView(el, false);
37946 selectNext : function(){
37947 var ct = this.store.getCount();
37949 if(this.selectedIndex == -1){
37951 }else if(this.selectedIndex < ct-1){
37952 this.select(this.selectedIndex+1);
37958 selectPrev : function(){
37959 var ct = this.store.getCount();
37961 if(this.selectedIndex == -1){
37963 }else if(this.selectedIndex != 0){
37964 this.select(this.selectedIndex-1);
37970 onKeyUp : function(e){
37971 if(this.editable !== false && !e.isSpecialKey()){
37972 this.lastKey = e.getKey();
37973 this.dqTask.delay(this.queryDelay);
37978 validateBlur : function(){
37979 return !this.list || !this.list.isVisible();
37983 initQuery : function(){
37984 this.doQuery(this.getRawValue());
37988 doForce : function(){
37989 if(this.el.dom.value.length > 0){
37990 this.el.dom.value =
37991 this.lastSelectionText === undefined ? '' : this.lastSelectionText;
37992 this.applyEmptyText();
37997 * Execute a query to filter the dropdown list. Fires the beforequery event prior to performing the
37998 * query allowing the query action to be canceled if needed.
37999 * @param {String} query The SQL query to execute
38000 * @param {Boolean} forceAll True to force the query to execute even if there are currently fewer characters
38001 * in the field than the minimum specified by the minChars config option. It also clears any filter previously
38002 * saved in the current store (defaults to false)
38004 doQuery : function(q, R){
38005 if(q === undefined || q === null){
38014 if(this.fireEvent('beforequery', qe)===false || qe.cancel){
38020 if(R === true || (q.length >= this.minChars)){
38021 if(this.lastQuery != q){
38022 this.lastQuery = q;
38023 if(this.mode == 'local'){
38024 this.selectedIndex = -1;
38026 this.store.clearFilter();
38028 this.store.filter(this.displayField, q);
38033 this.store.baseParams[this.queryParam] = q;
38035 params: this.getParams(q)
38040 this.selectedIndex = -1;
38047 getParams : function(q){
38049 //p[this.queryParam] = q;
38052 p.limit = this.pageSize;
38058 * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion.
38060 collapse : function(){
38061 if(!this.isExpanded()){
38066 Roo.get(document).un('mousedown', this.collapseIf, this);
38067 Roo.get(document).un('mousewheel', this.collapseIf, this);
38068 this.fireEvent('collapse', this);
38072 collapseIf : function(e){
38073 if(!e.within(this.wrap) && !e.within(this.list)){
38079 * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion.
38081 expand : function(){
38082 if(this.isExpanded() || !this.hasFocus){
38086 this.list.alignTo(this.el, this.listAlign);
38088 Roo.get(document).on('mousedown', this.collapseIf, this);
38089 Roo.get(document).on('mousewheel', this.collapseIf, this);
38090 this.fireEvent('expand', this);
38094 // Implements the default empty TriggerField.onTriggerClick function
38095 onTriggerClick : function(){
38099 if(this.isExpanded()){
38101 if (!this.blockFocus) {
38106 this.hasFocus = true;
38107 if(this.triggerAction == 'all') {
38108 this.doQuery(this.allQuery, true);
38110 this.doQuery(this.getRawValue());
38112 if (!this.blockFocus) {
38119 * @cfg {Boolean} grow
38123 * @cfg {Number} growMin
38127 * @cfg {Number} growMax
38137 * Ext JS Library 1.1.1
38138 * Copyright(c) 2006-2007, Ext JS, LLC.
38140 * Originally Released Under LGPL - original licence link has changed is not relivant.
38143 * <script type="text/javascript">
38146 * @class Roo.form.Checkbox
38147 * @extends Roo.form.Field
38148 * Single checkbox field. Can be used as a direct replacement for traditional checkbox fields.
38150 * Creates a new Checkbox
38151 * @param {Object} config Configuration options
38153 Roo.form.Checkbox = function(A){
38154 Roo.form.Checkbox.superclass.constructor.call(this, A);
38158 * Fires when the checkbox is checked or unchecked.
38159 * @param {Roo.form.Checkbox} this This checkbox
38160 * @param {Boolean} checked The new checked value
38166 Roo.extend(Roo.form.Checkbox, Roo.form.Field, {
38168 * @cfg {String} focusClass The CSS class to use when the checkbox receives focus (defaults to undefined)
38170 focusClass : undefined,
38172 * @cfg {String} fieldClass The default CSS class for the checkbox (defaults to "x-form-field")
38174 fieldClass: "x-form-field",
38176 * @cfg {Boolean} checked True if the the checkbox should render already checked (defaults to false)
38180 * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
38181 * {tag: "input", type: "checkbox", autocomplete: "off"})
38183 defaultAutoCreate : { tag: "input", type: 'hidden', autocomplete: "off"},
38185 * @cfg {String} boxLabel The text that appears beside the checkbox
38189 * @cfg {String} inputValue The value that should go into the generated input element's value attribute
38193 * @cfg {String} valueOff The value that should go into the generated input element's value when unchecked.
38195 valueOff: '0', // value when not checked..
38197 actionMode : 'viewEl',
38200 itemCls : 'x-menu-check-item x-form-item',
38201 groupClass : 'x-menu-group-item',
38202 inputType : 'hidden',
38205 inSetChecked: false, // check that we are not calling self...
38207 inputElement: false, // real input element?
38208 basedOn: false, // ????
38210 isFormField: true, // not sure where this is needed!!!!
38212 onResize : function(){
38213 Roo.form.Checkbox.superclass.onResize.apply(this, arguments);
38214 if(!this.boxLabel){
38215 this.el.alignTo(this.wrap, 'c-c');
38219 initEvents : function(){
38220 Roo.form.Checkbox.superclass.initEvents.call(this);
38221 this.el.on("click", this.onClick, this);
38222 this.el.on("change", this.onClick, this);
38226 getResizeEl : function(){
38230 getPositionEl : function(){
38235 onRender : function(ct, B){
38236 Roo.form.Checkbox.superclass.onRender.call(this, ct, B);
38238 if(this.inputValue !== undefined){
38239 this.el.dom.value = this.inputValue;
38242 //this.wrap = this.el.wrap({cls: "x-form-check-wrap"});
38243 this.wrap = this.el.wrap({cls: 'x-menu-check-item '});
38244 var C = this.wrap.createChild({
38245 tag: 'img', cls: 'x-menu-item-icon', style: 'margin: 0px;' ,src : Roo.BLANK_IMAGE_URL });
38247 this.wrap.on('click', this.onClick, this);
38249 this.el.on('DOMAttrModified', this.setFromHidden, this); //ff
38250 this.el.on('propertychange', this.setFromHidden, this); //ie
38255 this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
38256 // viewEl.on('click', this.onClick, this);
38259 //if(this.checked){
38260 this.setChecked(this.checked);
38262 //this.checked = this.el.dom;
38268 initValue : Roo.emptyFn,
38271 * Returns the checked state of the checkbox.
38272 * @return {Boolean} True if checked, else false
38274 getValue : function(){
38276 return String(this.el.dom.value) == String(this.inputValue ) ? this.inputValue : this.valueOff;
38278 return this.valueOff;
38283 onClick : function(){
38284 this.setChecked(!this.checked);
38286 //if(this.el.dom.checked != this.checked){
38287 // this.setValue(this.el.dom.checked);
38292 * Sets the checked state of the checkbox.
38293 * @param {Boolean/String} checked True, 'true', '1', or 'on' to check the checkbox, any other value will uncheck it.
38295 setValue : function(v,D){
38296 //this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
38297 //if(this.el && this.el.dom){
38298 // this.el.dom.checked = this.checked;
38299 // this.el.dom.defaultChecked = this.checked;
38301 this.setChecked(v === this.inputValue);
38302 //this.fireEvent("check", this, this.checked);
38305 setChecked : function(E,F)
38307 if (this.inSetChecked) {
38314 this.wrap[E ? 'addClass' : 'removeClass']('x-menu-item-checked');
38319 this.fireEvent('checkchange', this, E);
38322 this.inSetChecked = true;
38323 this.el.dom.value = E ? this.inputValue : this.valueOff;
38324 this.inSetChecked = false;
38327 // handle setting of hidden value by some other method!!?!?
38328 setFromHidden: function()
38334 //console.log("SET FROM HIDDEN");
38335 //alert('setFrom hidden');
38336 this.setValue(this.el.dom.value);
38339 onDestroy : function()
38342 Roo.get(this.viewEl).remove();
38346 Roo.form.Checkbox.superclass.onDestroy.call(this);
38352 * Ext JS Library 1.1.1
38353 * Copyright(c) 2006-2007, Ext JS, LLC.
38355 * Originally Released Under LGPL - original licence link has changed is not relivant.
38358 * <script type="text/javascript">
38362 * @class Roo.form.Radio
38363 * @extends Roo.form.Checkbox
38364 * Single radio field. Same as Checkbox, but provided as a convenience for automatically setting the input type.
38365 * Radio grouping is handled automatically by the browser if you give each radio in a group the same name.
38367 * Creates a new Radio
38368 * @param {Object} config Configuration options
38370 Roo.form.Radio = function(){
38371 Roo.form.Radio.superclass.constructor.apply(this, arguments);
38373 Roo.extend(Roo.form.Radio, Roo.form.Checkbox, {
38374 inputType: 'radio',
38377 * If this radio is part of a group, it will return the selected value
38380 getGroupValue : function(){
38381 return this.el.up('form').child('input[name='+this.el.dom.name+']:checked', true).value;
38384 //<script type="text/javascript">
38387 * Ext JS Library 1.1.1
38388 * Copyright(c) 2006-2007, Ext JS, LLC.
38389 * licensing@extjs.com
38391 * http://www.extjs.com/license
38397 * Default CSS appears to render it as fixed text by default (should really be Sans-Serif)
38398 * - IE ? - no idea how much works there.
38406 * @class Ext.form.HtmlEditor
38407 * @extends Ext.form.Field
38408 * Provides a lightweight HTML Editor component.
38409 * WARNING - THIS CURRENTlY ONLY WORKS ON FIREFOX - USE FCKeditor for a cross platform version
38411 * <br><br><b>Note: The focus/blur and validation marking functionality inherited from Ext.form.Field is NOT
38412 * supported by this editor.</b><br/><br/>
38413 * An Editor is a sensitive component that can't be used in all spots standard fields can be used. Putting an Editor within
38414 * any element that has display set to 'none' can cause problems in Safari and Firefox.<br/><br/>
38416 Roo.form.HtmlEditor = Roo.extend(Roo.form.Field, {
38418 * @cfg {Array} toolbars Array of toolbars. - defaults to just the Standard one
38422 * @cfg {String} createLinkText The default text for the create link prompt
38424 createLinkText : 'Please enter the URL for the link:',
38426 * @cfg {String} defaultLinkValue The default value for the create link prompt (defaults to http:/ /)
38428 defaultLinkValue : 'http:/'+'/',
38434 // private properties
38435 validationEvent : false,
38437 initialized : false,
38439 sourceEditMode : false,
38440 onFocus : Roo.emptyFn,
38442 hideMode:'offsets',
38443 defaultAutoCreate : {
38445 style:"width:500px;height:300px;",
38446 autocomplete: "off"
38450 initComponent : function(){
38453 * @event initialize
38454 * Fires when the editor is fully initialized (including the iframe)
38455 * @param {HtmlEditor} this
38460 * Fires when the editor is first receives the focus. Any insertion must wait
38461 * until after this event.
38462 * @param {HtmlEditor} this
38466 * @event beforesync
38467 * Fires before the textarea is updated with content from the editor iframe. Return false
38468 * to cancel the sync.
38469 * @param {HtmlEditor} this
38470 * @param {String} html
38474 * @event beforepush
38475 * Fires before the iframe editor is updated with content from the textarea. Return false
38476 * to cancel the push.
38477 * @param {HtmlEditor} this
38478 * @param {String} html
38483 * Fires when the textarea is updated with content from the editor iframe.
38484 * @param {HtmlEditor} this
38485 * @param {String} html
38490 * Fires when the iframe editor is updated with content from the textarea.
38491 * @param {HtmlEditor} this
38492 * @param {String} html
38496 * @event editmodechange
38497 * Fires when the editor switches edit modes
38498 * @param {HtmlEditor} this
38499 * @param {Boolean} sourceEdit True if source edit, false if standard editing.
38501 editmodechange: true,
38503 * @event editorevent
38504 * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
38505 * @param {HtmlEditor} this
38512 * Protected method that will not generally be called directly. It
38513 * is called when the editor creates its toolbar. Override this method if you need to
38514 * add custom toolbar buttons.
38515 * @param {HtmlEditor} editor
38517 createToolbar : function(A){
38518 if (!A.toolbars || !A.toolbars.length) {
38519 A.toolbars = [ new Roo.form.HtmlEditor.ToolbarStandard() ]; // can be empty?
38522 for (var i =0 ; i < A.toolbars.length;i++) {
38523 A.toolbars[i].init(A);
38530 * Protected method that will not generally be called directly. It
38531 * is called when the editor initializes the iframe with HTML contents. Override this method if you
38532 * want to change the initialization markup of the iframe (e.g. to add stylesheets).
38534 getDocMarkup : function(){
38535 return '<html><head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;}</style></head><body></body></html>';
38539 onRender : function(ct, B){
38540 Roo.form.HtmlEditor.superclass.onRender.call(this, ct, B);
38541 this.el.dom.style.border = '0 none';
38542 this.el.dom.setAttribute('tabIndex', -1);
38543 this.el.addClass('x-hidden');
38544 if(Roo.isIE){ // fix IE 1px bogus margin
38545 this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;')
38548 this.wrap = this.el.wrap({
38549 cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
38552 this.frameId = Roo.id();
38553 this.createToolbar(this);
38560 var C = this.wrap.createChild({
38563 name: this.frameId,
38564 frameBorder : 'no',
38565 'src' : Roo.SSL_SECURE_URL ? Roo.SSL_SECURE_URL : "javascript:false"
38568 // console.log(iframe);
38569 //this.wrap.dom.appendChild(iframe);
38571 this.iframe = C.dom;
38573 this.assignDocWin();
38575 this.doc.designMode = 'on';
38578 this.doc.write(this.getDocMarkup());
38582 var D = { // must defer to wait for browser to be ready
38584 //console.log("run task?" + this.doc.readyState);
38585 this.assignDocWin();
38586 if(this.doc.body || this.doc.readyState == 'complete'){
38590 this.doc.designMode="on";
38595 Roo.TaskMgr.stop(D);
38596 this.initEditor.defer(10, this);
38603 Roo.TaskMgr.start(D);
38606 this.setSize(this.el.getSize());
38611 onResize : function(w, h){
38612 Roo.form.HtmlEditor.superclass.onResize.apply(this, arguments);
38613 if(this.el && this.iframe){
38614 if(typeof w == 'number'){
38615 var aw = w - this.wrap.getFrameWidth('lr');
38616 this.el.setWidth(this.adjustWidth('textarea', aw));
38617 this.iframe.style.width = aw + 'px';
38619 if(typeof h == 'number'){
38621 for (var i =0; i < this.toolbars.length;i++) {
38622 // fixme - ask toolbars for heights?
38623 tbh += this.toolbars[i].tb.el.getHeight();
38629 var ah = h - this.wrap.getFrameWidth('tb') - tbh;// this.tb.el.getHeight();
38630 this.el.setHeight(this.adjustWidth('textarea', ah));
38631 this.iframe.style.height = ah + 'px';
38633 (this.doc.body || this.doc.documentElement).style.height = (ah - (this.iframePad*2)) + 'px';
38640 * Toggles the editor between standard and source edit mode.
38641 * @param {Boolean} sourceEdit (optional) True for source edit, false for standard
38643 toggleSourceEdit : function(E){
38645 this.sourceEditMode = E === true;
38647 if(this.sourceEditMode){
38650 this.iframe.className = 'x-hidden';
38651 this.el.removeClass('x-hidden');
38652 this.el.dom.removeAttribute('tabIndex');
38657 this.iframe.className = '';
38658 this.el.addClass('x-hidden');
38659 this.el.dom.setAttribute('tabIndex', -1);
38663 this.setSize(this.wrap.getSize());
38664 this.fireEvent('editmodechange', this, this.sourceEditMode);
38667 // private used internally
38668 createLink : function(){
38669 var F = prompt(this.createLinkText, this.defaultLinkValue);
38670 if(F && F != 'http:/'+'/'){
38671 this.relayCmd('createlink', F);
38675 // private (for BoxComponent)
38676 adjustSize : Roo.BoxComponent.prototype.adjustSize,
38678 // private (for BoxComponent)
38679 getResizeEl : function(){
38683 // private (for BoxComponent)
38684 getPositionEl : function(){
38689 initEvents : function(){
38690 this.originalValue = this.getValue();
38694 * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
38697 markInvalid : Roo.emptyFn,
38699 * Overridden and disabled. The editor element does not support standard valid/invalid marking. @hide
38702 clearInvalid : Roo.emptyFn,
38704 setValue : function(v){
38705 Roo.form.HtmlEditor.superclass.setValue.call(this, v);
38710 * Protected method that will not generally be called directly. If you need/want
38711 * custom HTML cleanup, this is the method you should override.
38712 * @param {String} html The HTML to be cleaned
38713 * return {String} The cleaned HTML
38715 cleanHtml : function(G){
38718 if(Roo.isSafari){ // strip safari nonsense
38719 G = G.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
38729 * Protected method that will not generally be called directly. Syncs the contents
38730 * of the editor iframe with the textarea.
38732 syncValue : function(){
38733 if(this.initialized){
38734 var bd = (this.doc.body || this.doc.documentElement);
38735 var G = bd.innerHTML;
38737 var bs = bd.getAttribute('style'); // Safari puts text-align styles on the body element!
38738 var m = bs.match(/text-align:(.*?);/i);
38740 G = '<div style="'+m[0]+'">' + G + '</div>';
38744 G = this.cleanHtml(G);
38745 if(this.fireEvent('beforesync', this, G) !== false){
38746 this.el.dom.value = G;
38747 this.fireEvent('sync', this, G);
38753 * Protected method that will not generally be called directly. Pushes the value of the textarea
38754 * into the iframe editor.
38756 pushValue : function(){
38757 if(this.initialized){
38758 var v = this.el.dom.value;
38762 if(this.fireEvent('beforepush', this, v) !== false){
38763 (this.doc.body || this.doc.documentElement).innerHTML = v;
38764 this.fireEvent('push', this, v);
38770 deferFocus : function(){
38771 this.focus.defer(10, this);
38775 focus : function(){
38776 if(this.win && !this.sourceEditMode){
38783 assignDocWin: function()
38785 var H = this.iframe;
38788 this.doc = H.contentWindow.document;
38789 this.win = H.contentWindow;
38791 this.doc = (H.contentDocument || Roo.get(this.frameId).dom.document);
38792 this.win = Roo.get(this.frameId).dom.contentWindow;
38797 initEditor : function(){
38798 //console.log("INIT EDITOR");
38799 this.assignDocWin();
38803 this.doc.designMode="on";
38805 this.doc.write(this.getDocMarkup());
38808 var I = (this.doc.body || this.doc.documentElement);
38809 //var ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat');
38810 // this copies styles from the containing element into thsi one..
38811 // not sure why we need all of this..
38812 var ss = this.el.getStyles('font-size', 'background-image', 'background-repeat');
38813 ss['background-attachment'] = 'fixed'; // w3c
38814 I.bgProperties = 'fixed'; // ie
38815 Roo.DomHelper.applyStyles(I, ss);
38816 Roo.EventManager.on(this.doc, {
38817 'mousedown': this.onEditorEvent,
38818 'dblclick': this.onEditorEvent,
38819 'click': this.onEditorEvent,
38820 'keyup': this.onEditorEvent,
38825 Roo.EventManager.on(this.doc, 'keypress', this.applyCommand, this);
38827 if(Roo.isIE || Roo.isSafari || Roo.isOpera){
38828 Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
38831 this.initialized = true;
38833 this.fireEvent('initialize', this);
38838 onDestroy : function(){
38844 for (var i =0; i < this.toolbars.length;i++) {
38845 // fixme - ask toolbars for heights?
38846 this.toolbars[i].onDestroy();
38850 this.wrap.dom.innerHTML = '';
38851 this.wrap.remove();
38856 onFirstFocus : function(){
38858 this.assignDocWin();
38861 this.activated = true;
38862 for (var i =0; i < this.toolbars.length;i++) {
38863 this.toolbars[i].onFirstFocus();
38866 if(Roo.isGecko){ // prevent silly gecko errors
38868 var s = this.win.getSelection();
38869 if(!s.focusNode || s.focusNode.nodeType != 3){
38870 var r = s.getRangeAt(0);
38871 r.selectNodeContents((this.doc.body || this.doc.documentElement));
38876 this.execCmd('useCSS', true);
38877 this.execCmd('styleWithCSS', false);
38881 this.fireEvent('activate', this);
38885 adjustFont: function(J){
38886 var K = J.cmd == 'increasefontsize' ? 1 : -1;
38887 //if(Roo.isSafari){ // safari
38890 var v = parseInt(this.doc.queryCommandValue('FontSize')|| 3, 10);
38891 if(Roo.isSafari){ // safari
38892 var sm = { 10 : 1, 13: 2, 16:3, 18:4, 24: 5, 32:6, 48: 7 };
38893 v = (v < 10) ? 10 : v;
38894 v = (v > 48) ? 48 : v;
38895 v = typeof(sm[v]) == 'undefined' ? 1 : sm[v];
38901 v = Math.max(1, v+K);
38903 this.execCmd('FontSize', v );
38906 onEditorEvent : function(e){
38907 this.fireEvent('editorevent', this, e);
38908 // this.updateToolbar();
38912 insertTag : function(tg)
38914 // could be a bit smarter... -> wrap the current selected tRoo..
38916 this.execCmd("formatblock", tg);
38920 insertText : function(L)
38924 range = this.createRange();
38925 range.deleteContents();
38926 //alert(Sender.getAttribute('label'));
38928 range.insertNode(this.doc.createTextNode(L));
38932 relayBtnCmd : function(M){
38933 this.relayCmd(M.cmd);
38937 * Executes a Midas editor command on the editor document and performs necessary focus and
38938 * toolbar updates. <b>This should only be called after the editor is initialized.</b>
38939 * @param {String} cmd The Midas command
38940 * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
38942 relayCmd : function(N, O){
38944 this.execCmd(N, O);
38945 this.fireEvent('editorevent', this);
38946 //this.updateToolbar();
38951 * Executes a Midas editor command directly on the editor document.
38952 * For visual commands, you should use {@link #relayCmd} instead.
38953 * <b>This should only be called after the editor is initialized.</b>
38954 * @param {String} cmd The Midas command
38955 * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
38957 execCmd : function(P, Q){
38958 this.doc.execCommand(P, false, Q === undefined ? null : Q);
38963 applyCommand : function(e){
38965 var c = e.getCharCode(), P;
38967 c = String.fromCharCode(c);
38983 e.preventDefault();
38990 * Inserts the passed text at the current cursor position. Note: the editor must be initialized and activated
38992 * @param {String} text
38994 insertAtCursor : function(R){
38995 if(!this.activated){
39000 var r = this.doc.selection.createRange();
39007 }else if(Roo.isGecko || Roo.isOpera){
39009 this.execCmd('InsertHTML', R);
39011 }else if(Roo.isSafari){
39012 this.execCmd('InsertText', R);
39018 fixKeys : function(){ // load time branching for fastest keydown performance
39020 return function(e){
39021 var k = e.getKey(), r;
39024 r = this.doc.selection.createRange();
39027 r.pasteHTML('    ');
39030 }else if(k == e.ENTER){
39031 r = this.doc.selection.createRange();
39033 var target = r.parentElement();
39034 if(!target || target.tagName.toLowerCase() != 'li'){
39036 r.pasteHTML('<br />');
39043 }else if(Roo.isOpera){
39044 return function(e){
39045 var k = e.getKey();
39049 this.execCmd('InsertHTML','    ');
39053 }else if(Roo.isSafari){
39054 return function(e){
39055 var k = e.getKey();
39058 this.execCmd('InsertText','\t');
39065 getAllAncestors: function()
39067 var p = this.getSelectedNode();
39070 a.push(p); // push blank onto stack..
39071 p = this.getParentElement();
39075 while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
39080 a.push(this.doc.body);
39084 lastSelNode : false,
39087 getSelection : function()
39089 this.assignDocWin();
39090 return Roo.isIE ? this.doc.selection : this.win.getSelection();
39093 getSelectedNode: function()
39095 // this may only work on Gecko!!!
39097 // should we cache this!!!!
39102 var S = this.createRange(this.getSelection());
39105 var parent = S.parentElement();
39107 var testRange = S.duplicate();
39108 testRange.moveToElementText(parent);
39109 if (testRange.inRange(S)) {
39112 if ((parent.nodeType != 1) || (parent.tagName.toLowerCase() == 'body')) {
39116 parent = parent.parentElement;
39122 var ar = S.endContainer.childNodes;
39124 ar = S.commonAncestorContainer.childNodes;
39125 //alert(ar.length);
39130 for (var i=0;i<ar.length;i++) {
39131 if ((ar[i].nodeType == 3) && (!ar[i].data.length)) { // empty text ?
39134 // fullly contained node.
39136 if (this.rangeIntersectsNode(S,ar[i]) && this.rangeCompareNode(S,ar[i]) == 3) {
39141 // probably selected..
39142 if ((ar[i].nodeType == 1) && this.rangeIntersectsNode(S,ar[i]) && (this.rangeCompareNode(S,ar[i]) > 0)) {
39146 if (!this.rangeIntersectsNode(S,ar[i])|| (this.rangeCompareNode(S,ar[i]) == 0)) {
39154 if (!T.length && U.length) {
39157 if (V || !T.length || (T.length > 1)) {
39163 createRange: function(W)
39165 // this has strange effects when using with
39166 // top toolbar - not sure if it's a great idea.
39167 //this.editor.contentWindow.focus();
39168 if (typeof W != "undefined") {
39170 return W.getRangeAt ? W.getRangeAt(0) : W.createRange();
39172 return this.doc.createRange();
39175 return this.doc.createRange();
39178 getParentElement: function()
39181 this.assignDocWin();
39182 var X = Roo.isIE ? this.doc.selection : this.win.getSelection();
39184 var Y = this.createRange(X);
39187 var p = Y.commonAncestorContainer;
39188 while (p.nodeType == 3) { // text node
39200 // BC Hacks - cause I cant work out what i was trying to do..
39201 rangeIntersectsNode : function(Z, b)
39203 var d = b.ownerDocument.createRange();
39208 nodeRange.selectNodeContents(node);
39211 return Z.compareBoundaryPoints(Range.END_TO_START, d) == -1 &&
39212 Z.compareBoundaryPoints(Range.START_TO_END, d) == 1;
39214 rangeCompareNode : function(f, g) {
39215 var j = g.ownerDocument.createRange();
39219 nodeRange.selectNodeContents(node);
39221 var k = f.compareBoundaryPoints(Range.START_TO_START, j) == 1;
39222 var l = f.compareBoundaryPoints(Range.END_TO_END, j) == -1;
39236 // hide stuff that is not compatible
39250 * @event specialkey
39254 * @cfg {String} fieldClass @hide
39257 * @cfg {String} focusClass @hide
39260 * @cfg {String} autoCreate @hide
39263 * @cfg {String} inputType @hide
39266 * @cfg {String} invalidClass @hide
39269 * @cfg {String} invalidText @hide
39272 * @cfg {String} msgFx @hide
39275 * @cfg {String} validateOnBlur @hide
39278 // <script type="text/javascript">
39281 * Ext JS Library 1.1.1
39282 * Copyright(c) 2006-2007, Ext JS, LLC.
39288 * @class Roo.form.HtmlEditorToolbar1
39293 new Roo.form.HtmlEditor({
39296 new Roo.form.HtmlEditorToolbar1({
39297 disable : { fonts: 1 , format: 1, ..., ... , ...],
39303 * @cfg {Object} disable List of elements to disable..
39304 * @cfg {Array} btns List of additional buttons.
39308 * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
39311 Roo.form.HtmlEditor.ToolbarStandard = function(A)
39314 Roo.apply(this, A);
39315 //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
39316 // dont call parent... till later.
39320 Roo.apply(Roo.form.HtmlEditor.ToolbarStandard.prototype, {
39328 * @cfg {Object} disable List of toolbar elements to disable
39333 * @cfg {Array} fontFamilies An array of available font families
39351 // "á" , ?? a acute?
39356 "°" // , // degrees
39358 // "é" , // e ecute
39359 // "ú" , // u ecute?
39362 "form", "input:text", "input:hidden", "input:checkbox", "input:radio", "input:password",
39363 "input:submit", "input:button", "select", "textarea", "label" ],
39366 ["h1"],["h2"],["h3"],["h4"],["h5"],["h6"],
39368 ["abbr"],[ "acronym"],[ "address"],[ "cite"],[ "samp"],[ "var"]
39371 * @cfg {String} defaultFont default font to use.
39373 defaultFont: 'tahoma',
39375 fontSelect : false,
39378 formatCombo : false,
39387 function E(id, G, H){
39388 var I = C + '-'+ id ;
39392 cls : 'x-btn-icon x-edit-'+id,
39393 enableToggle:G !== false,
39394 scope: B, // was editor...
39395 handler:H||B.relayBtnCmd,
39396 clickEvent:'mousedown',
39397 tooltip: D.buttonTips[id] || undefined, ///tips ???
39404 var tb = new Roo.Toolbar(B.wrap.dom.firstChild);
39406 // stop form submits
39407 tb.el.on('click', function(e){
39408 e.preventDefault(); // what does this do?
39411 if(!this.disable.font && !Roo.isSafari){
39412 /* why no safari for fonts
39413 editor.fontSelect = tb.el.createChild({
39416 cls:'x-font-select',
39417 html: editor.createFontOptions()
39419 editor.fontSelect.on('change', function(){
39420 var font = editor.fontSelect.dom.value;
39421 editor.relayCmd('fontname', font);
39422 editor.deferFocus();
39425 editor.fontSelect.dom,
39430 if(!this.disable.formats){
39431 this.formatCombo = new Roo.form.ComboBox({
39432 store: new Roo.data.SimpleStore({
39435 data : this.formats // from states.js
39438 //autoCreate : {tag: "div", size: "20"},
39439 displayField:'tag',
39443 triggerAction: 'all',
39444 emptyText:'Add tag',
39445 selectOnFocus:true,
39448 'select': function(c, r, i) {
39449 B.insertTag(r.get('tag'));
39455 tb.addField(this.formatCombo);
39459 if(!this.disable.format){
39466 if(!this.disable.fontSize){
39471 E('increasefontsize', false, B.adjustFont),
39472 E('decreasefontsize', false, B.adjustFont)
39477 if(this.disable.colors){
39480 id:B.frameId +'-forecolor',
39481 cls:'x-btn-icon x-edit-forecolor',
39482 clickEvent:'mousedown',
39483 tooltip: this.buttonTips['forecolor'] || undefined,
39485 menu : new Roo.menu.ColorMenu({
39486 allowReselect: true,
39487 focus: Roo.emptyFn,
39490 selectHandler: function(cp, G){
39491 B.execCmd('forecolor', Roo.isSafari || Roo.isIE ? '#'+G : G);
39495 clickEvent:'mousedown'
39498 id:B.frameId +'backcolor',
39499 cls:'x-btn-icon x-edit-backcolor',
39500 clickEvent:'mousedown',
39501 tooltip: this.buttonTips['backcolor'] || undefined,
39503 menu : new Roo.menu.ColorMenu({
39504 focus: Roo.emptyFn,
39507 allowReselect: true,
39508 selectHandler: function(cp, H){
39510 B.execCmd('useCSS', false);
39511 B.execCmd('hilitecolor', H);
39512 B.execCmd('useCSS', true);
39515 B.execCmd(Roo.isOpera ? 'hilitecolor' : 'backcolor',
39516 Roo.isSafari || Roo.isIE ? '#'+H : H);
39521 clickEvent:'mousedown'
39526 // now add all the items...
39529 if(!this.disable.alignments){
39533 E('justifycenter'),
39538 //if(!Roo.isSafari){
39539 if(!this.disable.links){
39542 E('createlink', false, B.createLink) /// MOVE TO HERE?!!?!?!?!
39546 if(!this.disable.lists){
39549 E('insertorderedlist'),
39550 E('insertunorderedlist')
39553 if(!this.disable.sourceEdit){
39556 E('sourceedit', true, function(G){
39557 this.toggleSourceEdit(G.pressed);
39564 // special menu.. - needs to be tidied up..
39565 if (!this.disable.special) {
39568 cls: 'x-edit-none',
39573 for (var i =0; i < this.specialChars.length; i++) {
39574 F.menu.items.push({
39576 text: this.specialChars[i],
39577 handler: function(a,b) {
39578 B.insertAtCursor(String.fromCharCode(a.text.replace('&#','').replace(';', '')));
39591 for(var i =0; i< this.btns.length;i++) {
39592 var b = this.btns[i];
39593 b.cls = 'x-edit-none';
39603 // disable everything...
39605 this.tb.items.each(function(G){
39606 if(G.id != B.frameId+ '-sourceedit'){
39610 this.rendered = true;
39612 // the all the btns;
39613 B.on('editorevent', this.updateToolbar, this);
39614 // other toolbars need to implement this..
39615 //editor.on('editmodechange', this.updateToolbar, this);
39621 * Protected method that will not generally be called directly. It triggers
39622 * a toolbar update by reading the markup state of the current selection in the editor.
39624 updateToolbar: function(){
39626 if(!this.editor.activated){
39627 this.editor.onFirstFocus();
39631 var G = this.tb.items.map,
39632 H = this.editor.doc,
39633 I = this.editor.frameId;
39635 if(!this.disable.font && !Roo.isSafari){
39637 var name = (doc.queryCommandValue('FontName')||this.editor.defaultFont).toLowerCase();
39638 if(name != this.fontSelect.dom.value){
39639 this.fontSelect.dom.value = name;
39643 if(!this.disable.format){
39644 G[I + '-bold'].toggle(H.queryCommandState('bold'));
39645 G[I + '-italic'].toggle(H.queryCommandState('italic'));
39646 G[I + '-underline'].toggle(H.queryCommandState('underline'));
39648 if(!this.disable.alignments){
39649 G[I + '-justifyleft'].toggle(H.queryCommandState('justifyleft'));
39650 G[I + '-justifycenter'].toggle(H.queryCommandState('justifycenter'));
39651 G[I + '-justifyright'].toggle(H.queryCommandState('justifyright'));
39653 if(!Roo.isSafari && !this.disable.lists){
39654 G[I + '-insertorderedlist'].toggle(H.queryCommandState('insertorderedlist'));
39655 G[I + '-insertunorderedlist'].toggle(H.queryCommandState('insertunorderedlist'));
39658 var J = this.editor.getAllAncestors();
39659 if (this.formatCombo) {
39662 var store = this.formatCombo.store;
39663 this.formatCombo.setValue("");
39664 for (var i =0; i < J.length;i++) {
39665 if (J[i] && store.query('tag',J[i].tagName.toLowerCase(), true).length) {
39667 this.formatCombo.setValue(J[i].tagName.toLowerCase());
39676 // hides menus... - so this cant be on a menu...
39677 Roo.menu.MenuMgr.hideAll();
39679 //this.editorsyncValue();
39683 createFontOptions : function(){
39684 var K = [], fs = this.fontFamilies, ff, lc;
39685 for(var i = 0, len = fs.length; i< len; i++){
39687 lc = ff.toLowerCase();
39689 '<option value="',lc,'" style="font-family:',ff,';"',
39690 (this.defaultFont == lc ? ' selected="true">' : '>'),
39698 toggleSourceEdit : function(L){
39699 if(L === undefined){
39700 L = !this.sourceEditMode;
39703 this.sourceEditMode = L === true;
39704 var M = this.tb.items.get(this.editor.frameId +'-sourceedit');
39705 // just toggle the button?
39706 if(M.pressed !== this.editor.sourceEditMode){
39707 M.toggle(this.editor.sourceEditMode);
39711 if(this.sourceEditMode){
39712 this.tb.items.each(function(N){
39713 if(N.cmd != 'sourceedit'){
39719 if(this.initialized){
39720 this.tb.items.each(function(O){
39727 // tell the editor that it's been pressed..
39728 this.editor.toggleSourceEdit(L);
39732 * Object collection of toolbar tooltips for the buttons in the editor. The key
39733 * is the command id associated with that button and the value is a valid QuickTips object.
39738 title: 'Bold (Ctrl+B)',
39739 text: 'Make the selected text bold.',
39740 cls: 'x-html-editor-tip'
39743 title: 'Italic (Ctrl+I)',
39744 text: 'Make the selected text italic.',
39745 cls: 'x-html-editor-tip'
39753 title: 'Bold (Ctrl+B)',
39754 text: 'Make the selected text bold.',
39755 cls: 'x-html-editor-tip'
39758 title: 'Italic (Ctrl+I)',
39759 text: 'Make the selected text italic.',
39760 cls: 'x-html-editor-tip'
39763 title: 'Underline (Ctrl+U)',
39764 text: 'Underline the selected text.',
39765 cls: 'x-html-editor-tip'
39767 increasefontsize : {
39768 title: 'Grow Text',
39769 text: 'Increase the font size.',
39770 cls: 'x-html-editor-tip'
39772 decreasefontsize : {
39773 title: 'Shrink Text',
39774 text: 'Decrease the font size.',
39775 cls: 'x-html-editor-tip'
39778 title: 'Text Highlight Color',
39779 text: 'Change the background color of the selected text.',
39780 cls: 'x-html-editor-tip'
39783 title: 'Font Color',
39784 text: 'Change the color of the selected text.',
39785 cls: 'x-html-editor-tip'
39788 title: 'Align Text Left',
39789 text: 'Align text to the left.',
39790 cls: 'x-html-editor-tip'
39793 title: 'Center Text',
39794 text: 'Center text in the editor.',
39795 cls: 'x-html-editor-tip'
39798 title: 'Align Text Right',
39799 text: 'Align text to the right.',
39800 cls: 'x-html-editor-tip'
39802 insertunorderedlist : {
39803 title: 'Bullet List',
39804 text: 'Start a bulleted list.',
39805 cls: 'x-html-editor-tip'
39807 insertorderedlist : {
39808 title: 'Numbered List',
39809 text: 'Start a numbered list.',
39810 cls: 'x-html-editor-tip'
39813 title: 'Hyperlink',
39814 text: 'Make the selected text a hyperlink.',
39815 cls: 'x-html-editor-tip'
39818 title: 'Source Edit',
39819 text: 'Switch to source editing mode.',
39820 cls: 'x-html-editor-tip'
39824 onDestroy : function(){
39827 this.tb.items.each(function(N){
39829 N.menu.removeAll();
39831 N.menu.el.destroy();
39840 onFirstFocus: function() {
39841 this.tb.items.each(function(N){
39851 // <script type="text/javascript">
39854 * Ext JS Library 1.1.1
39855 * Copyright(c) 2006-2007, Ext JS, LLC.
39862 * @class Roo.form.HtmlEditor.ToolbarContext
39867 new Roo.form.HtmlEditor({
39870 new Roo.form.HtmlEditor.ToolbarStandard(),
39871 new Roo.form.HtmlEditor.ToolbarContext()
39876 * @config : {Object} disable List of elements to disable.. (not done yet.)
39881 Roo.form.HtmlEditor.ToolbarContext = function(A)
39884 Roo.apply(this, A);
39885 //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
39886 // dont call parent... till later.
39889 Roo.form.HtmlEditor.ToolbarContext.types = {
39901 opts : [ [""],[ "left"],[ "right"],[ "center"],[ "top"]],
39963 opts : [[""],[ "left"],[ "center"],[ "right"],[ "justify"],[ "char"]],
39968 opts : [[""],[ "top"],[ "middle"],[ "bottom"],[ "baseline"]],
40032 Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype, {
40040 * @cfg {Object} disable List of toolbar elements to disable
40056 function E(id, G, H){
40057 var I = C + '-'+ id ;
40061 cls : 'x-btn-icon x-edit-'+id,
40062 enableToggle:G !== false,
40063 scope: B, // was editor...
40064 handler:H||B.relayBtnCmd,
40065 clickEvent:'mousedown',
40066 tooltip: D.buttonTips[id] || undefined, ///tips ???
40070 // create a new element.
40071 var F = B.wrap.createChild({
40073 }, B.wrap.dom.firstChild.nextSibling, true);
40075 // can we do this more than once??
40077 // stop form submits
40080 // disable everything...
40081 var ty= Roo.form.HtmlEditor.ToolbarContext.types;
40082 this.toolbars = {};
40084 for (var i in ty) {
40085 this.toolbars[i] = this.buildToolbar(ty[i],i);
40088 this.tb = this.toolbars.BODY;
40092 this.rendered = true;
40094 // the all the btns;
40095 B.on('editorevent', this.updateToolbar, this);
40096 // other toolbars need to implement this..
40097 //editor.on('editmodechange', this.updateToolbar, this);
40103 * Protected method that will not generally be called directly. It triggers
40104 * a toolbar update by reading the markup state of the current selection in the editor.
40106 updateToolbar: function(){
40108 if(!this.editor.activated){
40109 this.editor.onFirstFocus();
40114 var G = this.editor.getAllAncestors();
40117 var ty= Roo.form.HtmlEditor.ToolbarContext.types;
40118 var H = G.length ? (G[0] ? G[0] : G[1]) : this.editor.doc.body;
40119 H = H ? H : this.editor.doc.body;
40120 H = H.tagName.length ? H : this.editor.doc.body;
40121 var tn = H.tagName.toUpperCase();
40122 H = typeof(ty[tn]) != 'undefined' ? H : this.editor.doc.body;
40123 tn = H.tagName.toUpperCase();
40124 if (this.tb.name == tn) {
40125 return; // no change
40129 ///console.log("show: " + tn);
40130 this.tb = this.toolbars[tn];
40132 this.tb.fields.each(function(e) {
40133 e.setValue(H.getAttribute(e.name));
40135 this.tb.selectedNode = H;
40138 Roo.menu.MenuMgr.hideAll();
40140 //this.editorsyncValue();
40145 onDestroy : function(){
40148 this.tb.items.each(function(I){
40150 I.menu.removeAll();
40152 I.menu.el.destroy();
40161 onFirstFocus: function() {
40162 // need to do this for all the toolbars..
40163 this.tb.items.each(function(I){
40167 buildToolbar: function(I, nm)
40169 var J = this.editor;
40170 // create a new element.
40171 var K = J.wrap.createChild({
40173 }, J.wrap.dom.firstChild.nextSibling, true);
40176 var tb = new Roo.Toolbar(K);
40177 tb.add(nm+ ": ");
40180 tb.add(item.title + ": ");
40185 tb.addField( new Roo.form.ComboBox({
40186 store: new Roo.data.SimpleStore({
40189 data : item.opts // from states.js
40192 displayField:'val',
40196 triggerAction: 'all',
40197 emptyText:'Select',
40198 selectOnFocus:true,
40199 width: item.width ? item.width : 130,
40201 'select': function(c, r, i) {
40202 tb.selectedNode.setAttribute(c.name, r.get('val'));
40213 tb.addField( new Roo.form.TextField({
40216 //allowBlank:false,
40222 tb.addField( new Roo.form.TextField({
40228 'change' : function(f, nv, ov) {
40229 tb.selectedNode.setAttribute(f.name, nv);
40236 tb.el.on('click', function(e){
40237 e.preventDefault(); // what does this do?
40239 tb.el.setVisibilityMode( Roo.Element.DISPLAY);
40242 // dont need to disable them... as they will get hidden
40260 * Ext JS Library 1.1.1
40261 * Copyright(c) 2006-2007, Ext JS, LLC.
40263 * Originally Released Under LGPL - original licence link has changed is not relivant.
40266 * <script type="text/javascript">
40270 * @class Roo.form.BasicForm
40271 * @extends Roo.util.Observable
40272 * Supplies the functionality to do "actions" on forms and initialize Roo.form.Field types on existing markup.
40274 * @param {String/HTMLElement/Roo.Element} el The form element or its id
40275 * @param {Object} config Configuration options
40277 Roo.form.BasicForm = function(el, A){
40278 Roo.apply(this, A);
40280 * The Roo.form.Field items in this form.
40281 * @type MixedCollection
40283 this.items = new Roo.util.MixedCollection(false, function(o){
40284 return o.id || (o.id = Roo.id());
40288 * @event beforeaction
40289 * Fires before any action is performed. Return false to cancel the action.
40290 * @param {Form} this
40291 * @param {Action} action The action to be performed
40293 beforeaction: true,
40295 * @event actionfailed
40296 * Fires when an action fails.
40297 * @param {Form} this
40298 * @param {Action} action The action that failed
40300 actionfailed : true,
40302 * @event actioncomplete
40303 * Fires when an action is completed.
40304 * @param {Form} this
40305 * @param {Action} action The action that completed
40307 actioncomplete : true
40313 Roo.form.BasicForm.superclass.constructor.call(this);
40316 Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
40318 * @cfg {String} method
40319 * The request method to use (GET or POST) for form actions if one isn't supplied in the action options.
40322 * @cfg {DataReader} reader
40323 * An Roo.data.DataReader (e.g. {@link Roo.data.XmlReader}) to be used to read data when executing "load" actions.
40324 * This is optional as there is built-in support for processing JSON.
40327 * @cfg {DataReader} errorReader
40328 * An Roo.data.DataReader (e.g. {@link Roo.data.XmlReader}) to be used to read data when reading validation errors on "submit" actions.
40329 * This is completely optional as there is built-in support for processing JSON.
40332 * @cfg {String} url
40333 * The URL to use for form actions if one isn't supplied in the action options.
40336 * @cfg {Boolean} fileUpload
40337 * Set to true if this form is a file upload.
40340 * @cfg {Object} baseParams
40341 * Parameters to pass with all requests. e.g. baseParams: {id: '123', foo: 'bar'}.
40344 * @cfg {Number} timeout Timeout for form actions in seconds (default is 30 seconds).
40349 activeAction : null,
40352 * @cfg {Boolean} trackResetOnLoad If set to true, form.reset() resets to the last loaded
40353 * or setValues() data instead of when the form was first created.
40355 trackResetOnLoad : false,
40358 * By default wait messages are displayed with Roo.MessageBox.wait. You can target a specific
40359 * element by passing it or its id or mask the form itself by passing in true.
40362 waitMsgTarget : undefined,
40365 initEl : function(el){
40366 this.el = Roo.get(el);
40367 this.id = this.el.id || Roo.id();
40368 this.el.on('submit', this.onSubmit, this);
40369 this.el.addClass('x-form');
40373 onSubmit : function(e){
40378 * Returns true if client-side validation on the form is successful.
40381 isValid : function(){
40383 this.items.each(function(f){
40392 * Returns true if any fields in this form have changed since their original load.
40395 isDirty : function(){
40397 this.items.each(function(f){
40407 * Performs a predefined action (submit or load) or custom actions you define on this form.
40408 * @param {String} actionName The name of the action type
40409 * @param {Object} options (optional) The options to pass to the action. All of the config options listed
40410 * below are supported by both the submit and load actions unless otherwise noted (custom actions could also
40411 * accept other config options):
40413 Property Type Description
40414 ---------------- --------------- ----------------------------------------------------------------------------------
40415 url String The url for the action (defaults to the form's url)
40416 method String The form method to use (defaults to the form's method, or POST if not defined)
40417 params String/Object The params to pass (defaults to the form's baseParams, or none if not defined)
40418 clientValidation Boolean Applies to submit only. Pass true to call form.isValid() prior to posting to
40419 validate the form on the client (defaults to false)
40421 * @return {BasicForm} this
40423 doAction : function(D, E){
40424 if(typeof D == 'string'){
40425 D = new Roo.form.Action.ACTION_TYPES[D](this, E);
40427 if(this.fireEvent('beforeaction', this, D) !== false){
40428 this.beforeAction(D);
40429 D.run.defer(100, D);
40435 * Shortcut to do a submit action.
40436 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
40437 * @return {BasicForm} this
40439 submit : function(F){
40440 this.doAction('submit', F);
40445 * Shortcut to do a load action.
40446 * @param {Object} options The options to pass to the action (see {@link #doAction} for details)
40447 * @return {BasicForm} this
40449 load : function(G){
40450 this.doAction('load', G);
40455 * Persists the values in this form into the passed Roo.data.Record object in a beginEdit/endEdit block.
40456 * @param {Record} record The record to edit
40457 * @return {BasicForm} this
40459 updateRecord : function(H){
40462 fs.each(function(f){
40463 var I = this.findField(f.name);
40465 H.set(f.name, I.getValue());
40473 * Loads an Roo.data.Record into this form.
40474 * @param {Record} record The record to load
40475 * @return {BasicForm} this
40477 loadRecord : function(I){
40478 this.setValues(I.data);
40483 beforeAction : function(J){
40486 if(this.waitMsgTarget === true){
40487 this.el.mask(o.waitMsg, 'x-mask-loading');
40488 }else if(this.waitMsgTarget){
40489 this.waitMsgTarget = Roo.get(this.waitMsgTarget);
40490 this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
40492 Roo.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle || 'Please Wait...');
40498 afterAction : function(K, L){
40499 this.activeAction = null;
40502 if(this.waitMsgTarget === true){
40504 }else if(this.waitMsgTarget){
40505 this.waitMsgTarget.unmask();
40507 Roo.MessageBox.updateProgress(1);
40508 Roo.MessageBox.hide();
40516 Roo.callback(o.success, o.scope, [this, K]);
40517 this.fireEvent('actioncomplete', this, K);
40519 Roo.callback(o.failure, o.scope, [this, K]);
40520 this.fireEvent('actionfailed', this, K);
40525 * Find a Roo.form.Field in this form by id, dataIndex, name or hiddenName
40526 * @param {String} id The value to search for
40529 findField : function(id){
40530 var M = this.items.get(id);
40532 this.items.each(function(f){
40533 if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
40544 * Mark fields in this form invalid in bulk.
40545 * @param {Array/Object} errors Either an array in the form [{id:'fieldId', msg:'The message'},...] or an object hash of {id: msg, id2: msg2}
40546 * @return {BasicForm} this
40548 markInvalid : function(N){
40549 if(N instanceof Array){
40550 for(var i = 0, len = N.length; i < len; i++){
40551 var fieldError = N[i];
40552 var f = this.findField(fieldError.id);
40554 f.markInvalid(fieldError.msg);
40560 if(typeof N[id] != 'function' && (M = this.findField(id))){
40561 M.markInvalid(N[id]);
40569 * Set values for fields in this form in bulk.
40570 * @param {Array/Object} values Either an array in the form [{id:'fieldId', value:'foo'},...] or an object hash of {id: value, id2: value2}
40571 * @return {BasicForm} this
40573 setValues : function(O){
40574 if(O instanceof Array){ // array of objects
40575 for(var i = 0, len = O.length; i < len; i++){
40577 var f = this.findField(v.id);
40579 f.setValue(v.value);
40580 if(this.trackResetOnLoad){
40581 f.originalValue = f.getValue();
40585 }else { // object hash
40588 if(typeof O[id] != 'function' && (M = this.findField(id))){
40590 if (M.setFromData &&
40593 // combos' with local stores can
40594 // be queried via setValue()
40595 // to set their value..
40596 (M.store && !M.store.isLocal)
40600 sd[M.valueField] = typeof(O[M.hiddenName]) == 'undefined' ? '' : O[M.hiddenName];
40601 sd[M.displayField] = typeof(O[M.name]) == 'undefined' ? '' : O[M.name];
40609 if(this.trackResetOnLoad){
40610 M.originalValue = M.getValue();
40619 * Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
40620 * they are returned as an array.
40621 * @param {Boolean} asString
40624 getValues : function(P){
40625 var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
40629 return Roo.urlDecode(fs);
40633 * Clears all invalid messages in this form.
40634 * @return {BasicForm} this
40636 clearInvalid : function(){
40637 this.items.each(function(f){
40644 * Resets this form.
40645 * @return {BasicForm} this
40647 reset : function(){
40648 this.items.each(function(f){
40655 * Add Roo.form components to this form.
40656 * @param {Field} field1
40657 * @param {Field} field2 (optional)
40658 * @param {Field} etc (optional)
40659 * @return {BasicForm} this
40662 this.items.addAll(Array.prototype.slice.call(arguments, 0));
40668 * Removes a field from the items collection (does NOT remove its markup).
40669 * @param {Field} field
40670 * @return {BasicForm} this
40672 remove : function(Q){
40673 this.items.remove(Q);
40678 * Looks at the fields in this form, checks them for an id attribute,
40679 * and calls applyTo on the existing dom element with that id.
40680 * @return {BasicForm} this
40682 render : function(){
40683 this.items.each(function(f){
40684 if(f.isFormField && !f.rendered && document.getElementById(f.id)){ // if the element exists
40692 * Calls {@link Ext#apply} for all fields in this form with the passed object.
40693 * @param {Object} values
40694 * @return {BasicForm} this
40696 applyToFields : function(o){
40697 this.items.each(function(f){
40704 * Calls {@link Ext#applyIf} for all field in this form with the passed object.
40705 * @param {Object} values
40706 * @return {BasicForm} this
40708 applyIfToFields : function(o){
40709 this.items.each(function(f){
40717 Roo.BasicForm = Roo.form.BasicForm;
40720 * Ext JS Library 1.1.1
40721 * Copyright(c) 2006-2007, Ext JS, LLC.
40723 * Originally Released Under LGPL - original licence link has changed is not relivant.
40726 * <script type="text/javascript">
40730 * @class Roo.form.Form
40731 * @extends Roo.form.BasicForm
40732 * Adds the ability to dynamically render forms with JavaScript to {@link Roo.form.BasicForm}.
40734 * @param {Object} config Configuration options
40736 Roo.form.Form = function(A){
40745 Roo.form.Form.superclass.constructor.call(this, null, A);
40746 this.url = this.url || this.action;
40748 this.root = new Roo.form.Layout(Roo.applyIf({
40753 this.active = this.root;
40755 * Array of all the buttons that have been added to this form via {@link addButton}
40759 this.allItems = [];
40762 * @event clientvalidation
40763 * If the monitorValid config option is true, this event fires repetitively to notify of valid state
40764 * @param {Form} this
40765 * @param {Boolean} valid true if the form has passed client-side validation
40767 clientvalidation: true,
40770 * Fires when the form is rendered
40771 * @param {Roo.form.Form} form
40776 Roo.each(B, this.addxtype, this);
40782 Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
40784 * @cfg {Number} labelWidth The width of labels. This property cascades to child containers.
40787 * @cfg {String} itemCls A css class to apply to the x-form-item of fields. This property cascades to child containers.
40790 * @cfg {String} buttonAlign Valid values are "left," "center" and "right" (defaults to "center")
40792 buttonAlign:'center',
40795 * @cfg {Number} minButtonWidth Minimum width of all buttons in pixels (defaults to 75)
40800 * @cfg {String} labelAlign Valid values are "left," "top" and "right" (defaults to "left").
40801 * This property cascades to child containers if not set.
40806 * @cfg {Boolean} monitorValid If true the form monitors its valid state <b>client-side</b> and
40807 * fires a looping event with that state. This is required to bind buttons to the valid
40808 * state using the config value formBind:true on the button.
40810 monitorValid : false,
40813 * @cfg {Number} monitorPoll The milliseconds to poll valid state, ignored if monitorValid is not true (defaults to 200)
40818 * Opens a new {@link Roo.form.Column} container in the layout stack. If fields are passed after the config, the
40819 * fields are added and the column is closed. If no fields are passed the column remains open
40820 * until end() is called.
40821 * @param {Object} config The config to pass to the column
40822 * @param {Field} field1 (optional)
40823 * @param {Field} field2 (optional)
40824 * @param {Field} etc (optional)
40825 * @return Column The column container object
40827 column : function(c){
40828 var C = new Roo.form.Column(c);
40830 if(arguments.length > 1){ // duplicate code required because of Opera
40831 this.add.apply(this, Array.prototype.slice.call(arguments, 1));
40838 * Opens a new {@link Roo.form.FieldSet} container in the layout stack. If fields are passed after the config, the
40839 * fields are added and the fieldset is closed. If no fields are passed the fieldset remains open
40840 * until end() is called.
40841 * @param {Object} config The config to pass to the fieldset
40842 * @param {Field} field1 (optional)
40843 * @param {Field} field2 (optional)
40844 * @param {Field} etc (optional)
40845 * @return FieldSet The fieldset container object
40847 fieldset : function(c){
40848 var fs = new Roo.form.FieldSet(c);
40850 if(arguments.length > 1){ // duplicate code required because of Opera
40851 this.add.apply(this, Array.prototype.slice.call(arguments, 1));
40858 * Opens a new {@link Roo.form.Layout} container in the layout stack. If fields are passed after the config, the
40859 * fields are added and the container is closed. If no fields are passed the container remains open
40860 * until end() is called.
40861 * @param {Object} config The config to pass to the Layout
40862 * @param {Field} field1 (optional)
40863 * @param {Field} field2 (optional)
40864 * @param {Field} etc (optional)
40865 * @return Layout The container object
40867 container : function(c){
40868 var l = new Roo.form.Layout(c);
40870 if(arguments.length > 1){ // duplicate code required because of Opera
40871 this.add.apply(this, Array.prototype.slice.call(arguments, 1));
40878 * Opens the passed container in the layout stack. The container can be any {@link Roo.form.Layout} or subclass.
40879 * @param {Object} container A Roo.form.Layout or subclass of Layout
40880 * @return {Form} this
40882 start : function(c){
40883 // cascade label info
40884 Roo.applyIf(c, {'labelAlign': this.active.labelAlign, 'labelWidth': this.active.labelWidth, 'itemCls': this.active.itemCls});
40885 this.active.stack.push(c);
40886 c.ownerCt = this.active;
40892 * Closes the current open container
40893 * @return {Form} this
40896 if(this.active == this.root){
40900 this.active = this.active.ownerCt;
40905 * Add Roo.form components to the current open container (e.g. column, fieldset, etc.). Fields added via this method
40906 * can also be passed with an additional property of fieldLabel, which if supplied, will provide the text to display
40907 * as the label of the field.
40908 * @param {Field} field1
40909 * @param {Field} field2 (optional)
40910 * @param {Field} etc. (optional)
40911 * @return {Form} this
40914 this.active.stack.push.apply(this.active.stack, arguments);
40915 this.allItems.push.apply(this.allItems,arguments);
40917 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
40918 if(a[i].isFormField){
40923 Roo.form.Form.superclass.add.apply(this, r);
40928 * Find any element that has been added to a form, using it's ID or name
40929 * This can include framesets, columns etc. along with regular fields..
40930 * @param {String} id - id or name to find.
40932 * @return {Element} e - or false if nothing found.
40934 findbyId : function(id)
40941 Ext.each(this.allItems, function(f){
40942 if (f.id == id || f.name == id ){
40953 * Render this form into the passed container. This should only be called once!
40954 * @param {String/HTMLElement/Element} container The element this component should be rendered into
40955 * @return {Form} this
40957 render : function(ct){
40959 var o = this.autoCreate || {
40961 method : this.method || 'POST',
40962 id : this.id || Roo.id()
40964 this.initEl(ct.createChild(o));
40966 this.root.render(this.el);
40968 this.items.each(function(f){
40969 f.render('x-form-el-'+f.id);
40972 if(this.buttons.length > 0){
40973 // tables are required to maintain order and for correct IE layout
40974 var tb = this.el.createChild({cls:'x-form-btns-ct', cn: {
40975 cls:"x-form-btns x-form-btns-"+this.buttonAlign,
40976 html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
40978 var tr = tb.getElementsByTagName('tr')[0];
40979 for(var i = 0, len = this.buttons.length; i < len; i++) {
40980 var b = this.buttons[i];
40981 var td = document.createElement('td');
40982 td.className = 'x-form-btn-td';
40983 b.render(tr.appendChild(td));
40986 if(this.monitorValid){ // initialize after render
40987 this.startMonitoring();
40990 this.fireEvent('rendered', this);
40995 * Adds a button to the footer of the form - this <b>must</b> be called before the form is rendered.
40996 * @param {String/Object} config A string becomes the button text, an object can either be a Button config
40997 * object or a valid Roo.DomHelper element config
40998 * @param {Function} handler The function called when the button is clicked
40999 * @param {Object} scope (optional) The scope of the handler function
41000 * @return {Roo.Button}
41002 addButton : function(E, F, G){
41006 minWidth: this.minButtonWidth,
41009 if(typeof E == "string"){
41014 var H = new Roo.Button(null, bc);
41015 this.buttons.push(H);
41020 * Adds a series of form elements (using the xtype property as the factory method.
41021 * Valid xtypes are: TextField, TextArea .... Button, Layout, FieldSet, Column, (and 'end' to close a block)
41022 * @param {Object} config
41025 addxtype : function()
41027 var ar = Array.prototype.slice.call(arguments, 0);
41029 for(var i = 0; i < ar.length; i++) {
41031 continue; // skip -- if this happends something invalid got sent, we
41032 // should ignore it, as basically that interface element will not show up
41033 // and that should be pretty obvious!!
41036 if (Roo.form[ar[i].xtype]) {
41038 var fe = Roo.factory(ar[i], Roo.form);
41045 fe.store.form = this;
41050 this.allItems.push(fe);
41051 if (fe.items && fe.addxtype) {
41052 fe.addxtype.apply(fe, fe.items);
41064 // console.log('adding ' + ar[i].xtype);
41066 if (ar[i].xtype == 'Button') {
41067 //console.log('adding button');
41068 //console.log(ar[i]);
41069 this.addButton(ar[i]);
41070 this.allItems.push(fe);
41074 if (ar[i].xtype == 'end') { // so we can add fieldsets... / layout etc.
41075 alert('end is not supported on xtype any more, use items');
41077 // //console.log('adding end');
41085 * Starts monitoring of the valid state of this form. Usually this is done by passing the config
41086 * option "monitorValid"
41088 startMonitoring : function(){
41091 Roo.TaskMgr.start({
41092 run : this.bindHandler,
41093 interval : this.monitorPoll || 200,
41100 * Stops monitoring of the valid state of this form
41102 stopMonitoring : function(){
41103 this.bound = false;
41107 bindHandler : function(){
41109 return false; // stops binding
41112 this.items.each(function(f){
41113 if(!f.isValid(true)){
41118 for(var i = 0, len = this.buttons.length; i < len; i++){
41119 var H = this.buttons[i];
41120 if(H.formBind === true && H.disabled === J){
41125 this.fireEvent('clientvalidation', this, J);
41139 Roo.Form = Roo.form.Form;
41143 * Ext JS Library 1.1.1
41144 * Copyright(c) 2006-2007, Ext JS, LLC.
41146 * Originally Released Under LGPL - original licence link has changed is not relivant.
41149 * <script type="text/javascript">
41153 * @class Roo.form.Action
41154 * Internal Class used to handle form actions
41156 * @param {Roo.form.BasicForm} el The form element or its id
41157 * @param {Object} config Configuration options
41161 // define the action interface
41162 Roo.form.Action = function(A, B){
41164 this.options = B || {};
41167 * Client Validation Failed
41170 Roo.form.Action.CLIENT_INVALID = 'client';
41172 * Server Validation Failed
41175 Roo.form.Action.SERVER_INVALID = 'server';
41177 * Connect to Server Failed
41180 Roo.form.Action.CONNECT_FAILURE = 'connect';
41182 * Reading Data from Server Failed
41185 Roo.form.Action.LOAD_FAILURE = 'load';
41187 Roo.form.Action.prototype = {
41189 failureType : undefined,
41190 response : undefined,
41191 result : undefined,
41193 // interface method
41198 // interface method
41199 success : function(D){
41203 // interface method
41204 handleResponse : function(E){
41208 // default connection failure
41209 failure : function(F){
41211 this.failureType = Roo.form.Action.CONNECT_FAILURE;
41212 this.form.afterAction(this, false);
41215 processResponse : function(G){
41217 if(!G.responseText){
41221 this.result = this.handleResponse(G);
41222 return this.result;
41225 // utility functions used internally
41226 getUrl : function(H){
41227 var I = this.options.url || this.form.url || this.form.el.dom.action;
41229 var p = this.getParams();
41231 I += (I.indexOf('?') != -1 ? '&' : '?') + p;
41237 getMethod : function(){
41238 return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
41241 getParams : function(){
41242 var bp = this.form.baseParams;
41243 var p = this.options.params;
41245 if(typeof p == "object"){
41246 p = Roo.urlEncode(Roo.applyIf(p, bp));
41247 }else if(typeof p == 'string' && bp){
41248 p += '&' + Roo.urlEncode(bp);
41251 p = Roo.urlEncode(bp);
41256 createCallback : function(){
41258 success: this.success,
41259 failure: this.failure,
41261 timeout: (this.form.timeout*1000),
41262 upload: this.form.fileUpload ? this.success : undefined
41267 Roo.form.Action.Submit = function(J, K){
41268 Roo.form.Action.Submit.superclass.constructor.call(this, J, K);
41271 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
41275 var o = this.options;
41276 var L = this.getMethod();
41277 var M = L == 'POST';
41278 if(o.clientValidation === false || this.form.isValid()){
41279 Roo.Ajax.request(Roo.apply(this.createCallback(), {
41280 form:this.form.el.dom,
41281 url:this.getUrl(!M),
41283 params:M ? this.getParams() : null,
41284 isUpload: this.form.fileUpload
41287 }else if (o.clientValidation !== false){ // client validation failed
41288 this.failureType = Roo.form.Action.CLIENT_INVALID;
41289 this.form.afterAction(this, false);
41293 success : function(N){
41294 var O = this.processResponse(N);
41295 if(O === true || O.success){
41296 this.form.afterAction(this, true);
41300 this.form.markInvalid(O.errors);
41301 this.failureType = Roo.form.Action.SERVER_INVALID;
41304 this.form.afterAction(this, false);
41307 handleResponse : function(P){
41308 if(this.form.errorReader){
41309 var rs = this.form.errorReader.read(P);
41312 for(var i = 0, len = rs.records.length; i < len; i++) {
41313 var r = rs.records[i];
41314 errors[i] = r.data;
41317 if(errors.length < 1){
41321 success : rs.success,
41327 Q = Roo.decode(P.responseText);
41331 errorMsg: "Failed to read server message: " + response.responseText,
41341 Roo.form.Action.Load = function(R, S){
41342 Roo.form.Action.Load.superclass.constructor.call(this, R, S);
41343 this.reader = this.form.reader;
41346 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
41350 Roo.Ajax.request(Roo.apply(
41351 this.createCallback(), {
41352 method:this.getMethod(),
41353 url:this.getUrl(false),
41354 params:this.getParams()
41358 success : function(T){
41359 var U = this.processResponse(T);
41360 if(U === true || !U.success || !U.data){
41361 this.failureType = Roo.form.Action.LOAD_FAILURE;
41362 this.form.afterAction(this, false);
41366 this.form.clearInvalid();
41367 this.form.setValues(U.data);
41368 this.form.afterAction(this, true);
41371 handleResponse : function(V){
41372 if(this.form.reader){
41373 var rs = this.form.reader.read(V);
41374 var data = rs.records && rs.records[0] ? rs.records[0].data : null;
41376 success : rs.success,
41380 return Roo.decode(V.responseText);
41384 Roo.form.Action.ACTION_TYPES = {
41385 'load' : Roo.form.Action.Load,
41386 'submit' : Roo.form.Action.Submit
41390 * Ext JS Library 1.1.1
41391 * Copyright(c) 2006-2007, Ext JS, LLC.
41393 * Originally Released Under LGPL - original licence link has changed is not relivant.
41396 * <script type="text/javascript">
41400 * @class Roo.form.Layout
41401 * @extends Roo.Component
41402 * Creates a container for layout and rendering of fields in an {@link Roo.form.Form}.
41404 * @param {Object} config Configuration options
41406 Roo.form.Layout = function(A){
41413 Roo.form.Layout.superclass.constructor.call(this, A);
41415 Roo.each(B, this.addxtype, this);
41419 Roo.extend(Roo.form.Layout, Roo.Component, {
41421 * @cfg {String/Object} autoCreate
41422 * A DomHelper element spec used to autocreate the layout (defaults to {tag: 'div', cls: 'x-form-ct'})
41425 * @cfg {String/Object/Function} style
41426 * A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
41427 * a function which returns such a specification.
41430 * @cfg {String} labelAlign
41431 * Valid values are "left," "top" and "right" (defaults to "left")
41434 * @cfg {Number} labelWidth
41435 * Fixed width in pixels of all field labels (defaults to undefined)
41438 * @cfg {Boolean} clear
41439 * True to add a clearing element at the end of this layout, equivalent to CSS clear: both (defaults to true)
41443 * @cfg {String} labelSeparator
41444 * The separator to use after field labels (defaults to ':')
41446 labelSeparator : ':',
41448 * @cfg {Boolean} hideLabels
41449 * True to suppress the display of field labels in this layout (defaults to false)
41451 hideLabels : false,
41454 defaultAutoCreate : {tag: 'div', cls: 'x-form-ct'},
41459 onRender : function(ct, C){
41460 if(this.el){ // from markup
41461 this.el = Roo.get(this.el);
41462 }else { // generate
41463 var cfg = this.getAutoCreate();
41464 this.el = ct.createChild(cfg, C);
41467 this.el.applyStyles(this.style);
41469 if(this.labelAlign){
41470 this.el.addClass('x-form-label-'+this.labelAlign);
41472 if(this.hideLabels){
41473 this.labelStyle = "display:none";
41474 this.elementStyle = "padding-left:0;";
41476 if(typeof this.labelWidth == 'number'){
41477 this.labelStyle = "width:"+this.labelWidth+"px;";
41478 this.elementStyle = "padding-left:"+((this.labelWidth+(typeof this.labelPad == 'number' ? this.labelPad : 5))+'px')+";";
41480 if(this.labelAlign == 'top'){
41481 this.labelStyle = "width:auto;";
41482 this.elementStyle = "padding-left:0;";
41485 var D = this.stack;
41488 if(!this.fieldTpl){
41489 var t = new Roo.Template(
41490 '<div class="x-form-item {5}">',
41491 '<label for="{0}" style="{2}">{1}{4}</label>',
41492 '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
41494 '</div><div class="x-form-clear-left"></div>'
41496 t.disableFormats = true;
41498 Roo.form.Layout.prototype.fieldTpl = t;
41500 for(var i = 0; i < E; i++) {
41501 if(D[i].isFormField){
41502 this.renderField(D[i]);
41504 this.renderComponent(D[i]);
41509 this.el.createChild({cls:'x-form-clear'});
41514 renderField : function(f){
41515 f.fieldEl = Roo.get(this.fieldTpl.append(this.el, [
41518 f.labelStyle||this.labelStyle||'', //2
41519 this.elementStyle||'', //3
41520 typeof f.labelSeparator == 'undefined' ? this.labelSeparator : f.labelSeparator, //4
41521 f.itemCls||this.itemCls||'' //5
41522 ], true).getPrevSibling());
41526 renderComponent : function(c){
41527 c.render(c.isLayout ? this.el : this.el.createChild());
41530 * Adds a object form elements (using the xtype property as the factory method.)
41531 * Valid xtypes are: TextField, TextArea .... Button, Layout, FieldSet, Column
41532 * @param {Object} config
41534 addxtype : function(o)
41536 // create the lement.
41537 o.form = this.form;
41538 var fe = Roo.factory(o, Roo.form);
41539 this.form.allItems.push(fe);
41540 this.stack.push(fe);
41542 if (fe.isFormField) {
41543 this.form.items.add(fe);
41551 * @class Roo.form.Column
41552 * @extends Roo.form.Layout
41553 * Creates a column container for layout and rendering of fields in an {@link Roo.form.Form}.
41555 * @param {Object} config Configuration options
41557 Roo.form.Column = function(F){
41558 Roo.form.Column.superclass.constructor.call(this, F);
41561 Roo.extend(Roo.form.Column, Roo.form.Layout, {
41563 * @cfg {Number/String} width
41564 * The fixed width of the column in pixels or CSS value (defaults to "auto")
41567 * @cfg {String/Object} autoCreate
41568 * A DomHelper element spec used to autocreate the column (defaults to {tag: 'div', cls: 'x-form-ct x-form-column'})
41572 defaultAutoCreate : {tag: 'div', cls: 'x-form-ct x-form-column'},
41575 onRender : function(ct, G){
41576 Roo.form.Column.superclass.onRender.call(this, ct, G);
41578 this.el.setWidth(this.width);
41585 * @class Roo.form.Row
41586 * @extends Roo.form.Layout
41587 * Creates a row container for layout and rendering of fields in an {@link Roo.form.Form}.
41589 * @param {Object} config Configuration options
41593 Roo.form.Row = function(H){
41594 Roo.form.Row.superclass.constructor.call(this, H);
41597 Roo.extend(Roo.form.Row, Roo.form.Layout, {
41599 * @cfg {Number/String} width
41600 * The fixed width of the column in pixels or CSS value (defaults to "auto")
41603 * @cfg {Number/String} height
41604 * The fixed height of the column in pixels or CSS value (defaults to "auto")
41606 defaultAutoCreate : {tag: 'div', cls: 'x-form-ct x-form-row'},
41610 onRender : function(ct, I){
41611 //console.log('row render');
41613 var t = new Roo.Template(
41614 '<div class="x-form-item {5}" style="float:left;width:{6}px">',
41615 '<label for="{0}" style="{2}">{1}{4}</label>',
41616 '<div class="x-form-element" id="x-form-el-{0}" style="{3}">',
41620 t.disableFormats = true;
41622 Roo.form.Layout.prototype.rowTpl = t;
41625 this.fieldTpl = this.rowTpl;
41627 //console.log('lw' + this.labelWidth +', la:' + this.labelAlign);
41630 if ((this.labelAlign != 'top')) {
41631 if (typeof this.labelWidth == 'number') {
41632 J = this.labelWidth
41635 this.padWidth = 20 + J;
41640 Roo.form.Column.superclass.onRender.call(this, ct, I);
41642 this.el.setWidth(this.width);
41645 this.el.setHeight(this.height);
41650 renderField : function(f){
41651 f.fieldEl = this.fieldTpl.append(this.el, [
41652 f.id, f.fieldLabel,
41653 f.labelStyle||this.labelStyle||'',
41654 this.elementStyle||'',
41655 typeof f.labelSeparator == 'undefined' ? this.labelSeparator : f.labelSeparator,
41656 f.itemCls||this.itemCls||'',
41657 f.width ? f.width + this.padWidth : 160 + this.padWidth
41664 * @class Roo.form.FieldSet
41665 * @extends Roo.form.Layout
41666 * Creates a fieldset container for layout and rendering of fields in an {@link Roo.form.Form}.
41668 * @param {Object} config Configuration options
41670 Roo.form.FieldSet = function(K){
41671 Roo.form.FieldSet.superclass.constructor.call(this, K);
41674 Roo.extend(Roo.form.FieldSet, Roo.form.Layout, {
41676 * @cfg {String} legend
41677 * The text to display as the legend for the FieldSet (defaults to '')
41680 * @cfg {String/Object} autoCreate
41681 * A DomHelper element spec used to autocreate the fieldset (defaults to {tag: 'fieldset', cn: {tag:'legend'}})
41685 defaultAutoCreate : {tag: 'fieldset', cn: {tag:'legend'}},
41688 onRender : function(ct, L){
41689 Roo.form.FieldSet.superclass.onRender.call(this, ct, L);
41691 this.setLegend(this.legend);
41696 setLegend : function(M){
41698 this.el.child('legend').update(M);
41704 * Ext JS Library 1.1.1
41705 * Copyright(c) 2006-2007, Ext JS, LLC.
41707 * Originally Released Under LGPL - original licence link has changed is not relivant.
41710 * <script type="text/javascript">
41713 * @class Roo.form.VTypes
41714 * Overridable validation definitions. The validations provided are basic and intended to be easily customizable and extended.
41717 Roo.form.VTypes = function(){
41718 // closure these in so they are only created once.
41719 var A = /^[a-zA-Z_]+$/;
41720 var B = /^[a-zA-Z0-9_]+$/;
41721 var C = /^([\w]+)(.[\w]+)*@([\w-]+\.){1,5}([A-Za-z]){2,4}$/;
41722 var D = /(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
41724 // All these messages and functions are configurable
41727 * The function used to validate email addresses
41728 * @param {String} value The email address
41730 'email' : function(v){
41734 * The error text to display when the email validation function returns false
41737 'emailText' : 'This field should be an e-mail address in the format "user@domain.com"',
41739 * The keystroke filter mask to be applied on email input
41742 'emailMask' : /[a-z0-9_\.\-@]/i,
41745 * The function used to validate URLs
41746 * @param {String} value The URL
41748 'url' : function(v){
41752 * The error text to display when the url validation function returns false
41755 'urlText' : 'This field should be a URL in the format "http:/'+'/www.domain.com"',
41758 * The function used to validate alpha values
41759 * @param {String} value The value
41761 'alpha' : function(v){
41765 * The error text to display when the alpha validation function returns false
41768 'alphaText' : 'This field should only contain letters and _',
41770 * The keystroke filter mask to be applied on alpha input
41773 'alphaMask' : /[a-z_]/i,
41776 * The function used to validate alphanumeric values
41777 * @param {String} value The value
41779 'alphanum' : function(v){
41783 * The error text to display when the alphanumeric validation function returns false
41786 'alphanumText' : 'This field should only contain letters, numbers and _',
41788 * The keystroke filter mask to be applied on alphanumeric input
41791 'alphanumMask' : /[a-z0-9_]/i
41794 //<script type="text/javascript">
41797 * @class Roo.form.FCKeditor
41798 * @extends Roo.form.TextArea
41799 * Wrapper around the FCKEditor http://www.fckeditor.net
41801 * Creates a new FCKeditor
41802 * @param {Object} config Configuration options
41804 Roo.form.FCKeditor = function(A){
41805 Roo.form.FCKeditor.superclass.constructor.call(this, A);
41808 * @event editorinit
41809 * Fired when the editor is initialized - you can add extra handlers here..
41810 * @param {FCKeditor} this
41811 * @param {Object} the FCK object.
41818 Roo.form.FCKeditor.editors = { };
41819 Roo.extend(Roo.form.FCKeditor, Roo.form.TextArea,
41821 //defaultAutoCreate : {
41822 // tag : "textarea",style : "width:100px;height:60px;" ,autocomplete : "off"
41826 * @cfg {Object} fck options - see fck manual for details.
41831 * @cfg {Object} fck toolbar set (Basic or Default)
41833 toolbarSet : 'Basic',
41835 * @cfg {Object} fck BasePath
41837 basePath : '/fckeditor/',
41845 onRender : function(ct, B)
41848 this.defaultAutoCreate = {
41850 style:"width:300px;height:60px;",
41851 autocomplete: "off"
41855 Roo.form.FCKeditor.superclass.onRender.call(this, ct, B);
41858 this.textSizeEl = Roo.DomHelper.append(document.body, {tag: "pre", cls: "x-form-grow-sizer"});
41859 if(this.preventScrollbars){
41860 this.el.setStyle("overflow", "hidden");
41862 this.el.setHeight(this.growMin);
41865 //console.log('onrender' + this.getId() );
41866 Roo.form.FCKeditor.editors[this.getId()] = this;
41869 this.replaceTextarea() ;
41873 getEditor : function() {
41874 return this.fckEditor;
41877 * Sets a data value into the field and validates it. To set the value directly without validation see {@link #setRawValue}.
41878 * @param {Mixed} value The value to set
41882 setValue : function(C)
41884 //console.log('setValue: ' + value);
41886 if(typeof(C) == 'undefined') { // not sure why this is happending...
41890 Roo.form.FCKeditor.superclass.setValue.apply(this,[C]);
41892 //if(!this.el || !this.getEditor()) {
41893 // this.value = value;
41894 //this.setValue.defer(100,this,[value]);
41898 if(!this.getEditor()) {
41903 this.getEditor().SetData(C);
41910 * Returns the normalized data value (undefined or emptyText will be returned as ''). To return the raw value see {@link #getRawValue}.
41911 * @return {Mixed} value The field value
41913 getValue : function()
41916 if (this.frame && this.frame.dom.style.display == 'none') {
41917 return Roo.form.FCKeditor.superclass.getValue.call(this);
41920 if(!this.el || !this.getEditor()) {
41922 // this.getValue.defer(100,this);
41927 var D=this.getEditor().GetData();
41928 Roo.form.FCKeditor.superclass.setValue.apply(this,[D]);
41929 return Roo.form.FCKeditor.superclass.getValue.call(this);
41935 * Returns the raw data value which may or may not be a valid, defined value. To return a normalized value see {@link #getValue}.
41936 * @return {Mixed} value The field value
41938 getRawValue : function()
41940 if (this.frame && this.frame.dom.style.display == 'none') {
41941 return Roo.form.FCKeditor.superclass.getRawValue.call(this);
41944 if(!this.el || !this.getEditor()) {
41945 //this.getRawValue.defer(100,this);
41952 var E=this.getEditor().GetData();
41953 Roo.form.FCKeditor.superclass.setRawValue.apply(this,[E]);
41954 return Roo.form.FCKeditor.superclass.getRawValue.call(this);
41958 setSize : function(w,h) {
41962 //if (this.frame && this.frame.dom.style.display == 'none') {
41963 // Roo.form.FCKeditor.superclass.setSize.apply(this, [w, h]);
41966 //if(!this.el || !this.getEditor()) {
41967 // this.setSize.defer(100,this, [w,h]);
41973 Roo.form.FCKeditor.superclass.setSize.apply(this, [w, h]);
41975 this.frame.dom.setAttribute('width', w);
41976 this.frame.dom.setAttribute('height', h);
41977 this.frame.setSize(w,h);
41981 toggleSourceEdit : function(F) {
41985 this.el.dom.style.display = F ? '' : 'none';
41986 this.frame.dom.style.display = F ? 'none' : '';
41993 if (this.frame.dom.style.display == 'none') {
41994 return Roo.form.FCKeditor.superclass.focus.call(this);
41996 if(!this.el || !this.getEditor()) {
41997 this.focus.defer(100,this, [G]);
42004 var H = this.getEditor().EditorDocument.getElementsByTagName(G);
42005 this.getEditor().Focus();
42007 if (!this.getEditor().Selection.GetSelection()) {
42008 this.focus.defer(100,this, [G]);
42013 var r = this.getEditor().EditorDocument.createRange();
42014 r.setStart(H[0],0);
42016 this.getEditor().Selection.GetSelection().removeAllRanges();
42017 this.getEditor().Selection.GetSelection().addRange(r);
42018 this.getEditor().Focus();
42025 replaceTextarea : function()
42027 if ( document.getElementById( this.getId() + '___Frame' ) )
42029 //if ( !this.checkBrowser || this._isCompatibleBrowser() )
42031 // We must check the elements firstly using the Id and then the name.
42032 var I = document.getElementById( this.getId() );
42034 var J = document.getElementsByName( this.getId() ) ;
42036 I.style.display = 'none' ;
42038 if ( I.tabIndex ) {
42039 this.TabIndex = I.tabIndex ;
42043 this._insertHtmlBefore( this._getConfigHtml(), I ) ;
42044 this._insertHtmlBefore( this._getIFrameHtml(), I ) ;
42045 this.frame = Roo.get(this.getId() + '___Frame')
42048 _getConfigHtml : function()
42052 for ( var o in this.fckconfig ) {
42053 K += K.length > 0 ? '&' : '';
42054 K += encodeURIComponent( o ) + '=' + encodeURIComponent( this.fckconfig[o] ) ;
42057 return '<input type="hidden" id="' + this.getId() + '___Config" value="' + K + '" style="display:none" />' ;
42061 _getIFrameHtml : function()
42063 var L = 'fckeditor.html' ;
42064 /* no idea what this is about..
42067 if ( (/fcksource=true/i).test( window.top.location.search ) )
42068 sFile = 'fckeditor.original.html' ;
42073 var M = this.basePath + 'editor/' + L + '?InstanceName=' + encodeURIComponent( this.getId() ) ;
42074 M += this.toolbarSet ? ( '&Toolbar=' + this.toolbarSet) : '';
42077 var N = '<iframe id="' + this.getId() +
42078 '___Frame" src="' + M +
42079 '" width="' + this.width +
42080 '" height="' + this.height + '"' +
42081 (this.tabIndex ? ' tabindex="' + this.tabIndex + '"' :'' ) +
42082 ' frameborder="0" scrolling="no"></iframe>' ;
42087 _insertHtmlBefore : function( O, P )
42089 if ( P.insertAdjacentHTML ) {
42091 P.insertAdjacentHTML( 'beforeBegin', O ) ;
42093 var oRange = document.createRange() ;
42094 oRange.setStartBefore( P ) ;
42095 var oFragment = oRange.createContextualFragment( O );
42096 P.parentNode.insertBefore( oFragment, P ) ;
42109 //Roo.reg('fckeditor', Roo.form.FCKeditor);
42112 var f = Roo.form.FCKeditor.editors[R.Name];
42114 //console.log("loaded");
42115 f.fireEvent('editorinit', f, R);
42136 //<script type="text/javascript">
42138 * @class Roo.form.GridField
42139 * @extends Roo.form.Field
42140 * Embed a grid (or editable grid into a form)
42143 * Creates a new GridField
42144 * @param {Object} config Configuration options
42146 Roo.form.GridField = function(A){
42147 Roo.form.GridField.superclass.constructor.call(this, A);
42151 Roo.extend(Roo.form.GridField, Roo.form.Field, {
42153 * @cfg {Number} width - used to restrict width of grid..
42157 * @cfg {Number} height - used to restrict height of grid..
42161 * @cfg {Object} xgrid (xtype'd description of grid) Grid or EditorGrid
42165 * @cfg {String/Object} autoCreate A DomHelper element spec, or true for a default element spec (defaults to
42166 * {tag: "input", type: "checkbox", autocomplete: "off"})
42168 // defaultAutoCreate : { tag: 'div' },
42169 defaultAutoCreate : { tag: 'input', type: 'hidden', autocomplete: 'off'},
42171 * @cfg {String} addTitle Text to include for adding a title.
42175 onResize : function(){
42176 Roo.form.Field.superclass.onResize.apply(this, arguments);
42179 initEvents : function(){
42180 // Roo.form.Checkbox.superclass.initEvents.call(this);
42181 // has no events...
42186 getResizeEl : function(){
42190 getPositionEl : function(){
42195 onRender : function(ct, B){
42197 this.style = this.style || 'overflow: hidden; border:1px solid #c3daf9;';
42198 var C = this.style;
42201 Roo.form.DisplayImage.superclass.onRender.call(this, ct, B);
42202 this.wrap = this.el.wrap({cls: ''}); // not sure why ive done thsi...
42203 this.viewEl = this.wrap.createChild({ tag: 'div' });
42205 this.viewEl.applyStyles(C);
42208 this.viewEl.setWidth(this.width);
42211 this.viewEl.setHeight(this.height);
42214 //if(this.inputValue !== undefined){
42215 //this.setValue(this.value);
42218 this.grid = new Roo.grid[this.xgrid.xtype](this.viewEl, this.xgrid);
42221 this.grid.render();
42222 this.grid.getDataSource().on('remove', this.refreshValue, this);
42223 this.grid.getDataSource().on('update', this.refreshValue, this);
42224 this.grid.on('afteredit', this.refreshValue, this);
42230 * Sets the value of the item.
42231 * @param {String} either an object or a string..
42233 setValue : function(v){
42235 v = v || []; // empty set..
42236 // this does not seem smart - it really only affects memoryproxy grids..
42237 if (this.grid && this.grid.getDataSource() && typeof(v) != 'undefined') {
42238 var ds = this.grid.getDataSource();
42239 // assumes a json reader..
42242 data[ds.reader.meta.root ] = typeof(v) == 'string' ? Roo.decode(v) : v;
42243 ds.loadData( data);
42246 Roo.form.GridField.superclass.setValue.call(this, v);
42247 this.refreshValue();
42248 // should load data in the grid really....
42252 refreshValue: function() {
42254 this.grid.getDataSource().each(function(r) {
42257 this.el.dom.value = Roo.encode(D);
42264 //<script type="text/javasscript">
42268 * @class Roo.DDView
42269 * A DnD enabled version of Roo.View.
42270 * @param {Element/String} container The Element in which to create the View.
42271 * @param {String} tpl The template string used to create the markup for each element of the View
42272 * @param {Object} config The configuration properties. These include all the config options of
42273 * {@link Roo.View} plus some specific to this class.<br>
42275 * Drag/drop is implemented by adding {@link Roo.data.Record}s to the target DDView. If copying is
42276 * not being performed, the original {@link Roo.data.Record} is removed from the source DDView.<br>
42278 * The following extra CSS rules are needed to provide insertion point highlighting:<pre><code>
42279 .x-view-drag-insert-above {
42280 border-top:1px dotted #3366cc;
42282 .x-view-drag-insert-below {
42283 border-bottom:1px dotted #3366cc;
42289 Roo.DDView = function(A, B, C) {
42290 Roo.DDView.superclass.constructor.apply(this, arguments);
42291 this.getEl().setStyle("outline", "0px none");
42292 this.getEl().unselectable();
42293 if (this.dragGroup) {
42294 this.setDraggable(this.dragGroup.split(","));
42296 if (this.dropGroup) {
42297 this.setDroppable(this.dropGroup.split(","));
42299 if (this.deletable) {
42300 this.setDeletable();
42303 this.isDirtyFlag = false;
42309 Roo.extend(Roo.DDView, Roo.View, {
42310 /** @cfg {String/Array} dragGroup The ddgroup name(s) for the View's DragZone. */
42311 /** @cfg {String/Array} dropGroup The ddgroup name(s) for the View's DropZone. */
42312 /** @cfg {Boolean} copy Causes drag operations to copy nodes rather than move. */
42313 /** @cfg {Boolean} allowCopy Causes ctrl/drag operations to copy nodes rather than move. */
42317 reset: Roo.emptyFn,
42319 clearInvalid: Roo.form.Field.prototype.clearInvalid,
42321 validate: function() {
42325 destroy: function() {
42326 this.purgeListeners();
42327 this.getEl.removeAllListeners();
42328 this.getEl().remove();
42329 if (this.dragZone) {
42330 if (this.dragZone.destroy) {
42331 this.dragZone.destroy();
42334 if (this.dropZone) {
42335 if (this.dropZone.destroy) {
42336 this.dropZone.destroy();
42341 /** Allows this class to be an Roo.form.Field so it can be found using {@link Roo.form.BasicForm#findField}. */
42342 getName: function() {
42346 /** Loads the View from a JSON string representing the Records to put into the Store. */
42347 setValue: function(v) {
42349 throw "DDView.setValue(). DDView must be constructed with a valid Store";
42352 D[this.store.reader.meta.root] = v ? [].concat(v) : [];
42353 this.store.proxy = new Roo.data.MemoryProxy(D);
42357 /** @return {String} a parenthesised list of the ids of the Records in the View. */
42358 getValue: function() {
42360 this.store.each(function(F) {
42363 return E.substr(0, E.length - 1) + ')';
42366 getIds: function() {
42367 var i = 0, F = new Array(this.store.getCount());
42368 this.store.each(function(G) {
42374 isDirty: function() {
42375 return this.isDirtyFlag;
42379 * Part of the Roo.dd.DropZone interface. If no target node is found, the
42380 * whole Element becomes the target, and this causes the drop gesture to append.
42382 getTargetFromEvent : function(e) {
42383 var G = e.getTarget();
42384 while ((G !== null) && (G.parentNode != this.el.dom)) {
42388 G = this.el.dom.lastChild || this.el.dom;
42394 * Create the drag data which consists of an object which has the property "ddel" as
42395 * the drag proxy element.
42397 getDragData : function(e) {
42398 var H = this.findItemFromChild(e.getTarget());
42400 this.handleSelection(e);
42401 var selNodes = this.getSelectedNodes();
42404 copy: this.copy || (this.allowCopy && e.ctrlKey),
42408 var selectedIndices = this.getSelectedIndexes();
42409 for (var i = 0; i < selectedIndices.length; i++) {
42410 dragData.records.push(this.store.getAt(selectedIndices[i]));
42412 if (selNodes.length == 1) {
42413 dragData.ddel = H.cloneNode(true); // the div element
42415 var div = document.createElement('div'); // create the multi element drag "ghost"
42416 div.className = 'multi-proxy';
42417 for (var i = 0, len = selNodes.length; i < len; i++) {
42418 div.appendChild(selNodes[i].cloneNode(true));
42421 dragData.ddel = div;
42423 //console.log(dragData)
42424 //console.log(dragData.ddel.innerHTML)
42427 //console.log('nodragData')
42431 /** Specify to which ddGroup items in this DDView may be dragged. */
42432 setDraggable: function(I) {
42433 if (I instanceof Array) {
42434 Roo.each(I, this.setDraggable, this);
42437 if (this.dragZone) {
42438 this.dragZone.addToGroup(I);
42440 this.dragZone = new Roo.dd.DragZone(this.getEl(), {
42441 containerScroll: true,
42445 // Draggability implies selection. DragZone's mousedown selects the element.
42446 if (!this.multiSelect) { this.singleSelect = true; }
42449 // Wire the DragZone's handlers up to methods in *this*
42450 this.dragZone.getDragData = this.getDragData.createDelegate(this);
42454 /** Specify from which ddGroup this DDView accepts drops. */
42455 setDroppable: function(J) {
42456 if (J instanceof Array) {
42457 Roo.each(J, this.setDroppable, this);
42460 if (this.dropZone) {
42461 this.dropZone.addToGroup(J);
42463 this.dropZone = new Roo.dd.DropZone(this.getEl(), {
42464 containerScroll: true,
42468 // Wire the DropZone's handlers up to methods in *this*
42469 this.dropZone.getTargetFromEvent = this.getTargetFromEvent.createDelegate(this);
42470 this.dropZone.onNodeEnter = this.onNodeEnter.createDelegate(this);
42471 this.dropZone.onNodeOver = this.onNodeOver.createDelegate(this);
42472 this.dropZone.onNodeOut = this.onNodeOut.createDelegate(this);
42473 this.dropZone.onNodeDrop = this.onNodeDrop.createDelegate(this);
42477 /** Decide whether to drop above or below a View node. */
42478 getDropPoint : function(e, n, dd){
42479 if (n == this.el.dom) { return "above"; }
42480 var t = Roo.lib.Dom.getY(n), b = t + n.offsetHeight;
42481 var c = t + (b - t) / 2;
42482 var y = Roo.lib.Event.getPageY(e);
42490 onNodeEnter : function(n, dd, e, K){
42494 onNodeOver : function(n, dd, e, L){
42495 var pt = this.getDropPoint(e, n, dd);
42496 // set the insert point style on the target node
42497 var M = this.dropNotAllowed;
42500 if (pt == "above"){
42501 M = n.previousSibling ? "x-tree-drop-ok-between" : "x-tree-drop-ok-above";
42502 targetElClass = "x-view-drag-insert-above";
42504 M = n.nextSibling ? "x-tree-drop-ok-between" : "x-tree-drop-ok-below";
42505 targetElClass = "x-view-drag-insert-below";
42507 if (this.lastInsertClass != targetElClass){
42508 Roo.fly(n).replaceClass(this.lastInsertClass, targetElClass);
42509 this.lastInsertClass = targetElClass;
42515 onNodeOut : function(n, dd, e, N){
42516 this.removeDropIndicators(n);
42519 onNodeDrop : function(n, dd, e, O){
42520 if (this.fireEvent("drop", this, n, dd, e, O) === false) {
42523 var pt = this.getDropPoint(e, n, dd);
42524 var P = (n == this.el.dom) ? this.nodes.length : n.nodeIndex;
42525 if (pt == "below") { P++; }
42526 for (var i = 0; i < O.records.length; i++) {
42527 var r = O.records[i];
42528 var dup = this.store.getById(r.id);
42529 if (dup && (dd != this.dragZone)) {
42530 Roo.fly(this.getNode(this.store.indexOf(dup))).frame("red", 1);
42533 this.store.insert(P++, r.copy());
42535 O.source.isDirtyFlag = true;
42537 this.store.insert(P++, r);
42540 this.isDirtyFlag = true;
42544 this.dragZone.cachedTarget = null;
42548 removeDropIndicators : function(n){
42550 Roo.fly(n).removeClass([
42551 "x-view-drag-insert-above",
42552 "x-view-drag-insert-below"]);
42553 this.lastInsertClass = "_noclass";
42558 * Utility method. Add a delete option to the DDView's context menu.
42559 * @param {String} imageUrl The URL of the "delete" icon image.
42561 setDeletable: function(Q) {
42562 if (!this.singleSelect && !this.multiSelect) {
42563 this.singleSelect = true;
42565 var c = this.getContextMenu();
42566 this.contextMenu.on("itemclick", function(R) {
42569 this.remove(this.getSelectedIndexes());
42573 this.contextMenu.add({
42580 /** Return the context menu for this DDView. */
42581 getContextMenu: function() {
42582 if (!this.contextMenu) {
42583 // Create the View's context menu
42584 this.contextMenu = new Roo.menu.Menu({
42585 id: this.id + "-contextmenu"
42587 this.el.on("contextmenu", this.showContextMenu, this);
42589 return this.contextMenu;
42592 disableContextMenu: function() {
42593 if (this.contextMenu) {
42594 this.el.un("contextmenu", this.showContextMenu, this);
42598 showContextMenu: function(e, R) {
42599 R = this.findItemFromChild(e.getTarget());
42602 this.select(this.getNode(R), this.multiSelect && e.ctrlKey, true);
42603 this.contextMenu.showAt(e.getXY());
42608 * Remove {@link Roo.data.Record}s at the specified indices.
42609 * @param {Array/Number} selectedIndices The index (or Array of indices) of Records to remove.
42611 remove: function(S) {
42613 for (var i = 0; i < S.length; i++) {
42614 var rec = this.store.getAt(S[i]);
42615 this.store.remove(rec);
42620 * Double click fires the event, but also, if this is draggable, and there is only one other
42621 * related DropZone, it transfers the selected node.
42623 onDblClick : function(e){
42624 var T = this.findItemFromChild(e.getTarget());
42626 if (this.fireEvent("dblclick", this, this.indexOf(T), T, e) === false) {
42629 if (this.dragGroup) {
42630 var targets = Roo.dd.DragDropMgr.getRelated(this.dragZone, true);
42631 while (targets.indexOf(this.dropZone) > -1) {
42632 targets.remove(this.dropZone);
42634 if (targets.length == 1) {
42635 this.dragZone.cachedTarget = null;
42636 var el = Roo.get(targets[0].getEl());
42637 var box = el.getBox(true);
42638 targets[0].onNodeDrop(el.dom, {
42640 xy: [box.x, box.y + box.height - 1]
42641 }, null, this.getDragData(e));
42647 handleSelection: function(e) {
42648 this.dragZone.cachedTarget = null;
42649 var U = this.findItemFromChild(e.getTarget());
42651 this.clearSelections(true);
42654 if (U && (this.multiSelect || this.singleSelect)){
42655 if(this.multiSelect && e.shiftKey && (!e.ctrlKey) && this.lastSelection){
42656 this.select(this.getNodes(this.indexOf(this.lastSelection), U.nodeIndex), false);
42657 }else if (this.isSelected(this.getNode(U)) && e.ctrlKey){
42660 this.select(U, this.multiSelect && e.ctrlKey);
42661 this.lastSelection = U;
42666 onItemClick : function(V, W, e){
42667 if(this.fireEvent("beforeclick", this, W, V, e) === false){
42673 unselect : function(X, Y){
42674 var Z = this.getNode(X);
42675 if(Z && this.isSelected(Z)){
42676 if(this.fireEvent("beforeselect", this, Z, this.selections) !== false){
42677 Roo.fly(Z).removeClass(this.selectedClass);
42678 this.selections.remove(Z);
42680 this.fireEvent("selectionchange", this, this.selections);
42689 * Ext JS Library 1.1.1
42690 * Copyright(c) 2006-2007, Ext JS, LLC.
42692 * Originally Released Under LGPL - original licence link has changed is not relivant.
42695 * <script type="text/javascript">
42699 * @class Roo.LayoutManager
42700 * @extends Roo.util.Observable
42701 * Base class for layout managers.
42703 Roo.LayoutManager = function(A, B){
42704 Roo.LayoutManager.superclass.constructor.call(this);
42705 this.el = Roo.get(A);
42706 // ie scrollbar fix
42707 if(this.el.dom == document.body && Roo.isIE && !B.allowScroll){
42708 document.body.scroll = "no";
42709 }else if(this.el.dom != document.body && this.el.getStyle('position') == 'static'){
42710 this.el.position('relative');
42713 this.id = this.el.id;
42714 this.el.addClass("x-layout-container");
42715 /** false to disable window resize monitoring @type Boolean */
42716 this.monitorWindowResize = true;
42721 * Fires when a layout is performed.
42722 * @param {Roo.LayoutManager} this
42726 * @event regionresized
42727 * Fires when the user resizes a region.
42728 * @param {Roo.LayoutRegion} region The resized region
42729 * @param {Number} newSize The new size (width for east/west, height for north/south)
42731 "regionresized" : true,
42733 * @event regioncollapsed
42734 * Fires when a region is collapsed.
42735 * @param {Roo.LayoutRegion} region The collapsed region
42737 "regioncollapsed" : true,
42739 * @event regionexpanded
42740 * Fires when a region is expanded.
42741 * @param {Roo.LayoutRegion} region The expanded region
42743 "regionexpanded" : true
42745 this.updating = false;
42746 Roo.EventManager.onWindowResize(this.onWindowResize, this, true);
42749 Roo.extend(Roo.LayoutManager, Roo.util.Observable, {
42751 * Returns true if this layout is currently being updated
42752 * @return {Boolean}
42754 isUpdating : function(){
42755 return this.updating;
42759 * Suspend the LayoutManager from doing auto-layouts while
42760 * making multiple add or remove calls
42762 beginUpdate : function(){
42763 this.updating = true;
42767 * Restore auto-layouts and optionally disable the manager from performing a layout
42768 * @param {Boolean} noLayout true to disable a layout update
42770 endUpdate : function(C){
42771 this.updating = false;
42777 layout: function(){
42781 onRegionResized : function(D, E){
42782 this.fireEvent("regionresized", D, E);
42786 onRegionCollapsed : function(F){
42787 this.fireEvent("regioncollapsed", F);
42790 onRegionExpanded : function(G){
42791 this.fireEvent("regionexpanded", G);
42795 * Returns the size of the current view. This method normalizes document.body and element embedded layouts and
42796 * performs box-model adjustments.
42797 * @return {Object} The size as an object {width: (the width), height: (the height)}
42799 getViewSize : function(){
42801 if(this.el.dom != document.body){
42802 H = this.el.getSize();
42804 H = {width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
42807 H.width -= this.el.getBorderWidth("lr")-this.el.getPadding("lr");
42808 H.height -= this.el.getBorderWidth("tb")-this.el.getPadding("tb");
42813 * Returns the Element this layout is bound to.
42814 * @return {Roo.Element}
42816 getEl : function(){
42821 * Returns the specified region.
42822 * @param {String} target The region key ('center', 'north', 'south', 'east' or 'west')
42823 * @return {Roo.LayoutRegion}
42825 getRegion : function(I){
42826 return this.regions[I.toLowerCase()];
42829 onWindowResize : function(){
42830 if(this.monitorWindowResize){
42837 * Ext JS Library 1.1.1
42838 * Copyright(c) 2006-2007, Ext JS, LLC.
42840 * Originally Released Under LGPL - original licence link has changed is not relivant.
42843 * <script type="text/javascript">
42846 * @class Roo.BorderLayout
42847 * @extends Roo.LayoutManager
42848 * This class represents a common layout manager used in desktop applications. For screenshots and more details,
42849 * please see: <br><br>
42850 * <a href="http://www.jackslocum.com/yui/2006/10/19/cross-browser-web-20-layouts-with-yahoo-ui/">Cross Browser Layouts - Part 1</a><br>
42851 * <a href="http://www.jackslocum.com/yui/2006/10/28/cross-browser-web-20-layouts-part-2-ajax-feed-viewer-20/">Cross Browser Layouts - Part 2</a><br><br>
42854 var layout = new Roo.BorderLayout(document.body, {
42888 preferredTabWidth: 150
42893 var CP = Roo.ContentPanel;
42895 layout.beginUpdate();
42896 layout.add("north", new CP("north", "North"));
42897 layout.add("south", new CP("south", {title: "South", closable: true}));
42898 layout.add("west", new CP("west", {title: "West"}));
42899 layout.add("east", new CP("autoTabs", {title: "Auto Tabs", closable: true}));
42900 layout.add("center", new CP("center1", {title: "Close Me", closable: true}));
42901 layout.add("center", new CP("center2", {title: "Center Panel", closable: false}));
42902 layout.getRegion("center").showPanel("center1");
42903 layout.endUpdate();
42906 <b>The container the layout is rendered into can be either the body element or any other element.
42907 If it is not the body element, the container needs to either be an absolute positioned element,
42908 or you will need to add "position:relative" to the css of the container. You will also need to specify
42909 the container size if it is not the body element.</b>
42912 * Create a new BorderLayout
42913 * @param {String/HTMLElement/Element} container The container this layout is bound to
42914 * @param {Object} config Configuration options
42916 Roo.BorderLayout = function(A, B){
42918 Roo.BorderLayout.superclass.constructor.call(this, A, B);
42919 this.factory = B.factory || Roo.BorderLayout.RegionFactory;
42920 for(var i = 0, len = this.factory.validRegions.length; i < len; i++) {
42921 var target = this.factory.validRegions[i];
42923 this.addRegion(target, B[target]);
42928 Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
42930 * Creates and adds a new region if it doesn't already exist.
42931 * @param {String} target The target region key (north, south, east, west or center).
42932 * @param {Object} config The regions config object
42933 * @return {BorderLayoutRegion} The new region
42935 addRegion : function(C, D){
42936 if(!this.regions[C]){
42937 var r = this.factory.create(C, this, D);
42938 this.bindRegion(C, r);
42940 return this.regions[C];
42944 bindRegion : function(E, r){
42945 this.regions[E] = r;
42946 r.on("visibilitychange", this.layout, this);
42947 r.on("paneladded", this.layout, this);
42948 r.on("panelremoved", this.layout, this);
42949 r.on("invalidated", this.layout, this);
42950 r.on("resized", this.onRegionResized, this);
42951 r.on("collapsed", this.onRegionCollapsed, this);
42952 r.on("expanded", this.onRegionExpanded, this);
42956 * Performs a layout update.
42958 layout : function(){
42959 if(this.updating) return;
42960 var F = this.getViewSize();
42967 //var x = 0, y = 0;
42969 var rs = this.regions;
42970 var K = rs["north"];
42971 var L = rs["south"];
42972 var M = rs["west"];
42973 var N = rs["east"];
42974 var O = rs["center"];
42975 //if(this.hideOnLayout){ // not supported anymore
42976 //c.el.setStyle("display", "none");
42978 if(K && K.isVisible()){
42979 var b = K.getBox();
42980 var m = K.getMargins();
42981 b.width = w - (m.left+m.right);
42984 I = b.height + b.y + m.bottom;
42986 K.updateBox(this.safeBox(b));
42988 if(L && L.isVisible()){
42989 var b = L.getBox();
42990 var m = L.getMargins();
42991 b.width = w - (m.left+m.right);
42993 var totalHeight = (b.height + m.top + m.bottom);
42994 b.y = h - totalHeight + m.top;
42996 L.updateBox(this.safeBox(b));
42998 if(M && M.isVisible()){
42999 var b = M.getBox();
43000 var m = M.getMargins();
43001 b.height = H - (m.top+m.bottom);
43004 var totalWidth = (b.width + m.left + m.right);
43007 M.updateBox(this.safeBox(b));
43009 if(N && N.isVisible()){
43010 var b = N.getBox();
43011 var m = N.getMargins();
43012 b.height = H - (m.top+m.bottom);
43013 var totalWidth = (b.width + m.left + m.right);
43014 b.x = w - totalWidth + m.left;
43017 N.updateBox(this.safeBox(b));
43020 var m = O.getMargins();
43024 width: G - (m.left+m.right),
43025 height: H - (m.top+m.bottom)
43027 //if(this.hideOnLayout){
43028 //center.el.setStyle("display", "block");
43030 O.updateBox(this.safeBox(centerBox));
43034 this.fireEvent("layout", this);
43038 safeBox : function(P){
43039 P.width = Math.max(0, P.width);
43040 P.height = Math.max(0, P.height);
43045 * Adds a ContentPanel (or subclass) to this layout.
43046 * @param {String} target The target region key (north, south, east, west or center).
43047 * @param {Roo.ContentPanel} panel The panel to add
43048 * @return {Roo.ContentPanel} The added panel
43050 add : function(Q, R){
43052 Q = Q.toLowerCase();
43053 return this.regions[Q].add(R);
43057 * Remove a ContentPanel (or subclass) to this layout.
43058 * @param {String} target The target region key (north, south, east, west or center).
43059 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
43060 * @return {Roo.ContentPanel} The removed panel
43062 remove : function(S, T){
43063 S = S.toLowerCase();
43064 return this.regions[S].remove(T);
43068 * Searches all regions for a panel with the specified id
43069 * @param {String} panelId
43070 * @return {Roo.ContentPanel} The panel or null if it wasn't found
43072 findPanel : function(U){
43073 var rs = this.regions;
43075 if(typeof rs[S] != "function"){
43076 var p = rs[S].getPanel(U);
43086 * Searches all regions for a panel with the specified id and activates (shows) it.
43087 * @param {String/ContentPanel} panelId The panels id or the panel itself
43088 * @return {Roo.ContentPanel} The shown panel or null
43090 showPanel : function(V) {
43091 var rs = this.regions;
43094 if(typeof r != "function"){
43096 return r.showPanel(V);
43104 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
43105 * @param {Roo.state.Provider} provider (optional) An alternate state provider
43107 restoreState : function(W){
43109 W = Roo.state.Manager;
43111 var sm = new Roo.LayoutStateManager();
43116 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
43117 * object should contain properties for each region to add ContentPanels to, and each property's value should be
43118 * a valid ContentPanel config object. Example:
43120 // Create the main layout
43121 var layout = new Roo.BorderLayout('main-ct', {
43132 // Create and add multiple ContentPanels at once via configs
43135 id: 'source-files',
43137 title:'Ext Source Files',
43150 * @param {Object} regions An object containing ContentPanel configs by region name
43152 batchAdd : function(X){
43153 this.beginUpdate();
43154 for(var rname in X){
43155 var lr = this.regions[rname];
43157 this.addTypedPanels(lr, X[rname]);
43165 addTypedPanels : function(lr, ps){
43166 if(typeof ps == 'string'){
43167 lr.add(new Roo.ContentPanel(ps));
43169 else if(ps instanceof Array){
43170 for(var i =0, len = ps.length; i < len; i++){
43171 this.addTypedPanels(lr, ps[i]);
43174 else if(!ps.events){ // raw config?
43176 delete ps.el; // prevent conflict
43177 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
43179 else { // panel object assumed!
43184 * Adds a xtype elements to the layout.
43188 xtype : 'ContentPanel',
43195 xtype : 'NestedLayoutPanel',
43201 items : [ ... list of content panels or nested layout panels.. ]
43205 * @param {Object} cfg Xtype definition of item to add.
43207 addxtype : function(Y)
43209 // basically accepts a pannel...
43210 // can accept a layout region..!?!?
43211 // console.log('BorderLayout add ' + cfg.xtype)
43213 if (!Y.xtype.match(/Panel$/)) {
43230 case 'ContentPanel': // ContentPanel (el, cfg)
43232 Z = new Roo[Y.xtype](Y); // new panel!!!!!
43234 var el = this.el.createChild();
43235 Z = new Roo[Y.xtype](el, Y); // new panel!!!!!
43243 case 'TreePanel': // our new panel!
43244 Y.el = this.el.createChild();
43245 Z = new Roo[Y.xtype](Y); // new panel!!!!!
43249 case 'NestedLayoutPanel':
43250 // create a new Layout (which is a Border Layout...
43251 var el = this.el.createChild();
43252 var clayout = Y.layout;
43254 clayout.items = clayout.items || [];
43255 // replace this exitems with the clayout ones..
43259 if (a == 'center' && this.active && this.getRegion('center').panels.length < 1) {
43260 Y.background = false;
43262 var layout = new Roo.BorderLayout(el, clayout);
43264 Z = new Roo[Y.xtype](layout, Y); // new panel!!!!!
43265 //console.log('adding nested layout panel ' + cfg.toSource());
43272 // needs grid and region
43274 //var el = this.getRegion(region).el.createChild();
43275 var el = this.el.createChild();
43276 // create the grid first...
43278 var grid = new Roo.grid[Y.grid.xtype](el, Y.grid);
43280 if (a == 'center' && this.active ) {
43281 Y.background = false;
43284 Z = new Roo[Y.xtype](grid, Y); // new panel!!!!!
43287 if (Y.background) {
43288 Z.on('activate', function(gp) {
43289 if (!gp.grid.rendered) {
43302 alert("Can not add '" + Y.xtype + "' to BorderLayout");
43304 // GridPanel (grid, cfg)
43308 this.beginUpdate();
43310 Roo.each(c, function(i) {
43320 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
43321 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
43322 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
43323 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
43326 var CP = Roo.ContentPanel;
43328 var layout = Roo.BorderLayout.create({
43332 panels: [new CP("north", "North")]
43341 panels: [new CP("west", {title: "West"})]
43350 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
43359 panels: [new CP("south", {title: "South", closable: true})]
43366 preferredTabWidth: 150,
43368 new CP("center1", {title: "Close Me", closable: true}),
43369 new CP("center2", {title: "Center Panel", closable: false})
43374 layout.getRegion("center").showPanel("center1");
43379 Roo.BorderLayout.create = function(d, e){
43380 var f = new Roo.BorderLayout(e || document.body, d);
43382 var g = Roo.BorderLayout.RegionFactory.validRegions;
43383 for(var j = 0, jlen = g.length; j < jlen; j++){
43385 if(f.regions[lr] && d[lr].panels){
43386 var r = f.regions[lr];
43387 var ps = d[lr].panels;
43388 f.addTypedPanels(r, ps);
43397 Roo.BorderLayout.RegionFactory = {
43399 validRegions : ["north","south","east","west","center"],
43402 create : function(k, l, n){
43403 k = k.toLowerCase();
43404 if(n.lightweight || n.basic){
43405 return new Roo.BasicLayoutRegion(l, n, k);
43409 return new Roo.NorthLayoutRegion(l, n);
43411 return new Roo.SouthLayoutRegion(l, n);
43413 return new Roo.EastLayoutRegion(l, n);
43415 return new Roo.WestLayoutRegion(l, n);
43417 return new Roo.CenterLayoutRegion(l, n);
43419 throw 'Layout region "'+k+'" not supported.';
43424 * Ext JS Library 1.1.1
43425 * Copyright(c) 2006-2007, Ext JS, LLC.
43427 * Originally Released Under LGPL - original licence link has changed is not relivant.
43430 * <script type="text/javascript">
43434 * @class Roo.BasicLayoutRegion
43435 * @extends Roo.util.Observable
43436 * This class represents a lightweight region in a layout manager. This region does not move dom nodes
43437 * and does not have a titlebar, tabs or any other features. All it does is size and position
43438 * panels. To create a BasicLayoutRegion, add lightweight:true or basic:true to your regions config.
43440 Roo.BasicLayoutRegion = function(A, B, C, D){
43445 * @scope Roo.BasicLayoutRegion
43449 * @event beforeremove
43450 * Fires before a panel is removed (or closed). To cancel the removal set "e.cancel = true" on the event argument.
43451 * @param {Roo.LayoutRegion} this
43452 * @param {Roo.ContentPanel} panel The panel
43453 * @param {Object} e The cancel event object
43455 "beforeremove" : true,
43457 * @event invalidated
43458 * Fires when the layout for this region is changed.
43459 * @param {Roo.LayoutRegion} this
43461 "invalidated" : true,
43463 * @event visibilitychange
43464 * Fires when this region is shown or hidden
43465 * @param {Roo.LayoutRegion} this
43466 * @param {Boolean} visibility true or false
43468 "visibilitychange" : true,
43470 * @event paneladded
43471 * Fires when a panel is added.
43472 * @param {Roo.LayoutRegion} this
43473 * @param {Roo.ContentPanel} panel The panel
43475 "paneladded" : true,
43477 * @event panelremoved
43478 * Fires when a panel is removed.
43479 * @param {Roo.LayoutRegion} this
43480 * @param {Roo.ContentPanel} panel The panel
43482 "panelremoved" : true,
43485 * Fires when this region is collapsed.
43486 * @param {Roo.LayoutRegion} this
43488 "collapsed" : true,
43491 * Fires when this region is expanded.
43492 * @param {Roo.LayoutRegion} this
43497 * Fires when this region is slid into view.
43498 * @param {Roo.LayoutRegion} this
43500 "slideshow" : true,
43503 * Fires when this region slides out of view.
43504 * @param {Roo.LayoutRegion} this
43506 "slidehide" : true,
43508 * @event panelactivated
43509 * Fires when a panel is activated.
43510 * @param {Roo.LayoutRegion} this
43511 * @param {Roo.ContentPanel} panel The activated panel
43513 "panelactivated" : true,
43516 * Fires when the user resizes this region.
43517 * @param {Roo.LayoutRegion} this
43518 * @param {Number} newSize The new size (width for east/west, height for north/south)
43522 /** A collection of panels in this region. @type Roo.util.MixedCollection */
43523 this.panels = new Roo.util.MixedCollection();
43524 this.panels.getKey = this.getPanelId.createDelegate(this);
43526 this.activePanel = null;
43527 // ensure listeners are added...
43529 if (B.listeners || B.events) {
43530 Roo.BasicLayoutRegion.superclass.constructor.call(this, {
43531 listeners : B.listeners || {},
43532 events : B.events || {}
43537 this.applyConfig(B);
43541 Roo.extend(Roo.BasicLayoutRegion, Roo.util.Observable, {
43542 getPanelId : function(p){
43546 applyConfig : function(E){
43547 this.margins = E.margins || this.margins || {top: 0, left: 0, right:0, bottom: 0};
43553 * Resizes the region to the specified size. For vertical regions (west, east) this adjusts
43554 * the width, for horizontal (north, south) the height.
43555 * @param {Number} newSize The new width or height
43557 resizeTo : function(F){
43558 var el = this.el ? this.el :
43559 (this.activePanel ? this.activePanel.getEl() : null);
43561 switch(this.position){
43565 this.fireEvent("resized", this, F);
43570 this.fireEvent("resized", this, F);
43576 getBox : function(){
43577 return this.activePanel ? this.activePanel.getEl().getBox(false, true) : null;
43580 getMargins : function(){
43581 return this.margins;
43584 updateBox : function(G){
43586 var el = this.activePanel.getEl();
43587 el.dom.style.left = G.x + "px";
43588 el.dom.style.top = G.y + "px";
43589 this.activePanel.setSize(G.width, G.height);
43593 * Returns the container element for this region.
43594 * @return {Roo.Element}
43596 getEl : function(){
43597 return this.activePanel;
43601 * Returns true if this region is currently visible.
43602 * @return {Boolean}
43604 isVisible : function(){
43605 return this.activePanel ? true : false;
43608 setActivePanel : function(H){
43609 H = this.getPanel(H);
43610 if(this.activePanel && this.activePanel != H){
43611 this.activePanel.setActiveState(false);
43612 this.activePanel.getEl().setLeftTop(-10000,-10000);
43615 this.activePanel = H;
43616 H.setActiveState(true);
43618 H.setSize(this.box.width, this.box.height);
43621 this.fireEvent("panelactivated", this, H);
43622 this.fireEvent("invalidated");
43626 * Show the specified panel.
43627 * @param {Number/String/ContentPanel} panelId The panels index, id or the panel itself
43628 * @return {Roo.ContentPanel} The shown panel or null
43630 showPanel : function(I){
43631 if(I = this.getPanel(I)){
43632 this.setActivePanel(I);
43638 * Get the active panel for this region.
43639 * @return {Roo.ContentPanel} The active panel or null
43641 getActivePanel : function(){
43642 return this.activePanel;
43646 * Add the passed ContentPanel(s)
43647 * @param {ContentPanel...} panel The ContentPanel(s) to add (you can pass more than one)
43648 * @return {Roo.ContentPanel} The panel added (if only one was added)
43651 if(arguments.length > 1){
43652 for(var i = 0, len = arguments.length; i < len; i++) {
43653 this.add(arguments[i]);
43657 if(this.hasPanel(J)){
43661 var el = J.getEl();
43662 if(el.dom.parentNode != this.mgr.el.dom){
43663 this.mgr.el.dom.appendChild(el.dom);
43669 this.panels.add(J);
43670 el.setStyle("position", "absolute");
43672 this.setActivePanel(J);
43673 if(this.config.initialSize && this.panels.getCount()==1){
43674 this.resizeTo(this.config.initialSize);
43678 this.fireEvent("paneladded", this, J);
43683 * Returns true if the panel is in this region.
43684 * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself
43685 * @return {Boolean}
43687 hasPanel : function(K){
43688 if(typeof K == "object"){ // must be panel obj
43691 return this.getPanel(K) ? true : false;
43695 * Removes the specified panel. If preservePanel is not true (either here or in the config), the panel is destroyed.
43696 * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself
43697 * @param {Boolean} preservePanel Overrides the config preservePanel option
43698 * @return {Roo.ContentPanel} The panel that was removed
43700 remove : function(L, M){
43701 L = this.getPanel(L);
43706 this.fireEvent("beforeremove", this, L, e);
43707 if(e.cancel === true){
43711 this.panels.removeKey(N);
43716 * Returns the panel specified or null if it's not in this region.
43717 * @param {Number/String/ContentPanel} panel The panels index, id or the panel itself
43718 * @return {Roo.ContentPanel}
43720 getPanel : function(id){
43721 if(typeof id == "object"){ // must be panel obj
43724 return this.panels.get(id);
43728 * Returns this regions position (north/south/east/west/center).
43731 getPosition: function(){
43732 return this.position;
43737 * Ext JS Library 1.1.1
43738 * Copyright(c) 2006-2007, Ext JS, LLC.
43740 * Originally Released Under LGPL - original licence link has changed is not relivant.
43743 * <script type="text/javascript">
43747 * @class Roo.LayoutRegion
43748 * @extends Roo.BasicLayoutRegion
43749 * This class represents a region in a layout manager.
43750 * @cfg {Boolean} collapsible False to disable collapsing (defaults to true)
43751 * @cfg {Boolean} collapsed True to set the initial display to collapsed (defaults to false)
43752 * @cfg {Boolean} floatable False to disable floating (defaults to true)
43753 * @cfg {Object} margins Margins for the element (defaults to {top: 0, left: 0, right:0, bottom: 0})
43754 * @cfg {Object} cmargins Margins for the element when collapsed (defaults to: north/south {top: 2, left: 0, right:0, bottom: 2} or east/west {top: 0, left: 2, right:2, bottom: 0})
43755 * @cfg {String} tabPosition "top" or "bottom" (defaults to "bottom")
43756 * @cfg {String} collapsedTitle Optional string message to display in the collapsed block of a north or south region
43757 * @cfg {Boolean} alwaysShowTabs True to always display tabs even when there is only 1 panel (defaults to false)
43758 * @cfg {Boolean} autoScroll True to enable overflow scrolling (defaults to false)
43759 * @cfg {Boolean} titlebar True to display a title bar (defaults to true)
43760 * @cfg {String} title The title for the region (overrides panel titles)
43761 * @cfg {Boolean} animate True to animate expand/collapse (defaults to false)
43762 * @cfg {Boolean} autoHide False to disable auto hiding when the mouse leaves the "floated" region (defaults to true)
43763 * @cfg {Boolean} preservePanels True to preserve removed panels so they can be readded later (defaults to false)
43764 * @cfg {Boolean} closeOnTab True to place the close icon on the tabs instead of the region titlebar (defaults to false)
43765 * @cfg {Boolean} hideTabs True to hide the tab strip (defaults to false)
43766 * @cfg {Boolean} resizeTabs True to enable automatic tab resizing. This will resize the tabs so they are all the same size and fit within
43767 * the space available, similar to FireFox 1.5 tabs (defaults to false)
43768 * @cfg {Number} minTabWidth The minimum tab width (defaults to 40)
43769 * @cfg {Number} preferredTabWidth The preferred tab width (defaults to 150)
43770 * @cfg {Boolean} showPin True to show a pin button
43771 * @cfg {Boolean} hidden True to start the region hidden (defaults to false)
43772 * @cfg {Boolean} hideWhenEmpty True to hide the region when it has no panels
43773 * @cfg {Boolean} disableTabTips True to disable tab tooltips
43774 * @cfg {Number} width For East/West panels
43775 * @cfg {Number} height For North/South panels
43776 * @cfg {Boolean} split To show the splitter
43778 Roo.LayoutRegion = function(A, B, C){
43779 Roo.LayoutRegion.superclass.constructor.call(this, A, B, C, true);
43780 var dh = Roo.DomHelper;
43781 /** This region's container element
43782 * @type Roo.Element */
43783 this.el = dh.append(A.el.dom, {tag: "div", cls: "x-layout-panel x-layout-panel-" + this.position}, true);
43784 /** This region's title element
43785 * @type Roo.Element */
43787 this.titleEl = dh.append(this.el.dom, {tag: "div", unselectable: "on", cls: "x-unselectable x-layout-panel-hd x-layout-title-"+this.position, children:[
43788 {tag: "span", cls: "x-unselectable x-layout-panel-hd-text", unselectable: "on", html: " "},
43789 {tag: "div", cls: "x-unselectable x-layout-panel-hd-tools", unselectable: "on"}
43791 this.titleEl.enableDisplayMode();
43792 /** This region's title text element
43793 * @type HTMLElement */
43794 this.titleTextEl = this.titleEl.dom.firstChild;
43795 this.tools = Roo.get(this.titleEl.dom.childNodes[1], true);
43796 this.closeBtn = this.createTool(this.tools.dom, "x-layout-close");
43797 this.closeBtn.enableDisplayMode();
43798 this.closeBtn.on("click", this.closeClicked, this);
43799 this.closeBtn.hide();
43801 this.createBody(B);
43802 this.visible = true;
43803 this.collapsed = false;
43805 if(B.hideWhenEmpty){
43807 this.on("paneladded", this.validateVisibility, this);
43808 this.on("panelremoved", this.validateVisibility, this);
43811 this.applyConfig(B);
43814 Roo.extend(Roo.LayoutRegion, Roo.BasicLayoutRegion, {
43816 createBody : function(){
43817 /** This region's body element
43818 * @type Roo.Element */
43819 this.bodyEl = this.el.createChild({tag: "div", cls: "x-layout-panel-body"});
43822 applyConfig : function(c){
43823 if(c.collapsible && this.position != "center" && !this.collapsedEl){
43824 var dh = Roo.DomHelper;
43825 if(c.titlebar !== false){
43826 this.collapseBtn = this.createTool(this.tools.dom, "x-layout-collapse-"+this.position);
43827 this.collapseBtn.on("click", this.collapse, this);
43828 this.collapseBtn.enableDisplayMode();
43830 if(c.showPin === true || this.showPin){
43831 this.stickBtn = this.createTool(this.tools.dom, "x-layout-stick");
43832 this.stickBtn.enableDisplayMode();
43833 this.stickBtn.on("click", this.expand, this);
43834 this.stickBtn.hide();
43838 /** This region's collapsed element
43839 * @type Roo.Element */
43840 this.collapsedEl = dh.append(this.mgr.el.dom, {cls: "x-layout-collapsed x-layout-collapsed-"+this.position, children:[
43841 {cls: "x-layout-collapsed-tools", children:[{cls: "x-layout-ctools-inner"}]}
43843 if(c.floatable !== false){
43844 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
43845 this.collapsedEl.on("click", this.collapseClick, this);
43848 if(c.collapsedTitle && (this.position == "north" || this.position== "south")) {
43849 this.collapsedTitleTextEl = dh.append(this.collapsedEl.dom, {tag: "div", cls: "x-unselectable x-layout-panel-hd-text",
43850 id: "message", unselectable: "on", style:{"float":"left"}});
43851 this.collapsedTitleTextEl.innerHTML = c.collapsedTitle;
43854 this.expandBtn = this.createTool(this.collapsedEl.dom.firstChild.firstChild, "x-layout-expand-"+this.position);
43855 this.expandBtn.on("click", this.expand, this);
43857 if(this.collapseBtn){
43858 this.collapseBtn.setVisible(c.collapsible == true);
43861 this.cmargins = c.cmargins || this.cmargins ||
43862 (this.position == "west" || this.position == "east" ?
43863 {top: 0, left: 2, right:2, bottom: 0} :
43864 {top: 2, left: 0, right:0, bottom: 2});
43865 this.margins = c.margins || this.margins || {top: 0, left: 0, right:0, bottom: 0};
43866 this.bottomTabs = c.tabPosition != "top";
43867 this.autoScroll = c.autoScroll || false;
43868 if(this.autoScroll){
43869 this.bodyEl.setStyle("overflow", "auto");
43871 this.bodyEl.setStyle("overflow", "hidden");
43873 //if(c.titlebar !== false){
43874 if((!c.titlebar && !c.title) || c.titlebar === false){
43875 this.titleEl.hide();
43877 this.titleEl.show();
43879 this.titleTextEl.innerHTML = c.title;
43884 this.duration = c.duration || .30;
43885 this.slideDuration = c.slideDuration || .45;
43888 this.collapse(true);
43895 * Returns true if this region is currently visible.
43896 * @return {Boolean}
43898 isVisible : function(){
43899 return this.visible;
43903 * Updates the title for collapsed north/south regions (used with {@link #collapsedTitle} config option)
43904 * @param {String} title (optional) The title text (accepts HTML markup, defaults to the numeric character reference for a non-breaking space, "&#160;")
43906 setCollapsedTitle : function(D){
43908 if(this.collapsedTitleTextEl){
43909 this.collapsedTitleTextEl.innerHTML = D;
43913 getBox : function(){
43915 if(!this.collapsed){
43916 b = this.el.getBox(false, true);
43918 b = this.collapsedEl.getBox(false, true);
43923 getMargins : function(){
43924 return this.collapsed ? this.cmargins : this.margins;
43927 highlight : function(){
43928 this.el.addClass("x-layout-panel-dragover");
43931 unhighlight : function(){
43932 this.el.removeClass("x-layout-panel-dragover");
43935 updateBox : function(E){
43937 if(!this.collapsed){
43938 this.el.dom.style.left = E.x + "px";
43939 this.el.dom.style.top = E.y + "px";
43940 this.updateBody(E.width, E.height);
43942 this.collapsedEl.dom.style.left = E.x + "px";
43943 this.collapsedEl.dom.style.top = E.y + "px";
43944 this.collapsedEl.setSize(E.width, E.height);
43947 this.tabs.autoSizeTabs();
43951 updateBody : function(w, h){
43953 this.el.setWidth(w);
43954 w -= this.el.getBorderWidth("rl");
43955 if(this.config.adjustments){
43956 w += this.config.adjustments[0];
43960 this.el.setHeight(h);
43961 h = this.titleEl && this.titleEl.isDisplayed() ? h - (this.titleEl.getHeight()||0) : h;
43962 h -= this.el.getBorderWidth("tb");
43963 if(this.config.adjustments){
43964 h += this.config.adjustments[1];
43967 this.bodyEl.setHeight(h);
43969 h = this.tabs.syncHeight(h);
43972 if(this.panelSize){
43973 w = w !== null ? w : this.panelSize.width;
43974 h = h !== null ? h : this.panelSize.height;
43976 if(this.activePanel){
43977 var el = this.activePanel.getEl();
43978 w = w !== null ? w : el.getWidth();
43979 h = h !== null ? h : el.getHeight();
43980 this.panelSize = {width: w, height: h};
43981 this.activePanel.setSize(w, h);
43983 if(Roo.isIE && this.tabs){
43984 this.tabs.el.repaint();
43989 * Returns the container element for this region.
43990 * @return {Roo.Element}
43992 getEl : function(){
43997 * Hides this region.
44000 if(!this.collapsed){
44001 this.el.dom.style.left = "-2000px";
44004 this.collapsedEl.dom.style.left = "-2000px";
44005 this.collapsedEl.hide();
44008 this.visible = false;
44009 this.fireEvent("visibilitychange", this, false);
44013 * Shows this region if it was previously hidden.
44016 if(!this.collapsed){
44019 this.collapsedEl.show();
44022 this.visible = true;
44023 this.fireEvent("visibilitychange", this, true);
44026 closeClicked : function(){
44027 if(this.activePanel){
44028 this.remove(this.activePanel);
44032 collapseClick : function(e){
44034 e.stopPropagation();
44037 e.stopPropagation();
44043 * Collapses this region.
44044 * @param {Boolean} skipAnim (optional) true to collapse the element without animation (if animate is true)
44046 collapse : function(F){
44047 if(this.collapsed) return;
44048 this.collapsed = true;
44050 this.split.el.hide();
44052 if(this.config.animate && F !== true){
44053 this.fireEvent("invalidated", this);
44054 this.animateCollapse();
44056 this.el.setLocation(-20000,-20000);
44058 this.collapsedEl.show();
44059 this.fireEvent("collapsed", this);
44060 this.fireEvent("invalidated", this);
44064 animateCollapse : function(){
44069 * Expands this region if it was previously collapsed.
44070 * @param {Roo.EventObject} e The event that triggered the expand (or null if calling manually)
44071 * @param {Boolean} skipAnim (optional) true to expand the element without animation (if animate is true)
44073 expand : function(e, G){
44074 if(e) e.stopPropagation();
44075 if(!this.collapsed || this.el.hasActiveFx()) return;
44077 this.afterSlideIn();
44081 this.collapsed = false;
44082 if(this.config.animate && G !== true){
44083 this.animateExpand();
44087 this.split.el.show();
44090 this.collapsedEl.setLocation(-2000,-2000);
44091 this.collapsedEl.hide();
44092 this.fireEvent("invalidated", this);
44093 this.fireEvent("expanded", this);
44097 animateExpand : function(){
44101 initTabs : function(){
44102 this.bodyEl.setStyle("overflow", "hidden");
44103 var ts = new Roo.TabPanel(this.bodyEl.dom, {
44104 tabPosition: this.bottomTabs ? 'bottom' : 'top',
44105 disableTooltips: this.config.disableTabTips
44107 if(this.config.hideTabs){
44108 ts.stripWrap.setDisplayed(false);
44112 ts.resizeTabs = this.config.resizeTabs === true;
44113 ts.minTabWidth = this.config.minTabWidth || 40;
44114 ts.maxTabWidth = this.config.maxTabWidth || 250;
44115 ts.preferredTabWidth = this.config.preferredTabWidth || 150;
44116 ts.monitorResize = false;
44117 ts.bodyEl.setStyle("overflow", this.config.autoScroll ? "auto" : "hidden");
44118 ts.bodyEl.addClass('x-layout-tabs-body');
44119 this.panels.each(this.initPanelAsTab, this);
44122 initPanelAsTab : function(H){
44123 var ti = this.tabs.addTab(H.getEl().id, H.getTitle(), null,
44124 this.config.closeOnTab && H.isClosable());
44125 if(H.tabTip !== undefined){
44126 ti.setTooltip(H.tabTip);
44129 ti.on("activate", function(){
44130 this.setActivePanel(H);
44132 if(this.config.closeOnTab){
44133 ti.on("beforeclose", function(t, e){
44141 updatePanelTitle : function(I, J){
44142 if(this.activePanel == I){
44143 this.updateTitle(J);
44146 var ti = this.tabs.getTab(I.getEl().id);
44148 if(I.tabTip !== undefined){
44149 ti.setTooltip(I.tabTip);
44154 updateTitle : function(K){
44155 if(this.titleTextEl && !this.config.title){
44156 this.titleTextEl.innerHTML = (typeof K != "undefined" && K.length > 0 ? K : " ");
44160 setActivePanel : function(L){
44161 L = this.getPanel(L);
44162 if(this.activePanel && this.activePanel != L){
44163 this.activePanel.setActiveState(false);
44166 this.activePanel = L;
44167 L.setActiveState(true);
44168 if(this.panelSize){
44169 L.setSize(this.panelSize.width, this.panelSize.height);
44172 this.closeBtn.setVisible(!this.config.closeOnTab && !this.isSlid && L.isClosable());
44175 this.updateTitle(L.getTitle());
44177 this.fireEvent("invalidated", this);
44180 this.fireEvent("panelactivated", this, L);
44184 * Shows the specified panel.
44185 * @param {Number/String/ContentPanel} panelId The panel's index, id or the panel itself
44186 * @return {Roo.ContentPanel} The shown panel, or null if a panel could not be found from panelId
44188 showPanel : function(M){
44189 if(M = this.getPanel(M)){
44191 var tab = this.tabs.getTab(M.getEl().id);
44192 if(tab.isHidden()){
44193 this.tabs.unhideTab(tab.id);
44198 this.setActivePanel(M);
44205 * Get the active panel for this region.
44206 * @return {Roo.ContentPanel} The active panel or null
44208 getActivePanel : function(){
44209 return this.activePanel;
44212 validateVisibility : function(){
44213 if(this.panels.getCount() < 1){
44214 this.updateTitle(" ");
44215 this.closeBtn.hide();
44218 if(!this.isVisible()){
44225 * Adds the passed ContentPanel(s) to this region.
44226 * @param {ContentPanel...} panel The ContentPanel(s) to add (you can pass more than one)
44227 * @return {Roo.ContentPanel} The panel added (if only one was added; null otherwise)
44230 if(arguments.length > 1){
44231 for(var i = 0, len = arguments.length; i < len; i++) {
44232 this.add(arguments[i]);
44236 if(this.hasPanel(N)){
44242 this.panels.add(N);
44243 if(this.panels.getCount() == 1 && !this.config.alwaysShowTabs){
44244 this.bodyEl.dom.appendChild(N.getEl().dom);
44245 if(N.background !== true){
44246 this.setActivePanel(N);
44249 this.fireEvent("paneladded", this, N);
44255 this.initPanelAsTab(N);
44257 if(N.background !== true){
44258 this.tabs.activate(N.getEl().id);
44261 this.fireEvent("paneladded", this, N);
44266 * Hides the tab for the specified panel.
44267 * @param {Number/String/ContentPanel} panel The panel's index, id or the panel itself
44269 hidePanel : function(O){
44270 if(this.tabs && (O = this.getPanel(O))){
44271 this.tabs.hideTab(O.getEl().id);
44276 * Unhides the tab for a previously hidden panel.
44277 * @param {Number/String/ContentPanel} panel The panel's index, id or the panel itself
44279 unhidePanel : function(P){
44280 if(this.tabs && (P = this.getPanel(P))){
44281 this.tabs.unhideTab(P.getEl().id);
44285 clearPanels : function(){
44286 while(this.panels.getCount() > 0){
44287 this.remove(this.panels.first());
44292 * Removes the specified panel. If preservePanel is not true (either here or in the config), the panel is destroyed.
44293 * @param {Number/String/ContentPanel} panel The panel's index, id or the panel itself
44294 * @param {Boolean} preservePanel Overrides the config preservePanel option
44295 * @return {Roo.ContentPanel} The panel that was removed
44297 remove : function(Q, R){
44298 Q = this.getPanel(Q);
44303 this.fireEvent("beforeremove", this, Q, e);
44304 if(e.cancel === true){
44308 R = (typeof R != "undefined" ? R : (this.config.preservePanels === true || Q.preserve === true));
44310 this.panels.removeKey(S);
44312 document.body.appendChild(Q.getEl().dom);
44315 this.tabs.removeTab(Q.getEl().id);
44317 this.bodyEl.dom.removeChild(Q.getEl().dom);
44319 if(this.panels.getCount() == 1 && this.tabs && !this.config.alwaysShowTabs){
44320 var p = this.panels.first();
44321 var tempEl = document.createElement("div"); // temp holder to keep IE from deleting the node
44322 tempEl.appendChild(p.getEl().dom);
44323 this.bodyEl.update("");
44324 this.bodyEl.dom.appendChild(p.getEl().dom);
44326 this.updateTitle(p.getTitle());
44328 this.bodyEl.setStyle("overflow", this.config.autoScroll ? "auto" : "hidden");
44329 this.setActivePanel(p);
44333 if(this.activePanel == Q){
44334 this.activePanel = null;
44336 if(this.config.autoDestroy !== false && R !== true){
44337 try{Q.destroy();}catch(e){}
44340 this.fireEvent("panelremoved", this, Q);
44345 * Returns the TabPanel component used by this region
44346 * @return {Roo.TabPanel}
44348 getTabs : function(){
44352 createTool : function(T, U){
44353 var V = Roo.DomHelper.append(T, {tag: "div", cls: "x-layout-tools-button",
44354 children: [{tag: "div", cls: "x-layout-tools-button-inner " + U, html: " "}]}, true);
44355 V.addClassOnOver("x-layout-tools-button-over");
44361 * Ext JS Library 1.1.1
44362 * Copyright(c) 2006-2007, Ext JS, LLC.
44364 * Originally Released Under LGPL - original licence link has changed is not relivant.
44367 * <script type="text/javascript">
44373 * @class Roo.SplitLayoutRegion
44374 * @extends Roo.LayoutRegion
44375 * Adds a splitbar and other (private) useful functionality to a {@link Roo.LayoutRegion}.
44377 Roo.SplitLayoutRegion = function(A, B, C, D){
44379 Roo.SplitLayoutRegion.superclass.constructor.call(this, A, B, C);
44382 Roo.extend(Roo.SplitLayoutRegion, Roo.LayoutRegion, {
44383 splitTip : "Drag to resize.",
44384 collapsibleSplitTip : "Drag to resize. Double click to hide.",
44385 useSplitTips : false,
44387 applyConfig : function(E){
44388 Roo.SplitLayoutRegion.superclass.applyConfig.call(this, E);
44391 var splitEl = Roo.DomHelper.append(this.mgr.el.dom,
44392 {tag: "div", id: this.el.id + "-split", cls: "x-layout-split x-layout-split-"+this.position, html: " "});
44393 /** The SplitBar for this region
44394 * @type Roo.SplitBar */
44395 this.split = new Roo.SplitBar(splitEl, this.el, this.orientation);
44396 this.split.on("moved", this.onSplitMove, this);
44397 this.split.useShim = E.useShim === true;
44398 this.split.getMaximumSize = this[this.position == 'north' || this.position == 'south' ? 'getVMaxSize' : 'getHMaxSize'].createDelegate(this);
44399 if(this.useSplitTips){
44400 this.split.el.dom.title = E.collapsible ? this.collapsibleSplitTip : this.splitTip;
44403 this.split.el.on("dblclick", this.collapse, this);
44406 if(typeof E.minSize != "undefined"){
44407 this.split.minSize = E.minSize;
44409 if(typeof E.maxSize != "undefined"){
44410 this.split.maxSize = E.maxSize;
44412 if(E.hideWhenEmpty || E.hidden || E.collapsed){
44413 this.hideSplitter();
44418 getHMaxSize : function(){
44419 var F = this.config.maxSize || 10000;
44420 var G = this.mgr.getRegion("center");
44421 return Math.min(F, (this.el.getWidth()+G.getEl().getWidth())-G.getMinWidth());
44424 getVMaxSize : function(){
44425 var H = this.config.maxSize || 10000;
44426 var I = this.mgr.getRegion("center");
44427 return Math.min(H, (this.el.getHeight()+I.getEl().getHeight())-I.getMinHeight());
44430 onSplitMove : function(J, K){
44431 this.fireEvent("resized", this, K);
44435 * Returns the {@link Roo.SplitBar} for this region.
44436 * @return {Roo.SplitBar}
44438 getSplitBar : function(){
44443 this.hideSplitter();
44444 Roo.SplitLayoutRegion.superclass.hide.call(this);
44447 hideSplitter : function(){
44449 this.split.el.setLocation(-2000,-2000);
44450 this.split.el.hide();
44456 this.split.el.show();
44459 Roo.SplitLayoutRegion.superclass.show.call(this);
44462 beforeSlide: function(){
44463 if(Roo.isGecko){// firefox overflow auto bug workaround
44464 this.bodyEl.clip();
44465 if(this.tabs) this.tabs.bodyEl.clip();
44466 if(this.activePanel){
44467 this.activePanel.getEl().clip();
44469 if(this.activePanel.beforeSlide){
44470 this.activePanel.beforeSlide();
44476 afterSlide : function(){
44477 if(Roo.isGecko){// firefox overflow auto bug workaround
44478 this.bodyEl.unclip();
44479 if(this.tabs) this.tabs.bodyEl.unclip();
44480 if(this.activePanel){
44481 this.activePanel.getEl().unclip();
44482 if(this.activePanel.afterSlide){
44483 this.activePanel.afterSlide();
44489 initAutoHide : function(){
44490 if(this.autoHide !== false){
44491 if(!this.autoHideHd){
44492 var st = new Roo.util.DelayedTask(this.slideIn, this);
44493 this.autoHideHd = {
44494 "mouseout": function(e){
44495 if(!e.within(this.el, true)){
44499 "mouseover" : function(e){
44506 this.el.on(this.autoHideHd);
44510 clearAutoHide : function(){
44511 if(this.autoHide !== false){
44512 this.el.un("mouseout", this.autoHideHd.mouseout);
44513 this.el.un("mouseover", this.autoHideHd.mouseover);
44517 clearMonitor : function(){
44518 Roo.get(document).un("click", this.slideInIf, this);
44521 // these names are backwards but not changed for compat
44522 slideOut : function(){
44523 if(this.isSlid || this.el.hasActiveFx()){
44527 this.isSlid = true;
44528 if(this.collapseBtn){
44529 this.collapseBtn.hide();
44532 this.closeBtnState = this.closeBtn.getStyle('display');
44533 this.closeBtn.hide();
44535 this.stickBtn.show();
44539 this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
44540 this.beforeSlide();
44541 this.el.setStyle("z-index", 10001);
44542 this.el.slideIn(this.getSlideAnchor(), {
44543 callback: function(){
44545 this.initAutoHide();
44546 Roo.get(document).on("click", this.slideInIf, this);
44547 this.fireEvent("slideshow", this);
44554 afterSlideIn : function(){
44555 this.clearAutoHide();
44556 this.isSlid = false;
44557 this.clearMonitor();
44558 this.el.setStyle("z-index", "");
44559 if(this.collapseBtn){
44560 this.collapseBtn.show();
44563 this.closeBtn.setStyle('display', this.closeBtnState);
44565 this.stickBtn.hide();
44568 this.fireEvent("slidehide", this);
44571 slideIn : function(cb){
44572 if(!this.isSlid || this.el.hasActiveFx()){
44577 this.isSlid = false;
44578 this.beforeSlide();
44579 this.el.slideOut(this.getSlideAnchor(), {
44580 callback: function(){
44581 this.el.setLeftTop(-10000, -10000);
44583 this.afterSlideIn();
44591 slideInIf : function(e){
44592 if(!e.within(this.el)){
44597 animateCollapse : function(){
44598 this.beforeSlide();
44599 this.el.setStyle("z-index", 20000);
44600 var L = this.getSlideAnchor();
44601 this.el.slideOut(L, {
44602 callback : function(){
44603 this.el.setStyle("z-index", "");
44604 this.collapsedEl.slideIn(L, {duration:.3});
44606 this.el.setLocation(-10000,-10000);
44608 this.fireEvent("collapsed", this);
44615 animateExpand : function(){
44616 this.beforeSlide();
44617 this.el.alignTo(this.collapsedEl, this.getCollapseAnchor(), this.getExpandAdj());
44618 this.el.setStyle("z-index", 20000);
44619 this.collapsedEl.hide({
44622 this.el.slideIn(this.getSlideAnchor(), {
44623 callback : function(){
44624 this.el.setStyle("z-index", "");
44627 this.split.el.show();
44630 this.fireEvent("invalidated", this);
44631 this.fireEvent("expanded", this);
44659 getAnchor : function(){
44660 return this.anchors[this.position];
44663 getCollapseAnchor : function(){
44664 return this.canchors[this.position];
44667 getSlideAnchor : function(){
44668 return this.sanchors[this.position];
44671 getAlignAdj : function(){
44672 var cm = this.cmargins;
44673 switch(this.position){
44689 getExpandAdj : function(){
44690 var c = this.collapsedEl, cm = this.cmargins;
44691 switch(this.position){
44693 return [-(cm.right+c.getWidth()+cm.left), 0];
44696 return [cm.right+c.getWidth()+cm.left, 0];
44699 return [0, -(cm.top+cm.bottom+c.getHeight())];
44702 return [0, cm.top+cm.bottom+c.getHeight()];
44709 * Ext JS Library 1.1.1
44710 * Copyright(c) 2006-2007, Ext JS, LLC.
44712 * Originally Released Under LGPL - original licence link has changed is not relivant.
44715 * <script type="text/javascript">
44718 * These classes are private internal classes
44720 Roo.CenterLayoutRegion = function(A, B){
44721 Roo.LayoutRegion.call(this, A, B, "center");
44722 this.visible = true;
44723 this.minWidth = B.minWidth || 20;
44724 this.minHeight = B.minHeight || 20;
44727 Roo.extend(Roo.CenterLayoutRegion, Roo.LayoutRegion, {
44729 // center panel can't be hidden
44733 // center panel can't be hidden
44736 getMinWidth: function(){
44737 return this.minWidth;
44740 getMinHeight: function(){
44741 return this.minHeight;
44746 Roo.NorthLayoutRegion = function(C, D){
44747 Roo.LayoutRegion.call(this, C, D, "north", "n-resize");
44749 this.split.placement = Roo.SplitBar.TOP;
44750 this.split.orientation = Roo.SplitBar.VERTICAL;
44751 this.split.el.addClass("x-layout-split-v");
44753 var E = D.initialSize || D.height;
44754 if(typeof E != "undefined"){
44755 this.el.setHeight(E);
44758 Roo.extend(Roo.NorthLayoutRegion, Roo.SplitLayoutRegion, {
44759 orientation: Roo.SplitBar.VERTICAL,
44760 getBox : function(){
44761 if(this.collapsed){
44762 return this.collapsedEl.getBox();
44764 var F = this.el.getBox();
44766 F.height += this.split.el.getHeight();
44771 updateBox : function(G){
44772 if(this.split && !this.collapsed){
44773 G.height -= this.split.el.getHeight();
44774 this.split.el.setLeft(G.x);
44775 this.split.el.setTop(G.y+G.height);
44776 this.split.el.setWidth(G.width);
44778 if(this.collapsed){
44779 this.updateBody(G.width, null);
44782 Roo.LayoutRegion.prototype.updateBox.call(this, G);
44786 Roo.SouthLayoutRegion = function(H, I){
44787 Roo.SplitLayoutRegion.call(this, H, I, "south", "s-resize");
44789 this.split.placement = Roo.SplitBar.BOTTOM;
44790 this.split.orientation = Roo.SplitBar.VERTICAL;
44791 this.split.el.addClass("x-layout-split-v");
44793 var J = I.initialSize || I.height;
44794 if(typeof J != "undefined"){
44795 this.el.setHeight(J);
44798 Roo.extend(Roo.SouthLayoutRegion, Roo.SplitLayoutRegion, {
44799 orientation: Roo.SplitBar.VERTICAL,
44800 getBox : function(){
44801 if(this.collapsed){
44802 return this.collapsedEl.getBox();
44804 var K = this.el.getBox();
44806 var sh = this.split.el.getHeight();
44813 updateBox : function(L){
44814 if(this.split && !this.collapsed){
44815 var sh = this.split.el.getHeight();
44818 this.split.el.setLeft(L.x);
44819 this.split.el.setTop(L.y-sh);
44820 this.split.el.setWidth(L.width);
44822 if(this.collapsed){
44823 this.updateBody(L.width, null);
44826 Roo.LayoutRegion.prototype.updateBox.call(this, L);
44830 Roo.EastLayoutRegion = function(M, N){
44831 Roo.SplitLayoutRegion.call(this, M, N, "east", "e-resize");
44833 this.split.placement = Roo.SplitBar.RIGHT;
44834 this.split.orientation = Roo.SplitBar.HORIZONTAL;
44835 this.split.el.addClass("x-layout-split-h");
44837 var O = N.initialSize || N.width;
44838 if(typeof O != "undefined"){
44839 this.el.setWidth(O);
44842 Roo.extend(Roo.EastLayoutRegion, Roo.SplitLayoutRegion, {
44843 orientation: Roo.SplitBar.HORIZONTAL,
44844 getBox : function(){
44845 if(this.collapsed){
44846 return this.collapsedEl.getBox();
44848 var P = this.el.getBox();
44850 var sw = this.split.el.getWidth();
44857 updateBox : function(Q){
44858 if(this.split && !this.collapsed){
44859 var sw = this.split.el.getWidth();
44861 this.split.el.setLeft(Q.x);
44862 this.split.el.setTop(Q.y);
44863 this.split.el.setHeight(Q.height);
44866 if(this.collapsed){
44867 this.updateBody(null, Q.height);
44870 Roo.LayoutRegion.prototype.updateBox.call(this, Q);
44874 Roo.WestLayoutRegion = function(R, S){
44875 Roo.SplitLayoutRegion.call(this, R, S, "west", "w-resize");
44877 this.split.placement = Roo.SplitBar.LEFT;
44878 this.split.orientation = Roo.SplitBar.HORIZONTAL;
44879 this.split.el.addClass("x-layout-split-h");
44881 var T = S.initialSize || S.width;
44882 if(typeof T != "undefined"){
44883 this.el.setWidth(T);
44886 Roo.extend(Roo.WestLayoutRegion, Roo.SplitLayoutRegion, {
44887 orientation: Roo.SplitBar.HORIZONTAL,
44888 getBox : function(){
44889 if(this.collapsed){
44890 return this.collapsedEl.getBox();
44892 var U = this.el.getBox();
44894 U.width += this.split.el.getWidth();
44899 updateBox : function(V){
44900 if(this.split && !this.collapsed){
44901 var sw = this.split.el.getWidth();
44903 this.split.el.setLeft(V.x+V.width);
44904 this.split.el.setTop(V.y);
44905 this.split.el.setHeight(V.height);
44907 if(this.collapsed){
44908 this.updateBody(null, V.height);
44911 Roo.LayoutRegion.prototype.updateBox.call(this, V);
44917 * Ext JS Library 1.1.1
44918 * Copyright(c) 2006-2007, Ext JS, LLC.
44920 * Originally Released Under LGPL - original licence link has changed is not relivant.
44923 * <script type="text/javascript">
44928 * Private internal class for reading and applying state
44930 Roo.LayoutStateManager = function(A){
44931 // default empty state
44940 Roo.LayoutStateManager.prototype = {
44941 init : function(B, C){
44943 var D = C.get(B.id+"-layout-state");
44945 var wasUpdating = B.isUpdating();
44950 if(typeof D[key] != "function"){
44951 var rstate = D[key];
44952 var r = B.getRegion(key);
44955 r.resizeTo(rstate.size);
44957 if(rstate.collapsed == true){
44960 r.expand(null, true);
44973 B.on("regionresized", this.onRegionResized, this);
44974 B.on("regioncollapsed", this.onRegionCollapsed, this);
44975 B.on("regionexpanded", this.onRegionExpanded, this);
44978 storeState : function(){
44979 this.provider.set(this.layout.id+"-layout-state", this.state);
44982 onRegionResized : function(E, F){
44983 this.state[E.getPosition()].size = F;
44987 onRegionCollapsed : function(G){
44988 this.state[G.getPosition()].collapsed = true;
44992 onRegionExpanded : function(H){
44993 this.state[H.getPosition()].collapsed = false;
44999 * Ext JS Library 1.1.1
45000 * Copyright(c) 2006-2007, Ext JS, LLC.
45002 * Originally Released Under LGPL - original licence link has changed is not relivant.
45005 * <script type="text/javascript">
45008 * @class Roo.ContentPanel
45009 * @extends Roo.util.Observable
45010 * A basic ContentPanel element.
45011 * @cfg {Boolean} fitToFrame True for this panel to adjust its size to fit when the region resizes (defaults to false)
45012 * @cfg {Boolean} fitContainer When using {@link #fitToFrame} and {@link #resizeEl}, you can also fit the parent container (defaults to false)
45013 * @cfg {Boolean/Object} autoCreate True to auto generate the DOM element for this panel, or a {@link Roo.DomHelper} config of the element to create
45014 * @cfg {Boolean} closable True if the panel can be closed/removed
45015 * @cfg {Boolean} background True if the panel should not be activated when it is added (defaults to false)
45016 * @cfg {String/HTMLElement/Element} resizeEl An element to resize if {@link #fitToFrame} is true (instead of this panel's element)
45017 * @cfg {Toolbar} toolbar A toolbar for this panel
45018 * @cfg {Boolean} autoScroll True to scroll overflow in this panel (use with {@link #fitToFrame})
45019 * @cfg {String} title The title for this panel
45020 * @cfg {Array} adjustments Values to <b>add</b> to the width/height when doing a {@link #fitToFrame} (default is [0, 0])
45021 * @cfg {String} url Calls {@link #setUrl} with this value
45022 * @cfg {String/Object} params When used with {@link #url}, calls {@link #setUrl} with this value
45023 * @cfg {Boolean} loadOnce When used with {@link #url}, calls {@link #setUrl} with this value
45025 * Create a new ContentPanel.
45026 * @param {String/HTMLElement/Roo.Element} el The container element for this panel
45027 * @param {String/Object} config A string to set only the title or a config object
45028 * @param {String} content (optional) Set the HTML content for this panel
45029 * @param {String} region (optional) Used by xtype constructors to add to regions. (values center,east,west,south,north)
45031 Roo.ContentPanel = function(el, A, B){
45035 if(el.autoCreate || el.xtype){ // xtype is available if this is called from factory
45039 if (config && config.parentLayout) {
45040 el = config.parentLayout.el.createChild();
45043 if(el.autoCreate){ // xtype is available if this is called from factory
45048 this.el = Roo.get(el);
45049 if(!this.el && A && A.autoCreate){
45050 if(typeof A.autoCreate == "object"){
45051 if(!A.autoCreate.id){
45052 A.autoCreate.id = A.id||el;
45055 this.el = Roo.DomHelper.append(document.body,
45056 A.autoCreate, true);
45058 this.el = Roo.DomHelper.append(document.body,
45059 {tag: "div", cls: "x-layout-inactive-content", id: A.id||el}, true);
45063 this.closable = false;
45064 this.loaded = false;
45065 this.active = false;
45066 if(typeof A == "string"){
45069 Roo.apply(this, A);
45072 if (this.toolbar && !this.toolbar.el && this.toolbar.xtype) {
45073 this.wrapEl = this.el.wrap();
45074 this.toolbar = new Roo.Toolbar(this.el.insertSibling(false, 'before'), [] , this.toolbar);
45081 this.resizeEl = Roo.get(this.resizeEl, true);
45083 this.resizeEl = this.el;
45089 * Fires when this panel is activated.
45090 * @param {Roo.ContentPanel} this
45094 * @event deactivate
45095 * Fires when this panel is activated.
45096 * @param {Roo.ContentPanel} this
45098 "deactivate" : true,
45102 * Fires when this panel is resized if fitToFrame is true.
45103 * @param {Roo.ContentPanel} this
45104 * @param {Number} width The width after any component adjustments
45105 * @param {Number} height The height after any component adjustments
45109 if(this.autoScroll){
45110 this.resizeEl.setStyle("overflow", "auto");
45113 B = B || this.content;
45115 this.setContent(B);
45118 this.setUrl(this.url, this.params, this.loadOnce);
45124 Roo.ContentPanel.superclass.constructor.call(this);
45127 Roo.extend(Roo.ContentPanel, Roo.util.Observable, {
45129 setRegion : function(C){
45132 this.el.replaceClass("x-layout-inactive-content", "x-layout-active-content");
45134 this.el.replaceClass("x-layout-active-content", "x-layout-inactive-content");
45139 * Returns the toolbar for this Panel if one was configured.
45140 * @return {Roo.Toolbar}
45142 getToolbar : function(){
45143 return this.toolbar;
45146 setActiveState : function(D){
45149 this.fireEvent("deactivate", this);
45151 this.fireEvent("activate", this);
45155 * Updates this panel's element
45156 * @param {String} content The new content
45157 * @param {Boolean} loadScripts (optional) true to look for and process scripts
45159 setContent : function(E, F){
45160 this.el.update(E, F);
45163 ignoreResize : function(w, h){
45164 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
45167 this.lastSize = {width: w, height: h};
45172 * Get the {@link Roo.UpdateManager} for this panel. Enables you to perform Ajax updates.
45173 * @return {Roo.UpdateManager} The UpdateManager
45175 getUpdateManager : function(){
45176 return this.el.getUpdateManager();
45179 * Loads this content panel immediately with content from XHR. Note: to delay loading until the panel is activated, use {@link #setUrl}.
45180 * @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:
45183 url: "your-url.php",
45184 params: {param1: "foo", param2: "bar"}, // or a URL encoded string
45185 callback: yourFunction,
45186 scope: yourObject, //(optional scope)
45189 text: "Loading...",
45194 * The only required property is <i>url</i>. The optional properties <i>nocache</i>, <i>text</i> and <i>scripts</i>
45195 * are shorthand for <i>disableCaching</i>, <i>indicatorText</i> and <i>loadScripts</i> and are used to set their associated property on this panel UpdateManager instance.
45196 * @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}
45197 * @param {Function} callback (optional) Callback when transaction is complete -- called with signature (oElement, bSuccess, oResponse)
45198 * @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.
45199 * @return {Roo.ContentPanel} this
45202 var um = this.el.getUpdateManager();
45203 um.update.apply(um, arguments);
45209 * Set a URL to be used to load the content for this panel. When this panel is activated, the content will be loaded from that URL.
45210 * @param {String/Function} url The URL to load the content from or a function to call to get the URL
45211 * @param {String/Object} params (optional) The string params for the update call or an object of the params. See {@link Roo.UpdateManager#update} for more details. (Defaults to null)
45212 * @param {Boolean} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this panel is activated. (Defaults to false)
45213 * @return {Roo.UpdateManager} The UpdateManager
45215 setUrl : function(G, H, I){
45216 if(this.refreshDelegate){
45217 this.removeListener("activate", this.refreshDelegate);
45220 this.refreshDelegate = this._handleRefresh.createDelegate(this, [G, H, I]);
45221 this.on("activate", this.refreshDelegate);
45222 return this.el.getUpdateManager();
45225 _handleRefresh : function(J, K, L){
45226 if(!L || !this.loaded){
45227 var updater = this.el.getUpdateManager();
45228 updater.update(J, K, this._setLoaded.createDelegate(this));
45232 _setLoaded : function(){
45233 this.loaded = true;
45237 * Returns this panel's id
45240 getId : function(){
45245 * Returns this panel's element - used by regiosn to add.
45246 * @return {Roo.Element}
45248 getEl : function(){
45249 return this.wrapEl || this.el;
45252 adjustForComponents : function(M, N){
45253 if(this.resizeEl != this.el){
45254 M -= this.el.getFrameWidth('lr');
45255 N -= this.el.getFrameWidth('tb');
45258 var te = this.toolbar.getEl();
45259 N -= te.getHeight();
45262 if(this.adjustments){
45263 M += this.adjustments[0];
45264 N += this.adjustments[1];
45266 return {"width": M, "height": N};
45269 setSize : function(O, P){
45270 if(this.fitToFrame && !this.ignoreResize(O, P)){
45271 if(this.fitContainer && this.resizeEl != this.el){
45272 this.el.setSize(O, P);
45274 var size = this.adjustForComponents(O, P);
45275 this.resizeEl.setSize(this.autoWidth ? "auto" : size.width, this.autoHeight ? "auto" : size.height);
45276 this.fireEvent('resize', this, size.width, size.height);
45281 * Returns this panel's title
45284 getTitle : function(){
45289 * Set this panel's title
45290 * @param {String} title
45292 setTitle : function(Q){
45295 this.region.updatePanelTitle(this, Q);
45300 * Returns true is this panel was configured to be closable
45301 * @return {Boolean}
45303 isClosable : function(){
45304 return this.closable;
45307 beforeSlide : function(){
45309 this.resizeEl.clip();
45312 afterSlide : function(){
45314 this.resizeEl.unclip();
45318 * Force a content refresh from the URL specified in the {@link #setUrl} method.
45319 * Will fail silently if the {@link #setUrl} method has not been called.
45320 * This does not activate the panel, just updates its content.
45322 refresh : function(){
45323 if(this.refreshDelegate){
45324 this.loaded = false;
45325 this.refreshDelegate();
45330 * Destroys this panel
45332 destroy : function(){
45333 this.el.removeAllListeners();
45334 var R = document.createElement("span");
45335 R.appendChild(this.el.dom);
45342 * Adds a xtype elements to the panel - currently only supports Forms.
45352 * @param {Object} cfg Xtype definition of item to add.
45355 addxtype : function(S) {
45357 if (!S.xtype.match(/^Form$/)) {
45360 var el = this.el.createChild();
45362 this.form = new Roo.form.Form(S);
45365 if ( this.form.allItems.length) this.form.render(el.dom);
45372 * @class Roo.GridPanel
45373 * @extends Roo.ContentPanel
45375 * Create a new GridPanel.
45376 * @param {Roo.grid.Grid} grid The grid for this panel
45377 * @param {String/Object} config A string to set only the panel's title, or a config object
45379 Roo.GridPanel = function(T, U){
45382 this.wrapper = Roo.DomHelper.append(document.body, // wrapper for IE7 strict & safari scroll issue
45383 {tag: "div", cls: "x-layout-grid-wrapper x-layout-inactive-content"}, true);
45385 this.wrapper.dom.appendChild(T.getGridEl().dom);
45387 Roo.GridPanel.superclass.constructor.call(this, this.wrapper, U);
45390 this.toolbar.el.insertBefore(this.wrapper.dom.firstChild);
45392 // xtype created footer. - not sure if will work as we normally have to render first..
45393 if (this.footer && !this.footer.el && this.footer.xtype) {
45395 this.footer.container = this.grid.getView().getFooterPanel(true);
45396 this.footer.dataSource = this.grid.dataSource;
45397 this.footer = Roo.factory(this.footer, Roo);
45402 T.monitorWindowResize = false; // turn off autosizing
45403 T.autoHeight = false;
45404 T.autoWidth = false;
45406 this.grid.getGridEl().replaceClass("x-layout-inactive-content", "x-layout-component-panel");
45409 Roo.extend(Roo.GridPanel, Roo.ContentPanel, {
45410 getId : function(){
45411 return this.grid.id;
45415 * Returns the grid for this panel
45416 * @return {Roo.grid.Grid}
45418 getGrid : function(){
45422 setSize : function(V, W){
45423 if(!this.ignoreResize(V, W)){
45425 var size = this.adjustForComponents(V, W);
45426 T.getGridEl().setSize(size.width, size.height);
45431 beforeSlide : function(){
45432 this.grid.getView().scroller.clip();
45435 afterSlide : function(){
45436 this.grid.getView().scroller.unclip();
45439 destroy : function(){
45440 this.grid.destroy();
45442 Roo.GridPanel.superclass.destroy.call(this);
45448 * @class Roo.NestedLayoutPanel
45449 * @extends Roo.ContentPanel
45451 * Create a new NestedLayoutPanel.
45454 * @param {Roo.BorderLayout} layout The layout for this panel
45455 * @param {String/Object} config A string to set only the title or a config object
45457 Roo.NestedLayoutPanel = function(X, Y)
45459 // construct with only one argument..
45460 /* FIXME - implement nicer consturctors
45461 if (layout.layout) {
45463 layout = config.layout;
45464 delete config.layout;
45466 if (layout.xtype && !layout.getEl) {
45467 // then layout needs constructing..
45468 layout = Roo.factory(layout, Roo);
45472 Roo.NestedLayoutPanel.superclass.constructor.call(this, X.getEl(), Y);
45474 X.monitorWindowResize = false; // turn off autosizing
45476 this.layout.getEl().addClass("x-layout-nested-layout");
45482 Roo.extend(Roo.NestedLayoutPanel, Roo.ContentPanel, {
45484 setSize : function(Z, a){
45485 if(!this.ignoreResize(Z, a)){
45486 var size = this.adjustForComponents(Z, a);
45487 var el = this.layout.getEl();
45488 el.setSize(size.width, size.height);
45489 var touch = el.dom.offsetWidth;
45490 this.layout.layout();
45491 // ie requires a double layout on the first pass
45492 if(Roo.isIE && !this.initialized){
45493 this.initialized = true;
45494 this.layout.layout();
45499 // activate all subpanels if not currently active..
45501 setActiveState : function(b){
45504 this.fireEvent("deactivate", this);
45509 this.fireEvent("activate", this);
45510 // not sure if this should happen before or after..
45511 if (!this.layout) {
45512 return; // should not happen..
45515 for (var r in this.layout.regions) {
45516 c = this.layout.getRegion(r);
45517 if (c.getActivePanel()) {
45518 //reg.showPanel(reg.getActivePanel()); // force it to activate..
45519 c.setActivePanel(c.getActivePanel());
45522 if (!c.panels.length) {
45526 c.showPanel(c.getPanel(0));
45535 * Returns the nested BorderLayout for this panel
45536 * @return {Roo.BorderLayout}
45538 getLayout : function(){
45539 return this.layout;
45543 * Adds a xtype elements to the layout of the nested panel
45547 xtype : 'ContentPanel',
45554 xtype : 'NestedLayoutPanel',
45560 items : [ ... list of content panels or nested layout panels.. ]
45564 * @param {Object} cfg Xtype definition of item to add.
45566 addxtype : function(d) {
45567 return this.layout.addxtype(d);
45572 Roo.ScrollPanel = function(el, e, f){
45574 e.fitToFrame = true;
45575 Roo.ScrollPanel.superclass.constructor.call(this, el, e, f);
45577 this.el.dom.style.overflow = "hidden";
45578 var g = this.el.wrap({cls: "x-scroller x-layout-inactive-content"});
45579 this.el.removeClass("x-layout-inactive-content");
45580 this.el.on("mousewheel", this.onWheel, this);
45582 var up = g.createChild({cls: "x-scroller-up", html: " "}, this.el.dom);
45583 var i = g.createChild({cls: "x-scroller-down", html: " "});
45584 up.unselectable(); i.unselectable();
45585 up.on("click", this.scrollUp, this);
45586 i.on("click", this.scrollDown, this);
45587 up.addClassOnOver("x-scroller-btn-over");
45588 i.addClassOnOver("x-scroller-btn-over");
45589 up.addClassOnClick("x-scroller-btn-click");
45590 i.addClassOnClick("x-scroller-btn-click");
45591 this.adjustments = [0, -(up.getHeight() + i.getHeight())];
45593 this.resizeEl = this.el;
45594 this.el = g; this.up = up; this.down = i;
45597 Roo.extend(Roo.ScrollPanel, Roo.ContentPanel, {
45599 wheelIncrement : 5,
45600 scrollUp : function(){
45601 this.resizeEl.scroll("up", this.increment, {callback: this.afterScroll, scope: this});
45604 scrollDown : function(){
45605 this.resizeEl.scroll("down", this.increment, {callback: this.afterScroll, scope: this});
45608 afterScroll : function(){
45609 var el = this.resizeEl;
45610 var t = el.dom.scrollTop, h = el.dom.scrollHeight, ch = el.dom.clientHeight;
45611 this.up[t == 0 ? "addClass" : "removeClass"]("x-scroller-btn-disabled");
45612 this.down[h - t <= ch ? "addClass" : "removeClass"]("x-scroller-btn-disabled");
45615 setSize : function(){
45616 Roo.ScrollPanel.superclass.setSize.apply(this, arguments);
45617 this.afterScroll();
45620 onWheel : function(e){
45621 var d = e.getWheelDelta();
45622 this.resizeEl.dom.scrollTop -= (d*this.wheelIncrement);
45623 this.afterScroll();
45627 setContent : function(j, k){
45628 this.resizeEl.update(j, k);
45642 * @class Roo.TreePanel
45643 * @extends Roo.ContentPanel
45645 * Create a new TreePanel.
45646 * @param {String/Object} config A string to set only the panel's title, or a config object
45647 * @cfg {Roo.tree.TreePanel} tree The tree TreePanel, with config etc.
45649 Roo.TreePanel = function(l){
45653 delete l.el; // hopefull!
45654 Roo.TreePanel.superclass.constructor.call(this, el, l);
45655 var n = el.createChild();
45656 this.tree = new Roo.tree.TreePanel(n , m);
45657 //console.log(tree);
45658 this.on('activate', function()
45660 if (this.tree.rendered) {
45664 //console.log('render tree');
45665 this.tree.render();
45668 this.on('resize', function (cp, w, h) {
45669 this.tree.innerCt.setWidth(w);
45670 this.tree.innerCt.setHeight(h);
45671 this.tree.innerCt.setStyle('overflow-y', 'auto');
45678 Roo.extend(Roo.TreePanel, Roo.ContentPanel);
45693 * Ext JS Library 1.1.1
45694 * Copyright(c) 2006-2007, Ext JS, LLC.
45696 * Originally Released Under LGPL - original licence link has changed is not relivant.
45699 * <script type="text/javascript">
45704 * @class Roo.ReaderLayout
45705 * @extends Roo.BorderLayout
45706 * This is a pre-built layout that represents a classic, 5-pane application. It consists of a header, a primary
45707 * center region containing two nested regions (a top one for a list view and one for item preview below),
45708 * and regions on either side that can be used for navigation, application commands, informational displays, etc.
45709 * The setup and configuration work exactly the same as it does for a {@link Roo.BorderLayout} - this class simply
45710 * expedites the setup of the overall layout and regions for this common application style.
45713 var reader = new Roo.ReaderLayout();
45714 var CP = Roo.ContentPanel; // shortcut for adding
45716 reader.beginUpdate();
45717 reader.add("north", new CP("north", "North"));
45718 reader.add("west", new CP("west", {title: "West"}));
45719 reader.add("east", new CP("east", {title: "East"}));
45721 reader.regions.listView.add(new CP("listView", "List"));
45722 reader.regions.preview.add(new CP("preview", "Preview"));
45723 reader.endUpdate();
45726 * Create a new ReaderLayout
45727 * @param {Object} config Configuration options
45728 * @param {String/HTMLElement/Element} container (optional) The container this layout is bound to (defaults to
45729 * document.body if omitted)
45731 Roo.ReaderLayout = function(A, B){
45732 var c = A || {size:{}};
45733 Roo.ReaderLayout.superclass.constructor.call(this, B || document.body, {
45734 north: c.north !== false ? Roo.apply({
45738 }, c.north) : false,
45739 west: c.west !== false ? Roo.apply({
45747 margins:{left:5,right:0,bottom:5,top:5},
45748 cmargins:{left:5,right:5,bottom:5,top:5}
45749 }, c.west) : false,
45750 east: c.east !== false ? Roo.apply({
45758 margins:{left:0,right:5,bottom:5,top:5},
45759 cmargins:{left:5,right:5,bottom:5,top:5}
45760 }, c.east) : false,
45761 center: Roo.apply({
45762 tabPosition: 'top',
45766 margins:{left:c.west!==false ? 0 : 5,right:c.east!==false ? 0 : 5,bottom:5,top:2}
45770 this.el.addClass('x-reader');
45772 this.beginUpdate();
45774 var C = new Roo.BorderLayout(Roo.get(document.body).createChild(), {
45775 south: c.preview !== false ? Roo.apply({
45782 cmargins:{top:5,left:0, right:0, bottom:0}
45783 }, c.preview) : false,
45784 center: Roo.apply({
45790 this.add('center', new Roo.NestedLayoutPanel(C,
45791 Roo.apply({title: c.mainTitle || '',tabTip:''},c.innerPanelCfg)));
45795 this.regions.preview = C.getRegion('south');
45796 this.regions.listView = C.getRegion('center');
45799 Roo.extend(Roo.ReaderLayout, Roo.BorderLayout);
45802 * Ext JS Library 1.1.1
45803 * Copyright(c) 2006-2007, Ext JS, LLC.
45805 * Originally Released Under LGPL - original licence link has changed is not relivant.
45808 * <script type="text/javascript">
45812 * @class Roo.grid.Grid
45813 * @extends Roo.util.Observable
45814 * This class represents the primary interface of a component based grid control.
45815 * <br><br>Usage:<pre><code>
45816 var grid = new Roo.grid.Grid("my-container-id", {
45819 selModel: mySelectionModel,
45820 autoSizeColumns: true,
45821 monitorWindowResize: false,
45822 trackMouseOver: true
45827 * <b>Common Problems:</b><br/>
45828 * - Grid does not resize properly when going smaller: Setting overflow hidden on the container
45829 * element will correct this<br/>
45830 * - If you get el.style[camel]= NaNpx or -2px or something related, be certain you have given your container element
45831 * dimensions. The grid adapts to your container's size, if your container has no size defined then the results
45832 * are unpredictable.<br/>
45833 * - Do not render the grid into an element with display:none. Try using visibility:hidden. Otherwise there is no way for the
45834 * grid to calculate dimensions/offsets.<br/>
45836 * @param {String/HTMLElement/Roo.Element} container The element into which this grid will be rendered -
45837 * The container MUST have some type of size defined for the grid to fill. The container will be
45838 * automatically set to position relative if it isn't already.
45839 * @param {Object} config A config object that sets properties on this grid.
45841 Roo.grid.Grid = function(A, B){
45842 // initialize the container
45843 this.container = Roo.get(A);
45844 this.container.update("");
45845 this.container.setStyle("overflow", "hidden");
45846 this.container.addClass('x-grid-container');
45848 this.id = this.container.id;
45850 Roo.apply(this, B);
45851 // check and correct shorthanded configs
45853 this.dataSource = this.ds;
45857 this.colModel = this.cm;
45861 this.selModel = this.sm;
45865 if (this.selModel) {
45866 this.selModel = Roo.factory(this.selModel, Roo.grid);
45867 this.sm = this.selModel;
45868 this.sm.xmodule = this.xmodule || false;
45870 if (typeof(this.colModel.config) == 'undefined') {
45871 this.colModel = new Roo.grid.ColumnModel(this.colModel);
45872 this.cm = this.colModel;
45873 this.cm.xmodule = this.xmodule || false;
45875 if (this.dataSource) {
45876 this.dataSource= Roo.factory(this.dataSource, Roo.data);
45877 this.ds = this.dataSource;
45878 this.ds.xmodule = this.xmodule || false;
45885 this.container.setWidth(this.width);
45889 this.container.setHeight(this.height);
45897 * The raw click event for the entire grid.
45898 * @param {Roo.EventObject} e
45903 * The raw dblclick event for the entire grid.
45904 * @param {Roo.EventObject} e
45908 * @event contextmenu
45909 * The raw contextmenu event for the entire grid.
45910 * @param {Roo.EventObject} e
45912 "contextmenu" : true,
45915 * The raw mousedown event for the entire grid.
45916 * @param {Roo.EventObject} e
45918 "mousedown" : true,
45921 * The raw mouseup event for the entire grid.
45922 * @param {Roo.EventObject} e
45927 * The raw mouseover event for the entire grid.
45928 * @param {Roo.EventObject} e
45930 "mouseover" : true,
45933 * The raw mouseout event for the entire grid.
45934 * @param {Roo.EventObject} e
45939 * The raw keypress event for the entire grid.
45940 * @param {Roo.EventObject} e
45945 * The raw keydown event for the entire grid.
45946 * @param {Roo.EventObject} e
45954 * Fires when a cell is clicked
45955 * @param {Grid} this
45956 * @param {Number} rowIndex
45957 * @param {Number} columnIndex
45958 * @param {Roo.EventObject} e
45960 "cellclick" : true,
45962 * @event celldblclick
45963 * Fires when a cell is double clicked
45964 * @param {Grid} this
45965 * @param {Number} rowIndex
45966 * @param {Number} columnIndex
45967 * @param {Roo.EventObject} e
45969 "celldblclick" : true,
45972 * Fires when a row is clicked
45973 * @param {Grid} this
45974 * @param {Number} rowIndex
45975 * @param {Roo.EventObject} e
45979 * @event rowdblclick
45980 * Fires when a row is double clicked
45981 * @param {Grid} this
45982 * @param {Number} rowIndex
45983 * @param {Roo.EventObject} e
45985 "rowdblclick" : true,
45987 * @event headerclick
45988 * Fires when a header is clicked
45989 * @param {Grid} this
45990 * @param {Number} columnIndex
45991 * @param {Roo.EventObject} e
45993 "headerclick" : true,
45995 * @event headerdblclick
45996 * Fires when a header cell is double clicked
45997 * @param {Grid} this
45998 * @param {Number} columnIndex
45999 * @param {Roo.EventObject} e
46001 "headerdblclick" : true,
46003 * @event rowcontextmenu
46004 * Fires when a row is right clicked
46005 * @param {Grid} this
46006 * @param {Number} rowIndex
46007 * @param {Roo.EventObject} e
46009 "rowcontextmenu" : true,
46011 * @event cellcontextmenu
46012 * Fires when a cell is right clicked
46013 * @param {Grid} this
46014 * @param {Number} rowIndex
46015 * @param {Number} cellIndex
46016 * @param {Roo.EventObject} e
46018 "cellcontextmenu" : true,
46020 * @event headercontextmenu
46021 * Fires when a header is right clicked
46022 * @param {Grid} this
46023 * @param {Number} columnIndex
46024 * @param {Roo.EventObject} e
46026 "headercontextmenu" : true,
46028 * @event bodyscroll
46029 * Fires when the body element is scrolled
46030 * @param {Number} scrollLeft
46031 * @param {Number} scrollTop
46033 "bodyscroll" : true,
46035 * @event columnresize
46036 * Fires when the user resizes a column
46037 * @param {Number} columnIndex
46038 * @param {Number} newSize
46040 "columnresize" : true,
46042 * @event columnmove
46043 * Fires when the user moves a column
46044 * @param {Number} oldIndex
46045 * @param {Number} newIndex
46047 "columnmove" : true,
46050 * Fires when row(s) start being dragged
46051 * @param {Grid} this
46052 * @param {Roo.GridDD} dd The drag drop object
46053 * @param {event} e The raw browser event
46055 "startdrag" : true,
46058 * Fires when a drag operation is complete
46059 * @param {Grid} this
46060 * @param {Roo.GridDD} dd The drag drop object
46061 * @param {event} e The raw browser event
46066 * Fires when dragged row(s) are dropped on a valid DD target
46067 * @param {Grid} this
46068 * @param {Roo.GridDD} dd The drag drop object
46069 * @param {String} targetId The target drag drop object
46070 * @param {event} e The raw browser event
46075 * Fires while row(s) are being dragged. "targetId" is the id of the Yahoo.util.DD object the selected rows are being dragged over.
46076 * @param {Grid} this
46077 * @param {Roo.GridDD} dd The drag drop object
46078 * @param {String} targetId The target drag drop object
46079 * @param {event} e The raw browser event
46084 * Fires when the dragged row(s) first cross another DD target while being dragged
46085 * @param {Grid} this
46086 * @param {Roo.GridDD} dd The drag drop object
46087 * @param {String} targetId The target drag drop object
46088 * @param {event} e The raw browser event
46090 "dragenter" : true,
46093 * Fires when the dragged row(s) leave another DD target while being dragged
46094 * @param {Grid} this
46095 * @param {Roo.GridDD} dd The drag drop object
46096 * @param {String} targetId The target drag drop object
46097 * @param {event} e The raw browser event
46102 * Fires when the grid is rendered
46103 * @param {Grid} grid
46108 Roo.grid.Grid.superclass.constructor.call(this);
46110 Roo.extend(Roo.grid.Grid, Roo.util.Observable, {
46112 * @cfg {Number} minColumnWidth The minimum width a column can be resized to. Default is 25.
46114 minColumnWidth : 25,
46117 * @cfg {Boolean} autoSizeColumns True to automatically resize the columns to fit their content
46118 * <b>on initial render.</b> It is more efficient to explicitly size the columns
46119 * through the ColumnModel's {@link Roo.grid.ColumnModel#width} config option. Default is false.
46121 autoSizeColumns : false,
46124 * @cfg {Boolean} autoSizeHeaders True to measure headers with column data when auto sizing columns. Default is true.
46126 autoSizeHeaders : true,
46129 * @cfg {Boolean} monitorWindowResize True to autoSize the grid when the window resizes. Default is true.
46131 monitorWindowResize : true,
46134 * @cfg {Boolean} maxRowsToMeasure If autoSizeColumns is on, maxRowsToMeasure can be used to limit the number of
46135 * rows measured to get a columns size. Default is 0 (all rows).
46137 maxRowsToMeasure : 0,
46140 * @cfg {Boolean} trackMouseOver True to highlight rows when the mouse is over. Default is true.
46142 trackMouseOver : true,
46145 * @cfg {Boolean} enableDragDrop True to enable drag and drop of rows. Default is false.
46147 enableDragDrop : false,
46150 * @cfg {Boolean} enableColumnMove True to enable drag and drop reorder of columns. Default is true.
46152 enableColumnMove : true,
46155 * @cfg {Boolean} enableColumnHide True to enable hiding of columns with the header context menu. Default is true.
46157 enableColumnHide : true,
46160 * @cfg {Boolean} enableRowHeightSync True to manually sync row heights across locked and not locked rows. Default is false.
46162 enableRowHeightSync : false,
46165 * @cfg {Boolean} stripeRows True to stripe the rows. Default is true.
46170 * @cfg {Boolean} autoHeight True to fit the height of the grid container to the height of the data. Default is false.
46172 autoHeight : false,
46175 * @cfg {String} autoExpandColumn The id (or dataIndex) of a column in this grid that should expand to fill unused space. This id can not be 0. Default is false.
46177 autoExpandColumn : false,
46180 * @cfg {Number} autoExpandMin The minimum width the autoExpandColumn can have (if enabled).
46183 autoExpandMin : 50,
46186 * @cfg {Number} autoExpandMax The maximum width the autoExpandColumn can have (if enabled). Default is 1000.
46188 autoExpandMax : 1000,
46191 * @cfg {Object} view The {@link Roo.grid.GridView} used by the grid. This can be set before a call to render().
46196 * @cfg {Object} loadMask An {@link Roo.LoadMask} config or true to mask the grid while loading. Default is false.
46204 * @cfg {Boolean} autoWidth True to set the grid's width to the default total width of the grid's columns instead
46205 * of a fixed width. Default is false.
46208 * @cfg {Number} maxHeight Sets the maximum height of the grid - ignored if autoHeight is not on.
46211 * Called once after all setup has been completed and the grid is ready to be rendered.
46212 * @return {Roo.grid.Grid} this
46214 render : function(){
46215 var c = this.container;
46216 // try to detect autoHeight/width mode
46217 if((!c.dom.offsetHeight || c.dom.offsetHeight < 20) || c.getStyle("height") == "auto"){
46218 this.autoHeight = true;
46220 var C = this.getView();
46223 c.on("click", this.onClick, this);
46224 c.on("dblclick", this.onDblClick, this);
46225 c.on("contextmenu", this.onContextMenu, this);
46226 c.on("keydown", this.onKeyDown, this);
46228 this.relayEvents(c, ["mousedown","mouseup","mouseover","mouseout","keypress"]);
46230 this.getSelectionModel().init(this);
46235 this.loadMask = new Roo.LoadMask(this.container,
46236 Roo.apply({store:this.dataSource}, this.loadMask));
46240 if (this.toolbar && this.toolbar.xtype) {
46241 this.toolbar.container = this.getView().getHeaderPanel(true);
46242 this.toolbar = new Ext.Toolbar(this.toolbar);
46244 if (this.footer && this.footer.xtype) {
46245 this.footer.dataSource = this.getDataSource();
46246 this.footer.container = this.getView().getFooterPanel(true);
46247 this.footer = Roo.factory(this.footer, Roo);
46250 this.rendered = true;
46251 this.fireEvent('render', this);
46256 * Reconfigures the grid to use a different Store and Column Model.
46257 * The View will be bound to the new objects and refreshed.
46258 * @param {Roo.data.Store} dataSource The new {@link Roo.data.Store} object
46259 * @param {Roo.grid.ColumnModel} The new {@link Roo.grid.ColumnModel} object
46261 reconfigure : function(D, E){
46263 this.loadMask.destroy();
46264 this.loadMask = new Roo.LoadMask(this.container,
46265 Roo.apply({store:D}, this.loadMask));
46268 this.view.bind(D, E);
46269 this.dataSource = D;
46271 this.view.refresh(true);
46275 onKeyDown : function(e){
46276 this.fireEvent("keydown", e);
46280 * Destroy this grid.
46281 * @param {Boolean} removeEl True to remove the element
46283 destroy : function(F, G){
46285 this.loadMask.destroy();
46287 var c = this.container;
46288 c.removeAllListeners();
46289 this.view.destroy();
46290 this.colModel.purgeListeners();
46292 this.purgeListeners();
46302 processEvent : function(H, e){
46303 this.fireEvent(H, e);
46304 var t = e.getTarget();
46306 var I = v.findHeaderIndex(t);
46308 this.fireEvent("header" + H, this, I, e);
46310 var row = v.findRowIndex(t);
46311 var cell = v.findCellIndex(t);
46313 this.fireEvent("row" + H, this, row, e);
46314 if(cell !== false){
46315 this.fireEvent("cell" + H, this, row, cell, e);
46322 onClick : function(e){
46323 this.processEvent("click", e);
46327 onContextMenu : function(e, t){
46328 this.processEvent("contextmenu", e);
46332 onDblClick : function(e){
46333 this.processEvent("dblclick", e);
46337 walkCells : function(J, K, L, fn, M){
46338 var cm = this.colModel, N = cm.getColumnCount();
46339 var ds = this.dataSource, O = ds.getCount(), P = true;
46352 if(fn.call(M || this, J, K, cm) === true){
46373 if(fn.call(M || this, J, K, cm) === true){
46387 getSelections : function(){
46388 return this.selModel.getSelections();
46392 * Causes the grid to manually recalculate its dimensions. Generally this is done automatically,
46393 * but if manual update is required this method will initiate it.
46395 autoSize : function(){
46397 this.view.layout();
46398 if(this.view.adjustForScroll){
46399 this.view.adjustForScroll();
46405 * Returns the grid's underlying element.
46406 * @return {Element} The element
46408 getGridEl : function(){
46409 return this.container;
46412 // private for compatibility, overridden by editor grid
46413 stopEditing : function(){},
46416 * Returns the grid's SelectionModel.
46417 * @return {SelectionModel}
46419 getSelectionModel : function(){
46420 if(!this.selModel){
46421 this.selModel = new Roo.grid.RowSelectionModel();
46423 return this.selModel;
46427 * Returns the grid's DataSource.
46428 * @return {DataSource}
46430 getDataSource : function(){
46431 return this.dataSource;
46435 * Returns the grid's ColumnModel.
46436 * @return {ColumnModel}
46438 getColumnModel : function(){
46439 return this.colModel;
46443 * Returns the grid's GridView object.
46444 * @return {GridView}
46446 getView : function(){
46448 this.view = new Roo.grid.GridView(this.viewConfig);
46453 * Called to get grid's drag proxy text, by default returns this.ddText.
46456 getDragDropText : function(){
46457 var Q = this.selModel.getCount();
46458 return String.format(this.ddText, Q, Q == 1 ? '' : 's');
46462 * Configures the text is the drag proxy (defaults to "%0 selected row(s)").
46463 * %0 is replaced with the number of selected rows.
46466 Roo.grid.Grid.prototype.ddText = "{0} selected row{1}";
46469 * Ext JS Library 1.1.1
46470 * Copyright(c) 2006-2007, Ext JS, LLC.
46472 * Originally Released Under LGPL - original licence link has changed is not relivant.
46475 * <script type="text/javascript">
46478 Roo.grid.AbstractGridView = function(){
46482 "beforerowremoved" : true,
46483 "beforerowsinserted" : true,
46484 "beforerefresh" : true,
46485 "rowremoved" : true,
46486 "rowsinserted" : true,
46487 "rowupdated" : true,
46490 Roo.grid.AbstractGridView.superclass.constructor.call(this);
46493 Roo.extend(Roo.grid.AbstractGridView, Roo.util.Observable, {
46494 rowClass : "x-grid-row",
46495 cellClass : "x-grid-cell",
46496 tdClass : "x-grid-td",
46497 hdClass : "x-grid-hd",
46498 splitClass : "x-grid-hd-split",
46502 var B = this.grid.getGridEl().id;
46503 this.colSelector = "#" + B + " ." + this.cellClass + "-";
46504 this.tdSelector = "#" + B + " ." + this.tdClass + "-";
46505 this.hdSelector = "#" + B + " ." + this.hdClass + "-";
46506 this.splitSelector = "#" + B + " ." + this.splitClass + "-";
46509 getColumnRenderers : function(){
46511 var cm = this.grid.colModel;
46512 var D = cm.getColumnCount();
46513 for(var i = 0; i < D; i++){
46514 C[i] = cm.getRenderer(i);
46519 getColumnIds : function(){
46521 var cm = this.grid.colModel;
46522 var F = cm.getColumnCount();
46523 for(var i = 0; i < F; i++){
46524 E[i] = cm.getColumnId(i);
46529 getDataIndexes : function(){
46530 if(!this.indexMap){
46531 this.indexMap = this.buildIndexMap();
46533 return this.indexMap.colToData;
46536 getColumnIndexByDataIndex : function(G){
46537 if(!this.indexMap){
46538 this.indexMap = this.buildIndexMap();
46540 return this.indexMap.dataToCol[G];
46544 * Set a css style for a column dynamically.
46545 * @param {Number} colIndex The index of the column
46546 * @param {String} name The css property name
46547 * @param {String} value The css value
46549 setCSSStyle : function(H, I, J){
46550 var K = "#" + this.grid.id + " .x-grid-col-" + H;
46551 Roo.util.CSS.updateRule(K, I, J);
46554 generateRules : function(cm){
46555 var L = [], M = this.grid.id + '-cssrules';
46556 Roo.util.CSS.removeStyleSheet(M);
46557 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
46558 var B = cm.getColumnId(i);
46559 L.push(this.colSelector, B, " {\n", cm.config[i].css, "}\n",
46560 this.tdSelector, B, " {\n}\n",
46561 this.hdSelector, B, " {\n}\n",
46562 this.splitSelector, B, " {\n}\n");
46564 return Roo.util.CSS.createStyleSheet(L.join(""), M);
46569 * Ext JS Library 1.1.1
46570 * Copyright(c) 2006-2007, Ext JS, LLC.
46572 * Originally Released Under LGPL - original licence link has changed is not relivant.
46575 * <script type="text/javascript">
46579 // This is a support class used internally by the Grid components
46580 Roo.grid.HeaderDragZone = function(A, hd, B){
46582 this.view = A.getView();
46583 this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
46584 Roo.grid.HeaderDragZone.superclass.constructor.call(this, hd);
46586 this.setHandleElId(Roo.id(hd));
46587 this.setOuterHandleElId(Roo.id(B));
46590 this.scroll = false;
46592 Roo.extend(Roo.grid.HeaderDragZone, Roo.dd.DragZone, {
46594 getDragData : function(e){
46595 var t = Roo.lib.Event.getTarget(e);
46596 var h = this.view.findHeaderCell(t);
46598 return {ddel: h.firstChild, header:h};
46603 onInitDrag : function(e){
46604 this.view.headersDisabled = true;
46605 var C = this.dragData.ddel.cloneNode(true);
46607 C.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
46608 this.proxy.update(C);
46612 afterValidDrop : function(){
46614 setTimeout(function(){
46615 v.headersDisabled = false;
46619 afterInvalidDrop : function(){
46621 setTimeout(function(){
46622 v.headersDisabled = false;
46629 * Ext JS Library 1.1.1
46630 * Copyright(c) 2006-2007, Ext JS, LLC.
46632 * Originally Released Under LGPL - original licence link has changed is not relivant.
46635 * <script type="text/javascript">
46638 // This is a support class used internally by the Grid components
46639 Roo.grid.HeaderDropZone = function(A, hd, B){
46641 this.view = A.getView();
46642 // split the proxies so they don't interfere with mouse events
46643 this.proxyTop = Roo.DomHelper.append(document.body, {
46644 cls:"col-move-top", html:" "
46646 this.proxyBottom = Roo.DomHelper.append(document.body, {
46647 cls:"col-move-bottom", html:" "
46649 this.proxyTop.hide = this.proxyBottom.hide = function(){
46650 this.setLeftTop(-100,-100);
46651 this.setStyle("visibility", "hidden");
46653 this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
46654 // temporarily disabled
46655 //Roo.dd.ScrollManager.register(this.view.scroller.dom);
46656 Roo.grid.HeaderDropZone.superclass.constructor.call(this, A.getGridEl().dom);
46658 Roo.extend(Roo.grid.HeaderDropZone, Roo.dd.DropZone, {
46659 proxyOffsets : [-4, -9],
46660 fly: Roo.Element.fly,
46662 getTargetFromEvent : function(e){
46663 var t = Roo.lib.Event.getTarget(e);
46664 var C = this.view.findCellIndex(t);
46666 return this.view.getHeaderCell(C);
46670 nextVisible : function(h){
46671 var v = this.view, cm = this.grid.colModel;
46674 if(!cm.isHidden(v.getCellIndex(h))){
46683 prevVisible : function(h){
46684 var v = this.view, cm = this.grid.colModel;
46687 if(!cm.isHidden(v.getCellIndex(h))){
46696 positionIndicator : function(h, n, e){
46697 var x = Roo.lib.Event.getPageX(e);
46698 var r = Roo.lib.Dom.getRegion(n.firstChild);
46699 var px, pt, py = r.top + this.proxyOffsets[1];
46700 if((r.right - x) <= (r.right-r.left)/2){
46701 px = r.right+this.view.borderWidth;
46707 var D = this.view.getCellIndex(h);
46708 var E = this.view.getCellIndex(n);
46710 if(this.grid.colModel.isFixed(E)){
46714 var F = this.grid.colModel.isLocked(E);
46722 if(D == E && (F == this.grid.colModel.isLocked(D))){
46726 px += this.proxyOffsets[0];
46727 this.proxyTop.setLeftTop(px, py);
46728 this.proxyTop.show();
46729 if(!this.bottomOffset){
46730 this.bottomOffset = this.view.mainHd.getHeight();
46733 this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
46734 this.proxyBottom.show();
46738 onNodeEnter : function(n, dd, e, G){
46740 this.positionIndicator(G.header, n, e);
46744 onNodeOver : function(n, dd, e, H){
46747 I = this.positionIndicator(H.header, n, e);
46750 this.proxyTop.hide();
46751 this.proxyBottom.hide();
46753 return I ? this.dropAllowed : this.dropNotAllowed;
46756 onNodeOut : function(n, dd, e, J){
46757 this.proxyTop.hide();
46758 this.proxyBottom.hide();
46761 onNodeDrop : function(n, dd, e, K){
46764 var cm = this.grid.colModel;
46765 var x = Roo.lib.Event.getPageX(e);
46766 var r = Roo.lib.Dom.getRegion(n.firstChild);
46767 var pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before";
46768 var D = this.view.getCellIndex(h);
46769 var E = this.view.getCellIndex(n);
46770 var F = cm.isLocked(E);
46777 if(D == E && (F == cm.isLocked(D))){
46781 cm.setLocked(D, F, true);
46782 cm.moveColumn(D, E);
46783 this.grid.fireEvent("columnmove", D, E);
46792 * Ext JS Library 1.1.1
46793 * Copyright(c) 2006-2007, Ext JS, LLC.
46795 * Originally Released Under LGPL - original licence link has changed is not relivant.
46798 * <script type="text/javascript">
46802 * @class Roo.grid.GridView
46803 * @extends Roo.util.Observable
46806 * @param {Object} config
46808 Roo.grid.GridView = function(A){
46809 Roo.grid.GridView.superclass.constructor.call(this);
46812 Roo.apply(this, A);
46815 Roo.extend(Roo.grid.GridView, Roo.grid.AbstractGridView, {
46818 * Override this function to apply custom css classes to rows during rendering
46819 * @param {Record} record The record
46820 * @param {Number} index
46821 * @method getRowClass
46823 rowClass : "x-grid-row",
46825 cellClass : "x-grid-col",
46827 tdClass : "x-grid-td",
46829 hdClass : "x-grid-hd",
46831 splitClass : "x-grid-split",
46833 sortClasses : ["sort-asc", "sort-desc"],
46835 enableMoveAnim : false,
46839 dh : Roo.DomHelper,
46841 fly : Roo.Element.fly,
46843 css : Roo.util.CSS,
46849 scrollIncrement : 22,
46851 cellRE: /(?:.*?)x-grid-(?:hd|cell|csplit)-(?:[\d]+)-([\d]+)(?:.*?)/,
46853 findRE: /\s?(?:x-grid-hd|x-grid-col|x-grid-csplit)\s/,
46855 bind : function(ds, cm){
46857 this.ds.un("load", this.onLoad, this);
46858 this.ds.un("datachanged", this.onDataChange, this);
46859 this.ds.un("add", this.onAdd, this);
46860 this.ds.un("remove", this.onRemove, this);
46861 this.ds.un("update", this.onUpdate, this);
46862 this.ds.un("clear", this.onClear, this);
46865 ds.on("load", this.onLoad, this);
46866 ds.on("datachanged", this.onDataChange, this);
46867 ds.on("add", this.onAdd, this);
46868 ds.on("remove", this.onRemove, this);
46869 ds.on("update", this.onUpdate, this);
46870 ds.on("clear", this.onClear, this);
46876 this.cm.un("widthchange", this.onColWidthChange, this);
46877 this.cm.un("headerchange", this.onHeaderChange, this);
46878 this.cm.un("hiddenchange", this.onHiddenChange, this);
46879 this.cm.un("columnmoved", this.onColumnMove, this);
46880 this.cm.un("columnlockchange", this.onColumnLock, this);
46883 this.generateRules(cm);
46884 cm.on("widthchange", this.onColWidthChange, this);
46885 cm.on("headerchange", this.onHeaderChange, this);
46886 cm.on("hiddenchange", this.onHiddenChange, this);
46887 cm.on("columnmoved", this.onColumnMove, this);
46888 cm.on("columnlockchange", this.onColumnLock, this);
46895 Roo.grid.GridView.superclass.init.call(this, B);
46897 this.bind(B.dataSource, B.colModel);
46899 B.on("headerclick", this.handleHeaderClick, this);
46901 if(B.trackMouseOver){
46902 B.on("mouseover", this.onRowOver, this);
46903 B.on("mouseout", this.onRowOut, this);
46906 B.cancelTextSelection = function(){};
46907 this.gridId = B.id;
46909 var C = this.templates || {};
46912 C.master = new Roo.Template(
46913 '<div class="x-grid" hidefocus="true">',
46914 '<div class="x-grid-topbar"></div>',
46915 '<div class="x-grid-scroller"><div></div></div>',
46916 '<div class="x-grid-locked">',
46917 '<div class="x-grid-header">{lockedHeader}</div>',
46918 '<div class="x-grid-body">{lockedBody}</div>',
46920 '<div class="x-grid-viewport">',
46921 '<div class="x-grid-header">{header}</div>',
46922 '<div class="x-grid-body">{body}</div>',
46924 '<div class="x-grid-bottombar"></div>',
46925 '<a href="#" class="x-grid-focus" tabIndex="-1"></a>',
46926 '<div class="x-grid-resize-proxy"> </div>',
46929 C.master.disableformats = true;
46933 C.header = new Roo.Template(
46934 '<table border="0" cellspacing="0" cellpadding="0">',
46935 '<tbody><tr class="x-grid-hd-row">{cells}</tr></tbody>',
46938 C.header.disableformats = true;
46941 C.header.compile();
46944 C.hcell = new Roo.Template(
46945 '<td class="x-grid-hd x-grid-td-{id} {cellId}"><div title="{title}" class="x-grid-hd-inner x-grid-hd-{id}">',
46946 '<div class="x-grid-hd-text" unselectable="on">{value}<img class="x-grid-sort-icon" src="', Roo.BLANK_IMAGE_URL, '" /></div>',
46949 C.hcell.disableFormats = true;
46955 C.hsplit = new Roo.Template('<div class="x-grid-split {splitId} x-grid-split-{id}" style="{style}" unselectable="on"> </div>');
46956 C.hsplit.disableFormats = true;
46959 C.hsplit.compile();
46962 C.body = new Roo.Template(
46963 '<table border="0" cellspacing="0" cellpadding="0">',
46964 "<tbody>{rows}</tbody>",
46967 C.body.disableFormats = true;
46973 C.row = new Roo.Template('<tr class="x-grid-row {alt}">{cells}</tr>');
46974 C.row.disableFormats = true;
46980 C.cell = new Roo.Template(
46981 '<td class="x-grid-col x-grid-td-{id} {cellId} {css}" tabIndex="0">',
46982 '<div class="x-grid-col-{id} x-grid-cell-inner"><div class="x-grid-cell-text" unselectable="on" {attr}>{value}</div></div>',
46985 C.cell.disableFormats = true;
46990 this.templates = C;
46993 // remap these for backwards compat
46994 onColWidthChange : function(){
46995 this.updateColumns.apply(this, arguments);
46997 onHeaderChange : function(){
46998 this.updateHeaders.apply(this, arguments);
47000 onHiddenChange : function(){
47001 this.handleHiddenChange.apply(this, arguments);
47003 onColumnMove : function(){
47004 this.handleColumnMove.apply(this, arguments);
47006 onColumnLock : function(){
47007 this.handleLockChange.apply(this, arguments);
47010 onDataChange : function(){
47012 this.updateHeaderSortState();
47015 onClear : function(){
47019 onUpdate : function(ds, D){
47020 this.refreshRow(D);
47023 refreshRow : function(E){
47024 var ds = this.ds, F;
47025 if(typeof E == 'number'){
47032 this.insertRows(ds, F, F, true);
47033 this.onRemove(ds, E, F+1, true);
47034 this.syncRowHeights(F, F);
47036 this.fireEvent("rowupdated", this, F, E);
47039 onAdd : function(ds, G, H){
47040 this.insertRows(ds, H, H + (G.length-1));
47043 onRemove : function(ds, I, J, K){
47045 this.fireEvent("beforerowremoved", this, J, I);
47047 var bt = this.getBodyTable(), lt = this.getLockedTable();
47049 bt.firstChild.removeChild(bt.rows[J]);
47052 lt.firstChild.removeChild(lt.rows[J]);
47055 this.stripeRows(J);
47056 this.syncRowHeights(J, J);
47058 this.fireEvent("rowremoved", this, J, I);
47062 onLoad : function(){
47063 this.scrollToTop();
47067 * Scrolls the grid to the top
47069 scrollToTop : function(){
47071 this.scroller.dom.scrollTop = 0;
47077 * Gets a panel in the header of the grid that can be used for toolbars etc.
47078 * After modifying the contents of this panel a call to grid.autoSize() may be
47079 * required to register any changes in size.
47080 * @param {Boolean} doShow By default the header is hidden. Pass true to show the panel
47081 * @return Roo.Element
47083 getHeaderPanel : function(L){
47085 this.headerPanel.show();
47087 return this.headerPanel;
47091 * Gets a panel in the footer of the grid that can be used for toolbars etc.
47092 * After modifying the contents of this panel a call to grid.autoSize() may be
47093 * required to register any changes in size.
47094 * @param {Boolean} doShow By default the footer is hidden. Pass true to show the panel
47095 * @return Roo.Element
47097 getFooterPanel : function(M){
47099 this.footerPanel.show();
47101 return this.footerPanel;
47104 initElements : function(){
47105 var E = Roo.Element;
47106 var el = this.grid.getGridEl().dom.firstChild;
47107 var cs = el.childNodes;
47109 this.el = new E(el);
47110 this.headerPanel = new E(el.firstChild);
47111 this.headerPanel.enableDisplayMode("block");
47113 this.scroller = new E(cs[1]);
47114 this.scrollSizer = new E(this.scroller.dom.firstChild);
47116 this.lockedWrap = new E(cs[2]);
47117 this.lockedHd = new E(this.lockedWrap.dom.firstChild);
47118 this.lockedBody = new E(this.lockedWrap.dom.childNodes[1]);
47120 this.mainWrap = new E(cs[3]);
47121 this.mainHd = new E(this.mainWrap.dom.firstChild);
47122 this.mainBody = new E(this.mainWrap.dom.childNodes[1]);
47124 this.footerPanel = new E(cs[4]);
47125 this.footerPanel.enableDisplayMode("block");
47127 this.focusEl = new E(cs[5]);
47128 this.focusEl.swallowEvent("click", true);
47129 this.resizeProxy = new E(cs[6]);
47131 this.headerSelector = String.format(
47132 '#{0} td.x-grid-hd, #{1} td.x-grid-hd',
47133 this.lockedHd.id, this.mainHd.id
47136 this.splitterSelector = String.format(
47137 '#{0} div.x-grid-split, #{1} div.x-grid-split',
47138 this.idToCssName(this.lockedHd.id), this.idToCssName(this.mainHd.id)
47141 idToCssName : function(s)
47143 return s.replace(/[^a-z0-9]+/ig, '-');
47146 getHeaderCell : function(N){
47147 return Roo.DomQuery.select(this.headerSelector)[N];
47150 getHeaderCellMeasure : function(O){
47151 return this.getHeaderCell(O).firstChild;
47154 getHeaderCellText : function(P){
47155 return this.getHeaderCell(P).firstChild.firstChild;
47158 getLockedTable : function(){
47159 return this.lockedBody.dom.firstChild;
47162 getBodyTable : function(){
47163 return this.mainBody.dom.firstChild;
47166 getLockedRow : function(Q){
47167 return this.getLockedTable().rows[Q];
47170 getRow : function(R){
47171 return this.getBodyTable().rows[R];
47174 getRowComposite : function(S){
47176 this.rowEl = new Roo.CompositeElementLite();
47179 if(U = this.getLockedRow(S)){
47182 if(V = this.getRow(S)){
47186 this.rowEl.elements = T;
47190 getCell : function(W, X){
47191 var Y = this.cm.getLockedCount();
47194 Z = this.lockedBody.dom.firstChild;
47196 Z = this.mainBody.dom.firstChild;
47199 return Z.rows[W].childNodes[X];
47202 getCellText : function(a, b){
47203 return this.getCell(a, b).firstChild.firstChild;
47206 getCellBox : function(c){
47207 var b = this.fly(c).getBox();
47208 if(Roo.isOpera){ // opera fails to report the Y
47209 b.y = c.offsetTop + this.mainBody.getY();
47214 getCellIndex : function(d){
47215 var id = String(d.className).match(this.cellRE);
47217 return parseInt(id[1], 10);
47222 findHeaderIndex : function(n){
47223 var r = Roo.fly(n).findParent("td." + this.hdClass, 6);
47224 return r ? this.getCellIndex(r) : false;
47227 findHeaderCell : function(n){
47228 var r = Roo.fly(n).findParent("td." + this.hdClass, 6);
47229 return r ? r : false;
47232 findRowIndex : function(n){
47236 var r = Roo.fly(n).findParent("tr." + this.rowClass, 6);
47237 return r ? r.rowIndex : false;
47240 findCellIndex : function(e){
47241 var f = this.el.dom;
47242 while(e && e != f){
47243 if(this.findRE.test(e.className)){
47244 return this.getCellIndex(e);
47252 getColumnId : function(g){
47253 return this.cm.getColumnId(g);
47256 getSplitters : function(){
47257 if(this.splitterSelector){
47258 return Roo.DomQuery.select(this.splitterSelector);
47264 getSplitter : function(k){
47265 return this.getSplitters()[k];
47268 onRowOver : function(e, t){
47270 if((o = this.findRowIndex(t)) !== false){
47271 this.getRowComposite(o).addClass("x-grid-row-over");
47275 onRowOut : function(e, t){
47277 if((p = this.findRowIndex(t)) !== false && p !== this.findRowIndex(e.getRelatedTarget())){
47278 this.getRowComposite(p).removeClass("x-grid-row-over");
47282 renderHeaders : function(){
47284 var ct = this.templates.hcell, ht = this.templates.header, st = this.templates.hsplit;
47285 var cb = [], lb = [], sb = [], q = [], p = {};
47286 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
47287 p.cellId = "x-grid-hd-0-" + i;
47288 p.splitId = "x-grid-csplit-0-" + i;
47289 p.id = cm.getColumnId(i);
47290 p.title = cm.getColumnTooltip(i) || "";
47291 p.value = cm.getColumnHeader(i) || "";
47292 p.style = (this.grid.enableColumnResize === false || !cm.isResizable(i) || cm.isFixed(i)) ? 'cursor:default' : '';
47293 if(!cm.isLocked(i)){
47294 cb[cb.length] = ct.apply(p);
47295 sb[sb.length] = st.apply(p);
47297 lb[lb.length] = ct.apply(p);
47298 q[q.length] = st.apply(p);
47301 return [ht.apply({cells: lb.join(""), splits:q.join("")}),
47302 ht.apply({cells: cb.join(""), splits:sb.join("")})];
47305 updateHeaders : function(){
47306 var u = this.renderHeaders();
47307 this.lockedHd.update(u[0]);
47308 this.mainHd.update(u[1]);
47312 * Focuses the specified row.
47313 * @param {Number} row The row index
47315 focusRow : function(v){
47316 var x = this.scroller.dom.scrollLeft;
47317 this.focusCell(v, 0, false);
47318 this.scroller.dom.scrollLeft = x;
47322 * Focuses the specified cell.
47323 * @param {Number} row The row index
47324 * @param {Number} col The column index
47325 * @param {Boolean} hscroll false to disable horizontal scrolling
47327 focusCell : function(y, z, AA){
47328 var el = this.ensureVisible(y, z, AA);
47329 this.focusEl.alignTo(el, "tl-tl");
47331 this.focusEl.focus();
47333 this.focusEl.focus.defer(1, this.focusEl);
47338 * Scrolls the specified cell into view
47339 * @param {Number} row The row index
47340 * @param {Number} col The column index
47341 * @param {Boolean} hscroll false to disable horizontal scrolling
47343 ensureVisible : function(AB, AC, AD){
47344 if(typeof AB != "number"){
47347 if(AB < 0 && AB >= this.ds.getCount()){
47351 AC = (AC !== undefined ? AC : 0);
47352 var cm = this.grid.colModel;
47353 while(cm.isHidden(AC)){
47357 var el = this.getCell(AB, AC);
47361 var c = this.scroller.dom;
47363 var AE = parseInt(el.offsetTop, 10);
47364 var AF = parseInt(el.offsetLeft, 10);
47365 var AG = AE + el.offsetHeight;
47366 var AH = AF + el.offsetWidth;
47368 var ch = c.clientHeight - this.mainHd.dom.offsetHeight;
47369 var AI = parseInt(c.scrollTop, 10);
47370 var AJ = parseInt(c.scrollLeft, 10);
47372 var AL = AJ + c.clientWidth;
47377 c.scrollTop = AG-ch;
47384 c.scrollLeft = AH-c.clientWidth;
47390 updateColumns : function(){
47391 this.grid.stopEditing();
47392 var cm = this.grid.colModel, AM = this.getColumnIds();
47393 //var totalWidth = cm.getTotalWidth();
47395 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
47396 //if(cm.isHidden(i)) continue;
47397 var w = cm.getColumnWidth(i);
47398 this.css.updateRule(this.colSelector+this.idToCssName(AM[i]), "width", (w - this.borderWidth) + "px");
47399 this.css.updateRule(this.hdSelector+this.idToCssName(AM[i]), "width", (w - this.borderWidth) + "px");
47402 this.updateSplitters();
47405 generateRules : function(cm){
47406 var AO = [], AP = this.idToCssName(this.grid.id)+ '-cssrules';
47407 Roo.util.CSS.removeStyleSheet(AP);
47408 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
47409 var cid = cm.getColumnId(i);
47411 if(cm.config[i].align){
47412 align = 'text-align:'+cm.config[i].align+';';
47415 if(cm.isHidden(i)){
47416 hidden = 'display:none;';
47418 var width = "width:" + (cm.getColumnWidth(i) - this.borderWidth) + "px;";
47420 this.colSelector, cid, " {\n", cm.config[i].css, align, width, "\n}\n",
47421 this.hdSelector, cid, " {\n", align, width, "}\n",
47422 this.tdSelector, cid, " {\n",hidden,"\n}\n",
47423 this.splitSelector, cid, " {\n", hidden , "\n}\n");
47425 return Roo.util.CSS.createStyleSheet(AO.join(""), AP);
47428 updateSplitters : function(){
47429 var cm = this.cm, s = this.getSplitters();
47430 if(s){ // splitters not created yet
47431 var AN = 0, Y = true;
47432 for(var i = 0, len = cm.getColumnCount(); i < len; i++){
47433 if(cm.isHidden(i)) continue;
47434 var w = cm.getColumnWidth(i);
47435 if(!cm.isLocked(i) && Y){
47441 s[i].style.left = (AN-this.splitOffset) + "px";
47446 handleHiddenChange : function(AQ, AR, AS){
47448 this.hideColumn(AR);
47450 this.unhideColumn(AR);
47454 hideColumn : function(AT){
47455 var AU = this.getColumnId(AT);
47456 this.css.updateRule(this.tdSelector+this.idToCssName(AU), "display", "none");
47457 this.css.updateRule(this.splitSelector+this.idToCssName(AU), "display", "none");
47459 this.updateHeaders();
47462 this.updateSplitters();
47466 unhideColumn : function(AV){
47467 var AW = this.getColumnId(AV);
47468 this.css.updateRule(this.tdSelector+this.idToCssName(AW), "display", "");
47469 this.css.updateRule(this.splitSelector+this.idToCssName(AW), "display", "");
47472 this.updateHeaders();
47475 this.updateSplitters();
47479 insertRows : function(dm, AX, AY, AZ){
47480 if(AX == 0 && AY == dm.getCount()-1){
47484 this.fireEvent("beforerowsinserted", this, AX, AY);
47486 var s = this.getScrollState();
47487 var markup = this.renderRows(AX, AY);
47488 this.bufferRows(markup[0], this.getLockedTable(), AX);
47489 this.bufferRows(markup[1], this.getBodyTable(), AX);
47490 this.restoreScroll(s);
47492 this.fireEvent("rowsinserted", this, AX, AY);
47493 this.syncRowHeights(AX, AY);
47494 this.stripeRows(AX);
47500 bufferRows : function(Aa, Ab, Ac){
47501 var Ad = null, Ae = Ab.rows, Af = Ab.tBodies[0];
47502 if(Ac < Ae.length){
47505 var b = document.createElement("div");
47506 b.innerHTML = "<table><tbody>"+Aa+"</tbody></table>";
47507 var Ag = b.firstChild.rows;
47508 for(var i = 0, len = Ag.length; i < len; i++){
47510 Af.insertBefore(Ag[0], Ad);
47512 Af.appendChild(Ag[0]);
47520 deleteRows : function(dm, Ah, Ai){
47521 if(dm.getRowCount()<1){
47522 this.fireEvent("beforerefresh", this);
47523 this.mainBody.update("");
47524 this.lockedBody.update("");
47525 this.fireEvent("refresh", this);
47527 this.fireEvent("beforerowsdeleted", this, Ah, Ai);
47528 var bt = this.getBodyTable();
47529 var Af = bt.firstChild;
47531 for(var a = Ah; a <= Ai; a++){
47532 Af.removeChild(Ag[Ah]);
47535 this.stripeRows(Ah);
47536 this.fireEvent("rowsdeleted", this, Ah, Ai);
47540 updateRows : function(Aj, Ak, Al){
47541 var s = this.getScrollState();
47543 this.restoreScroll(s);
47546 handleSort : function(Am, An, Ao, Ap){
47551 this.updateHeaderSortState();
47554 getScrollState : function(){
47555 var sb = this.scroller.dom;
47556 return {left: sb.scrollLeft, top: sb.scrollTop};
47559 stripeRows : function(Aq){
47560 if(!this.grid.stripeRows || this.ds.getCount() < 1){
47565 var Ar = this.getBodyTable().rows;
47566 var As = this.getLockedTable().rows;
47567 var At = ' x-grid-row-alt ';
47568 for(var i = Aq, len = Ar.length; i < len; i++){
47569 var AB = Ar[i], U = As[i];
47570 var isAlt = ((i+1) % 2 == 0);
47571 var hasAlt = (' '+AB.className + ' ').indexOf(At) != -1;
47572 if(isAlt == hasAlt){
47576 AB.className += " x-grid-row-alt";
47578 AB.className = AB.className.replace("x-grid-row-alt", "");
47581 U.className = AB.className;
47586 restoreScroll : function(Au){
47587 var sb = this.scroller.dom;
47588 sb.scrollLeft = Au.left;
47589 sb.scrollTop = Au.top;
47593 syncScroll : function(){
47594 var sb = this.scroller.dom;
47595 var sh = this.mainHd.dom;
47596 var bs = this.mainBody.dom;
47597 var lv = this.lockedBody.dom;
47598 sh.scrollLeft = bs.scrollLeft = sb.scrollLeft;
47599 lv.scrollTop = bs.scrollTop = sb.scrollTop;
47602 handleScroll : function(e){
47604 var sb = this.scroller.dom;
47605 this.grid.fireEvent("bodyscroll", sb.scrollLeft, sb.scrollTop);
47609 handleWheel : function(e){
47610 var d = e.getWheelDelta();
47611 this.scroller.dom.scrollTop -= d*22;
47612 // set this here to prevent jumpy scrolling on large tables
47613 this.lockedBody.dom.scrollTop = this.mainBody.dom.scrollTop = this.scroller.dom.scrollTop;
47617 renderRows : function(Av, Aw){
47618 // pull in all the crap needed to render rows
47619 var g = this.grid, cm = g.colModel, ds = g.dataSource, Ax = g.stripeRows;
47620 var Ay = cm.getColumnCount();
47622 if(ds.getCount() < 1){
47626 // build a map for all the columns
47628 for(var i = 0; i < Ay; i++){
47629 var name = cm.getDataIndex(i);
47631 name : typeof name == 'undefined' ? ds.fields.get(i).name : name,
47632 renderer : cm.getRenderer(i),
47633 id : cm.getColumnId(i),
47634 locked : cm.isLocked(i)
47640 Aw = typeof Aw == "undefined"? ds.getCount()-1 : Aw;
47642 // records to render
47643 var rs = ds.getRange(Av, Aw);
47645 return this.doRender(cs, rs, ds, Av, Ay, Ax);
47648 // As much as I hate to duplicate code, this was branched because FireFox really hates
47649 // [].join("") on strings. The performance difference was substantial enough to
47650 // branch this function
47651 doRender : Roo.isGecko ?
47652 function(cs, rs, ds, Az, A0, A1){
47653 var ts = this.templates, ct = ts.cell, rt = ts.row;
47655 var A2 = "", A3 = "", cb, A4, c, p = {}, rp = {}, r, a;
47656 for(var j = 0, len = rs.length; j < len; j++){
47657 r = rs[j]; cb = ""; A4 = ""; a = (j+Az);
47658 for(var i = 0; i < A0; i++){
47660 p.cellId = "x-grid-cell-" + a + "-" + i;
47662 p.css = p.attr = "";
47663 p.value = c.renderer(r.data[c.name], p, r, a, i, ds);
47664 if(p.value == undefined || p.value === "") p.value = " ";
47665 if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
47666 p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
47668 var Aa = ct.apply(p);
47676 if(A1 && ((a+1) % 2 == 0)){
47677 alt[0] = "x-grid-row-alt";
47680 alt[1] = " x-grid-dirty-row";
47684 if(this.getRowClass){
47685 alt[2] = this.getRowClass(r, a);
47688 rp.alt = alt.join(" ");
47695 function(cs, rs, ds, A5, A6, A7){
47696 var ts = this.templates, ct = ts.cell, rt = ts.row;
47698 var A8 = [], A9 = [], cb, BA, c, p = {}, rp = {}, r, a;
47699 for(var j = 0, len = rs.length; j < len; j++){
47700 r = rs[j]; cb = []; BA = []; a = (j+A5);
47701 for(var i = 0; i < A6; i++){
47703 p.cellId = "x-grid-cell-" + a + "-" + i;
47705 p.css = p.attr = "";
47706 p.value = c.renderer(r.data[c.name], p, r, a, i, ds);
47707 if(p.value == undefined || p.value === "") p.value = " ";
47708 if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
47709 p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
47711 var Aa = ct.apply(p);
47713 cb[cb.length] = Aa;
47715 BA[BA.length] = Aa;
47719 if(A7 && ((a+1) % 2 == 0)){
47720 alt[0] = "x-grid-row-alt";
47723 alt[1] = " x-grid-dirty-row";
47727 if(this.getRowClass){
47728 alt[2] = this.getRowClass(r, a);
47731 rp.alt = alt.join(" ");
47732 rp.cells = BA.join("");
47733 A9[A9.length] = rt.apply(rp);
47734 rp.cells = cb.join("");
47735 A8[A8.length] = rt.apply(rp);
47737 return [A9.join(""), A8.join("")];
47740 renderBody : function(){
47741 var BB = this.renderRows();
47742 var bt = this.templates.body;
47743 return [bt.apply({rows: BB[0]}), bt.apply({rows: BB[1]})];
47747 * Refreshes the grid
47748 * @param {Boolean} headersToo
47750 refresh : function(BC){
47751 this.fireEvent("beforerefresh", this);
47752 this.grid.stopEditing();
47753 var BD = this.renderBody();
47754 this.lockedBody.update(BD[0]);
47755 this.mainBody.update(BD[1]);
47757 this.updateHeaders();
47758 this.updateColumns();
47759 this.updateSplitters();
47760 this.updateHeaderSortState();
47763 this.syncRowHeights();
47765 this.fireEvent("refresh", this);
47768 handleColumnMove : function(cm, BE, BF){
47769 this.indexMap = null;
47770 var s = this.getScrollState();
47771 this.refresh(true);
47772 this.restoreScroll(s);
47773 this.afterMove(BF);
47776 afterMove : function(BG){
47777 if(this.enableMoveAnim && Roo.enableFx){
47778 this.fly(this.getHeaderCell(BG).firstChild).highlight(this.hlColor);
47782 updateCell : function(dm, BH, BI){
47783 var BJ = this.getColumnIndexByDataIndex(BI);
47784 if(typeof BJ == "undefined"){ // not present in grid
47787 var cm = this.grid.colModel;
47788 var BK = this.getCell(BH, BJ);
47789 var BL = this.getCellText(BH, BJ);
47792 cellId : "x-grid-cell-" + BH + "-" + BJ,
47793 id : cm.getColumnId(BJ),
47794 css: BJ == cm.getColumnCount()-1 ? "x-grid-col-last" : ""
47796 var BM = cm.getRenderer(BJ);
47797 var BN = BM(dm.getValueAt(BH, BI), p, BH, BJ, dm);
47798 if(typeof BN == "undefined" || BN === "") BN = " ";
47800 BK.className = this.cellClass + " " + this.idToCssName(p.cellId) + " " + p.css;
47801 this.syncRowHeights(BH, BH);
47804 calcColumnWidth : function(BO, BP){
47806 if(this.grid.autoSizeHeaders){
47807 var h = this.getHeaderCellMeasure(BO);
47808 BQ = Math.max(BQ, h.scrollWidth);
47811 if(this.cm.isLocked(BO)){
47812 tb = this.getLockedTable();
47815 tb = this.getBodyTable();
47816 BR = BO - this.cm.getLockedCount();
47820 var stopIndex = Math.min(BP || Ar.length, Ar.length);
47821 for(var i = 0; i < stopIndex; i++){
47822 var BK = Ar[i].childNodes[BR].firstChild;
47823 BQ = Math.max(BQ, BK.scrollWidth);
47826 return BQ + /*margin for error in IE*/ 5;
47829 * Autofit a column to its content.
47830 * @param {Number} colIndex
47831 * @param {Boolean} forceMinSize true to force the column to go smaller if possible
47833 autoSizeColumn : function(BS, BT, BU){
47834 if(this.cm.isHidden(BS)){
47835 return; // can't calc a hidden column
47838 var AW = this.cm.getColumnId(BS);
47839 this.css.updateRule(this.colSelector +this.idToCssName( AW), "width", this.grid.minColumnWidth + "px");
47840 if(this.grid.autoSizeHeaders){
47841 this.css.updateRule(this.hdSelector + this.idToCssName(AW), "width", this.grid.minColumnWidth + "px");
47844 var BV = this.calcColumnWidth(BS);
47845 this.cm.setColumnWidth(BS,
47846 Math.max(this.grid.minColumnWidth, BV), BU);
47848 this.grid.fireEvent("columnresize", BS, BV);
47853 * Autofits all columns to their content and then expands to fit any extra space in the grid
47855 autoSizeColumns : function(){
47856 var cm = this.grid.colModel;
47857 var BW = cm.getColumnCount();
47858 for(var i = 0; i < BW; i++){
47859 this.autoSizeColumn(i, true, true);
47861 if(cm.getTotalWidth() < this.scroller.dom.clientWidth){
47864 this.updateColumns();
47870 * Autofits all columns to the grid's width proportionate with their current size
47871 * @param {Boolean} reserveScrollSpace Reserve space for a scrollbar
47873 fitColumns : function(BX){
47874 var cm = this.grid.colModel;
47875 var BY = cm.getColumnCount();
47879 for (i = 0; i < BY; i++){
47880 if(!cm.isHidden(i) && !cm.isFixed(i)){
47881 w = cm.getColumnWidth(i);
47887 var Bb = Math.min(this.scroller.dom.clientWidth, this.el.getWidth());
47891 var Bc = (Bb - cm.getTotalWidth())/Ba;
47895 cm.setColumnWidth(i, Math.floor(w + w*Bc), true);
47898 this.updateColumns();
47902 onRowSelect : function(Bd){
47903 var Be = this.getRowComposite(Bd);
47904 Be.addClass("x-grid-row-selected");
47907 onRowDeselect : function(Bf){
47908 var Bg = this.getRowComposite(Bf);
47909 Bg.removeClass("x-grid-row-selected");
47912 onCellSelect : function(Bh, Bi){
47913 var Bj = this.getCell(Bh, Bi);
47915 Roo.fly(Bj).addClass("x-grid-cell-selected");
47919 onCellDeselect : function(Bk, Bl){
47920 var Bm = this.getCell(Bk, Bl);
47922 Roo.fly(Bm).removeClass("x-grid-cell-selected");
47926 updateHeaderSortState : function(){
47927 var Bn = this.ds.getSortState();
47932 this.sortState = Bn;
47933 var Bo = this.cm.findColumnIndex(Bn.field);
47935 var Ao = Bn.direction;
47936 var sc = this.sortClasses;
47937 var hds = this.el.select(this.headerSelector).removeClass(sc);
47938 hds.item(Bo).addClass(sc[Ao == "DESC" ? 1 : 0]);
47942 handleHeaderClick : function(g, Bp){
47943 if(this.headersDisabled){
47946 var dm = g.dataSource, cm = g.colModel;
47947 if(!cm.isSortable(Bp)){
47952 dm.sort(cm.getDataIndex(Bp));
47956 destroy : function(){
47958 this.colMenu.removeAll();
47959 Roo.menu.MenuMgr.unregister(this.colMenu);
47960 this.colMenu.getEl().remove();
47961 delete this.colMenu;
47964 this.hmenu.removeAll();
47965 Roo.menu.MenuMgr.unregister(this.hmenu);
47966 this.hmenu.getEl().remove();
47969 if(this.grid.enableColumnMove){
47970 var dds = Roo.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
47972 for(var dd in dds){
47973 if(!dds[dd].config.isTarget && dds[dd].dragElId){
47974 var elid = dds[dd].dragElId;
47976 Roo.get(elid).remove();
47977 } else if(dds[dd].config.isTarget){
47978 dds[dd].proxyTop.remove();
47979 dds[dd].proxyBottom.remove();
47982 if(Roo.dd.DDM.locationCache[dd]){
47983 delete Roo.dd.DDM.locationCache[dd];
47986 delete Roo.dd.DDM.ids['gridHeader' + this.grid.getGridEl().id];
47990 Roo.util.CSS.removeStyleSheet(this.idToCssName(this.grid.id) + '-cssrules');
47991 this.bind(null, null);
47992 Roo.EventManager.removeResizeListener(this.onWindowResize, this);
47995 handleLockChange : function(){
47996 this.refresh(true);
47999 onDenyColumnLock : function(){
48003 onDenyColumnHide : function(){
48007 handleHdMenuClick : function(Bq){
48008 var Br = this.hdCtxIndex;
48009 var cm = this.cm, ds = this.ds;
48012 ds.sort(cm.getDataIndex(Br), "ASC");
48015 ds.sort(cm.getDataIndex(Br), "DESC");
48018 var lc = cm.getLockedCount();
48019 if(cm.getColumnCount(true) <= lc+1){
48020 this.onDenyColumnLock();
48024 cm.setLocked(Br, true, true);
48025 cm.moveColumn(Br, lc);
48026 this.grid.fireEvent("columnmove", Br, lc);
48028 cm.setLocked(Br, true);
48032 var lc = cm.getLockedCount();
48034 cm.setLocked(Br, false, true);
48035 cm.moveColumn(Br, lc-1);
48036 this.grid.fireEvent("columnmove", Br, lc-1);
48038 cm.setLocked(Br, false);
48042 Br = cm.getIndexById(Bq.id.substr(4));
48044 if(Bq.checked && cm.getColumnCount(true) <= 1){
48045 this.onDenyColumnHide();
48049 cm.setHidden(Br, Bq.checked);
48055 beforeColMenuShow : function(){
48056 var cm = this.cm, Bs = cm.getColumnCount();
48057 this.colMenu.removeAll();
48058 for(var i = 0; i < Bs; i++){
48059 this.colMenu.add(new Roo.menu.CheckItem({
48060 id: "col-"+cm.getColumnId(i),
48061 text: cm.getColumnHeader(i),
48062 checked: !cm.isHidden(i),
48068 handleHdCtx : function(g, Bt, e){
48070 var hd = this.getHeaderCell(Bt);
48071 this.hdCtxIndex = Bt;
48072 var ms = this.hmenu.items, cm = this.cm;
48073 ms.get("asc").setDisabled(!cm.isSortable(Bt));
48074 ms.get("desc").setDisabled(!cm.isSortable(Bt));
48075 if(this.grid.enableColLock !== false){
48076 ms.get("lock").setDisabled(cm.isLocked(Bt));
48077 ms.get("unlock").setDisabled(!cm.isLocked(Bt));
48080 this.hmenu.show(hd, "tl-bl");
48083 handleHdOver : function(e){
48084 var hd = this.findHeaderCell(e.getTarget());
48085 if(hd && !this.headersDisabled){
48086 if(this.grid.colModel.isSortable(this.getCellIndex(hd))){
48087 this.fly(hd).addClass("x-grid-hd-over");
48092 handleHdOut : function(e){
48093 var hd = this.findHeaderCell(e.getTarget());
48095 this.fly(hd).removeClass("x-grid-hd-over");
48099 handleSplitDblClick : function(e, t){
48100 var i = this.getCellIndex(t);
48101 if(this.grid.enableColumnResize !== false && this.cm.isResizable(i) && !this.cm.isFixed(i)){
48102 this.autoSizeColumn(i, true);
48107 render : function(){
48110 var Bu = cm.getColumnCount();
48112 if(this.grid.monitorWindowResize === true){
48113 Roo.EventManager.onWindowResize(this.onWindowResize, this, true);
48115 var Bv = this.renderHeaders();
48116 var Bw = this.templates.body.apply({rows:""});
48117 var Bx = this.templates.master.apply({
48120 lockedHeader: Bv[0],
48124 //this.updateColumns();
48126 this.grid.getGridEl().dom.innerHTML = Bx;
48128 this.initElements();
48130 this.scroller.on("scroll", this.handleScroll, this);
48131 this.lockedBody.on("mousewheel", this.handleWheel, this);
48132 this.mainBody.on("mousewheel", this.handleWheel, this);
48134 this.mainHd.on("mouseover", this.handleHdOver, this);
48135 this.mainHd.on("mouseout", this.handleHdOut, this);
48136 this.mainHd.on("dblclick", this.handleSplitDblClick, this,
48137 {delegate: "."+this.splitClass});
48139 this.lockedHd.on("mouseover", this.handleHdOver, this);
48140 this.lockedHd.on("mouseout", this.handleHdOut, this);
48141 this.lockedHd.on("dblclick", this.handleSplitDblClick, this,
48142 {delegate: "."+this.splitClass});
48144 if(this.grid.enableColumnResize !== false && Roo.grid.SplitDragZone){
48145 new Roo.grid.SplitDragZone(this.grid, this.lockedHd.dom, this.mainHd.dom);
48149 this.updateSplitters();
48151 if(this.grid.enableColumnMove && Roo.grid.HeaderDragZone){
48152 new Roo.grid.HeaderDragZone(this.grid, this.lockedHd.dom, this.mainHd.dom);
48153 new Roo.grid.HeaderDropZone(this.grid, this.lockedHd.dom, this.mainHd.dom);
48156 if(this.grid.enableCtxMenu !== false && Roo.menu.Menu){
48157 this.hmenu = new Roo.menu.Menu({id: this.grid.id + "-hctx"});
48159 {id:"asc", text: this.sortAscText, cls: "xg-hmenu-sort-asc"},
48160 {id:"desc", text: this.sortDescText, cls: "xg-hmenu-sort-desc"}
48162 if(this.grid.enableColLock !== false){
48163 this.hmenu.add('-',
48164 {id:"lock", text: this.lockText, cls: "xg-hmenu-lock"},
48165 {id:"unlock", text: this.unlockText, cls: "xg-hmenu-unlock"}
48168 if(this.grid.enableColumnHide !== false){
48170 this.colMenu = new Roo.menu.Menu({id:this.grid.id + "-hcols-menu"});
48171 this.colMenu.on("beforeshow", this.beforeColMenuShow, this);
48172 this.colMenu.on("itemclick", this.handleHdMenuClick, this);
48174 this.hmenu.add('-',
48175 {id:"columns", text: this.columnsText, menu: this.colMenu}
48179 this.hmenu.on("itemclick", this.handleHdMenuClick, this);
48181 this.grid.on("headercontextmenu", this.handleHdCtx, this);
48184 if((this.grid.enableDragDrop || this.grid.enableDrag) && Roo.grid.GridDragZone){
48185 this.dd = new Roo.grid.GridDragZone(this.grid, {
48186 ddGroup : this.grid.ddGroup || 'GridDD'
48192 for(var i = 0; i < colCount; i++){
48193 if(cm.isHidden(i)){
48194 this.hideColumn(i);
48196 if(cm.config[i].align){
48197 this.css.updateRule(this.colSelector + i, "textAlign", cm.config[i].align);
48198 this.css.updateRule(this.hdSelector + i, "textAlign", cm.config[i].align);
48202 this.updateHeaderSortState();
48204 this.beforeInitialResize();
48207 // two part rendering gives faster view to the user
48208 this.renderPhase2.defer(1, this);
48211 renderPhase2 : function(){
48212 // render the rows now
48214 if(this.grid.autoSizeColumns){
48215 this.autoSizeColumns();
48219 beforeInitialResize : function(){
48223 onColumnSplitterMoved : function(i, w){
48224 this.userResized = true;
48225 var cm = this.grid.colModel;
48226 cm.setColumnWidth(i, w, true);
48227 var By = cm.getColumnId(i);
48228 this.css.updateRule(this.colSelector + this.idToCssName(By), "width", (w-this.borderWidth) + "px");
48229 this.css.updateRule(this.hdSelector + this.idToCssName(By), "width", (w-this.borderWidth) + "px");
48230 this.updateSplitters();
48232 this.grid.fireEvent("columnresize", i, w);
48235 syncRowHeights : function(Bz, B0){
48236 if(this.grid.enableRowHeightSync === true && this.cm.getLockedCount() > 0){
48238 var mrows = this.getBodyTable().rows;
48239 var As = this.getLockedTable().rows;
48240 var len = mrows.length-1;
48241 B0 = Math.min(B0 || len, len);
48242 for(var i = Bz; i <= B0; i++){
48243 var m = mrows[i], l = As[i];
48244 var h = Math.max(m.offsetHeight, l.offsetHeight);
48245 m.style.height = l.style.height = h + "px";
48250 layout : function(B1, B2){
48252 var B3 = g.autoHeight;
48254 var c = g.getGridEl(), cm = this.cm,
48255 B5 = g.autoExpandColumn,
48257 //c.beginMeasure();
48259 if(!c.dom.offsetWidth){ // display:none?
48261 this.lockedWrap.show();
48262 this.mainWrap.show();
48267 var B6 = this.cm.isLocked(0);
48269 var B7 = this.headerPanel.getHeight();
48270 var B8 = this.footerPanel.getHeight();
48273 var ch = this.getBodyTable().offsetHeight + B7 + B8 + this.mainHd.getHeight();
48274 var newHeight = ch + c.getBorderWidth("tb");
48276 newHeight = Math.min(g.maxHeight, newHeight);
48279 c.setHeight(newHeight);
48283 c.setWidth(cm.getTotalWidth()+c.getBorderWidth('lr'));
48286 var s = this.scroller;
48288 var B9 = c.getSize(true);
48290 this.el.setSize(B9.width, B9.height);
48292 this.headerPanel.setWidth(B9.width);
48293 this.footerPanel.setWidth(B9.width);
48295 var CA = this.mainHd.getHeight();
48297 var vh = B9.height - (B7 + B8);
48301 var bt = this.getBodyTable();
48303 Math.max(this.getLockedTable().offsetWidth, this.lockedHd.dom.firstChild.offsetWidth) : 0;
48305 var CC = bt.offsetHeight;
48306 var CD = CB + bt.offsetWidth;
48307 var CE = false, CF = false;
48309 this.scrollSizer.setSize(CD, CC+CA);
48311 var lw = this.lockedWrap, mw = this.mainWrap;
48312 var lb = this.lockedBody, mb = this.mainBody;
48314 setTimeout(function(){
48315 var t = s.dom.offsetTop;
48316 var w = s.dom.clientWidth,
48317 h = s.dom.clientHeight;
48322 mw.setLeftTop(CB, t);
48323 mw.setSize(w-CB, h);
48325 lb.setHeight(h-CA);
48326 mb.setHeight(h-CA);
48328 if(B2 !== true && !gv.userResized && B5){
48329 // high speed resize without full column calculation
48331 var ci = cm.getIndexById(B5);
48333 ci = cm.findColumnIndex(B5);
48336 ci = Math.max(0, ci); // make sure it's got at least the first col.
48337 var expandId = cm.getColumnId(ci);
48338 var tw = cm.getTotalWidth(false);
48339 var currentWidth = cm.getColumnWidth(ci);
48340 var cw = Math.min(Math.max(((w-tw)+currentWidth-2)-/*scrollbar*/(w <= s.dom.offsetWidth ? 0 : 18), g.autoExpandMin), g.autoExpandMax);
48341 if(currentWidth != cw){
48342 cm.setColumnWidth(ci, cw, true);
48343 gv.css.updateRule(gv.colSelector+gv.idToCssName(expandId), "width", (cw - gv.borderWidth) + "px");
48344 gv.css.updateRule(gv.hdSelector+gv.idToCssName(expandId), "width", (cw - gv.borderWidth) + "px");
48345 gv.updateSplitters();
48346 gv.layout(false, true);
48358 onWindowResize : function(){
48359 if(!this.grid.monitorWindowResize || this.grid.autoHeight){
48366 appendFooter : function(CG){
48370 sortAscText : "Sort Ascending",
48371 sortDescText : "Sort Descending",
48372 lockText : "Lock Column",
48373 unlockText : "Unlock Column",
48374 columnsText : "Columns"
48378 Roo.grid.GridView.ColumnDragZone = function(CH, hd){
48379 Roo.grid.GridView.ColumnDragZone.superclass.constructor.call(this, CH, hd, null);
48380 this.proxy.el.addClass('x-grid3-col-dd');
48383 Roo.extend(Roo.grid.GridView.ColumnDragZone, Roo.grid.HeaderDragZone, {
48384 handleMouseDown : function(e){
48388 callHandleMouseDown : function(e){
48389 Roo.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
48395 * Ext JS Library 1.1.1
48396 * Copyright(c) 2006-2007, Ext JS, LLC.
48398 * Originally Released Under LGPL - original licence link has changed is not relivant.
48401 * <script type="text/javascript">
48405 // This is a support class used internally by the Grid components
48406 Roo.grid.SplitDragZone = function(A, hd, B){
48408 this.view = A.getView();
48409 this.proxy = this.view.resizeProxy;
48410 Roo.grid.SplitDragZone.superclass.constructor.call(this, hd,
48411 "gridSplitters" + this.grid.getGridEl().id, {
48412 dragElId : Roo.id(this.proxy.dom), resizeFrame:false
48414 this.setHandleElId(Roo.id(hd));
48415 this.setOuterHandleElId(Roo.id(B));
48416 this.scroll = false;
48418 Roo.extend(Roo.grid.SplitDragZone, Roo.dd.DDProxy, {
48419 fly: Roo.Element.fly,
48421 b4StartDrag : function(x, y){
48422 this.view.headersDisabled = true;
48423 this.proxy.setHeight(this.view.mainWrap.getHeight());
48424 var w = this.cm.getColumnWidth(this.cellIndex);
48425 var C = Math.max(w-this.grid.minColumnWidth, 0);
48426 this.resetConstraints();
48427 this.setXConstraint(C, 1000);
48428 this.setYConstraint(0, 0);
48430 this.maxX = x + 1000;
48432 Roo.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
48436 handleMouseDown : function(e){
48437 ev = Roo.EventObject.setEvent(e);
48438 var t = this.fly(ev.getTarget());
48439 if(t.hasClass("x-grid-split")){
48440 this.cellIndex = this.view.getCellIndex(t.dom);
48441 this.split = t.dom;
48442 this.cm = this.grid.colModel;
48443 if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
48444 Roo.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
48449 endDrag : function(e){
48450 this.view.headersDisabled = false;
48451 var D = Math.max(this.minX, Roo.lib.Event.getPageX(e));
48452 var E = D - this.startPos;
48453 this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+E);
48456 autoOffset : function(){
48457 this.setDelta(0,0);
48462 * Ext JS Library 1.1.1
48463 * Copyright(c) 2006-2007, Ext JS, LLC.
48465 * Originally Released Under LGPL - original licence link has changed is not relivant.
48468 * <script type="text/javascript">
48472 // This is a support class used internally by the Grid components
48473 Roo.grid.GridDragZone = function(A, B){
48474 this.view = A.getView();
48475 Roo.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, B);
48476 if(this.view.lockedBody){
48477 this.setHandleElId(Roo.id(this.view.mainBody.dom));
48478 this.setOuterHandleElId(Roo.id(this.view.lockedBody.dom));
48481 this.scroll = false;
48483 this.ddel = document.createElement('div');
48484 this.ddel.className = 'x-grid-dd-wrap';
48487 Roo.extend(Roo.grid.GridDragZone, Roo.dd.DragZone, {
48488 ddGroup : "GridDD",
48490 getDragData : function(e){
48491 var t = Roo.lib.Event.getTarget(e);
48492 var C = this.view.findRowIndex(t);
48494 var sm = this.grid.selModel;
48495 //if(!sm.isSelected(rowIndex) || e.hasModifier()){
48496 // sm.mouseDown(e, t);
48498 if (e.hasModifier()){
48499 sm.handleMouseDown(e, t); // non modifier buttons are handled by row select.
48501 return {grid: this.grid, ddel: this.ddel, rowIndex: C, selections:sm.getSelections()};
48506 onInitDrag : function(e){
48507 var D = this.dragData;
48508 this.ddel.innerHTML = this.grid.getDragDropText();
48509 this.proxy.update(this.ddel);
48510 // fire start drag?
48513 afterRepair : function(){
48514 this.dragging = false;
48517 getRepairXY : function(e, E){
48521 onEndDrag : function(F, e){
48525 onValidDrop : function(dd, e, id){
48530 beforeInvalidDrop : function(e, id){
48536 * Ext JS Library 1.1.1
48537 * Copyright(c) 2006-2007, Ext JS, LLC.
48539 * Originally Released Under LGPL - original licence link has changed is not relivant.
48542 * <script type="text/javascript">
48547 * @class Roo.grid.ColumnModel
48548 * @extends Roo.util.Observable
48549 * This is the default implementation of a ColumnModel used by the Grid. It defines
48550 * the columns in the grid.
48553 var colModel = new Roo.grid.ColumnModel([
48554 {header: "Ticker", width: 60, sortable: true, locked: true},
48555 {header: "Company Name", width: 150, sortable: true},
48556 {header: "Market Cap.", width: 100, sortable: true},
48557 {header: "$ Sales", width: 100, sortable: true, renderer: money},
48558 {header: "Employees", width: 100, sortable: true, resizable: false}
48563 * The config options listed for this class are options which may appear in each
48564 * individual column definition.
48565 * <br/>RooJS Fix - column id's are not sequential but use Roo.id() - fixes bugs with layouts.
48567 * @param {Object} config An Array of column config objects. See this class's
48568 * config objects for details.
48570 Roo.grid.ColumnModel = function(A){
48572 * The config passed into the constructor
48577 // if no id, create one
48578 // if the column does not have a dataIndex mapping,
48579 // map it to the order it is in the config
48580 for(var i = 0, len = A.length; i < len; i++){
48582 if(typeof c.dataIndex == "undefined"){
48585 if(typeof c.renderer == "string"){
48586 c.renderer = Roo.util.Format[c.renderer];
48588 if(typeof c.id == "undefined"){
48591 if(c.editor && c.editor.xtype){
48592 c.editor = Roo.factory(c.editor, Roo.grid);
48594 if(c.editor && c.editor.isFormField){
48595 c.editor = new Roo.grid.GridEditor(c.editor);
48598 this.lookup[c.id] = c;
48603 * The width of columns which have no width specified (defaults to 100)
48606 this.defaultWidth = 100;
48609 * Default sortable of columns which have no sortable specified (defaults to false)
48612 this.defaultSortable = false;
48616 * @event widthchange
48617 * Fires when the width of a column changes.
48618 * @param {ColumnModel} this
48619 * @param {Number} columnIndex The column index
48620 * @param {Number} newWidth The new width
48622 "widthchange": true,
48624 * @event headerchange
48625 * Fires when the text of a header changes.
48626 * @param {ColumnModel} this
48627 * @param {Number} columnIndex The column index
48628 * @param {Number} newText The new header text
48630 "headerchange": true,
48632 * @event hiddenchange
48633 * Fires when a column is hidden or "unhidden".
48634 * @param {ColumnModel} this
48635 * @param {Number} columnIndex The column index
48636 * @param {Boolean} hidden true if hidden, false otherwise
48638 "hiddenchange": true,
48640 * @event columnmoved
48641 * Fires when a column is moved.
48642 * @param {ColumnModel} this
48643 * @param {Number} oldIndex
48644 * @param {Number} newIndex
48646 "columnmoved" : true,
48648 * @event columlockchange
48649 * Fires when a column's locked state is changed
48650 * @param {ColumnModel} this
48651 * @param {Number} colIndex
48652 * @param {Boolean} locked true if locked
48654 "columnlockchange" : true
48656 Roo.grid.ColumnModel.superclass.constructor.call(this);
48658 Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
48660 * @cfg {String} header The header text to display in the Grid view.
48663 * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s
48664 * {@link Roo.data.Record} definition from which to draw the column's value. If not
48665 * specified, the column's index is used as an index into the Record's data Array.
48668 * @cfg {Number} width (Optional) The initial width in pixels of the column. Using this
48669 * instead of {@link Roo.grid.Grid#autoSizeColumns} is more efficient.
48672 * @cfg {Boolean} sortable (Optional) True if sorting is to be allowed on this column.
48673 * Defaults to the value of the {@link #defaultSortable} property.
48674 * Whether local/remote sorting is used is specified in {@link Roo.data.Store#remoteSort}.
48677 * @cfg {Boolean} locked (Optional) True to lock the column in place while scrolling the Grid. Defaults to false.
48680 * @cfg {Boolean} fixed (Optional) True if the column width cannot be changed. Defaults to false.
48683 * @cfg {Boolean} resizable (Optional) False to disable column resizing. Defaults to true.
48686 * @cfg {Boolean} hidden (Optional) True to hide the column. Defaults to false.
48689 * @cfg {Function} renderer (Optional) A function used to generate HTML markup for a cell
48690 * given the cell's data value. See {@link #setRenderer}. If not specified, the
48691 * default renderer uses the raw data value.
48694 * @cfg {Roo.grid.GridEditor} editor (Optional) For grid editors - returns the grid editor
48697 * @cfg {String} align (Optional) Set the CSS text-align property of the column. Defaults to undefined.
48701 * Returns the id of the column at the specified index.
48702 * @param {Number} index The column index
48703 * @return {String} the id
48705 getColumnId : function(B){
48706 return this.config[B].id;
48710 * Returns the column for a specified id.
48711 * @param {String} id The column id
48712 * @return {Object} the column
48714 getColumnById : function(id){
48715 return this.lookup[id];
48719 * Returns the index for a specified column id.
48720 * @param {String} id The column id
48721 * @return {Number} the index, or -1 if not found
48723 getIndexById : function(id){
48724 for(var i = 0, len = this.config.length; i < len; i++){
48725 if(this.config[i].id == id){
48732 * Returns the index for a specified column dataIndex.
48733 * @param {String} dataIndex The column dataIndex
48734 * @return {Number} the index, or -1 if not found
48737 findColumnIndex : function(C){
48738 for(var i = 0, len = this.config.length; i < len; i++){
48739 if(this.config[i].dataIndex == C){
48747 moveColumn : function(D, E){
48748 var c = this.config[D];
48749 this.config.splice(D, 1);
48750 this.config.splice(E, 0, c);
48751 this.dataMap = null;
48752 this.fireEvent("columnmoved", this, D, E);
48755 isLocked : function(F){
48756 return this.config[F].locked === true;
48759 setLocked : function(G, H, I){
48760 if(this.isLocked(G) == H){
48764 this.config[G].locked = H;
48766 this.fireEvent("columnlockchange", this, G, H);
48770 getTotalLockedWidth : function(){
48772 for(var i = 0; i < this.config.length; i++){
48773 if(this.isLocked(i) && !this.isHidden(i)){
48774 this.totalWidth += this.getColumnWidth(i);
48780 getLockedCount : function(){
48781 for(var i = 0, len = this.config.length; i < len; i++){
48782 if(!this.isLocked(i)){
48789 * Returns the number of columns.
48792 getColumnCount : function(K){
48795 for(var i = 0, len = this.config.length; i < len; i++){
48796 if(!this.isHidden(i)){
48802 return this.config.length;
48806 * Returns the column configs that return true by the passed function that is called with (columnConfig, index)
48807 * @param {Function} fn
48808 * @param {Object} scope (optional)
48809 * @return {Array} result
48811 getColumnsBy : function(fn, L){
48813 for(var i = 0, len = this.config.length; i < len; i++){
48814 var c = this.config[i];
48815 if(fn.call(L||this, c, i) === true){
48823 * Returns true if the specified column is sortable.
48824 * @param {Number} col The column index
48825 * @return {Boolean}
48827 isSortable : function(M){
48828 if(typeof this.config[M].sortable == "undefined"){
48829 return this.defaultSortable;
48831 return this.config[M].sortable;
48835 * Returns the rendering (formatting) function defined for the column.
48836 * @param {Number} col The column index.
48837 * @return {Function} The function used to render the cell. See {@link #setRenderer}.
48839 getRenderer : function(N){
48840 if(!this.config[N].renderer){
48841 return Roo.grid.ColumnModel.defaultRenderer;
48843 return this.config[N].renderer;
48847 * Sets the rendering (formatting) function for a column.
48848 * @param {Number} col The column index
48849 * @param {Function} fn The function to use to process the cell's raw data
48850 * to return HTML markup for the grid view. The render function is called with
48851 * the following parameters:<ul>
48852 * <li>Data value.</li>
48853 * <li>Cell metadata. An object in which you may set the following attributes:<ul>
48854 * <li>css A CSS style string to apply to the table cell.</li>
48855 * <li>attr An HTML attribute definition string to apply to the data container element <i>within</i> the table cell.</li></ul>
48856 * <li>The {@link Roo.data.Record} from which the data was extracted.</li>
48857 * <li>Row index</li>
48858 * <li>Column index</li>
48859 * <li>The {@link Roo.data.Store} object from which the Record was extracted</li></ul>
48861 setRenderer : function(O, fn){
48862 this.config[O].renderer = fn;
48866 * Returns the width for the specified column.
48867 * @param {Number} col The column index
48870 getColumnWidth : function(P){
48871 return this.config[P].width || this.defaultWidth;
48875 * Sets the width for a column.
48876 * @param {Number} col The column index
48877 * @param {Number} width The new width
48879 setColumnWidth : function(Q, R, S){
48880 this.config[Q].width = R;
48881 this.totalWidth = null;
48883 this.fireEvent("widthchange", this, Q, R);
48888 * Returns the total width of all columns.
48889 * @param {Boolean} includeHidden True to include hidden column widths
48892 getTotalWidth : function(T){
48893 if(!this.totalWidth){
48894 this.totalWidth = 0;
48895 for(var i = 0, len = this.config.length; i < len; i++){
48896 if(T || !this.isHidden(i)){
48897 this.totalWidth += this.getColumnWidth(i);
48901 return this.totalWidth;
48905 * Returns the header for the specified column.
48906 * @param {Number} col The column index
48909 getColumnHeader : function(U){
48910 return this.config[U].header;
48914 * Sets the header for a column.
48915 * @param {Number} col The column index
48916 * @param {String} header The new header
48918 setColumnHeader : function(V, W){
48919 this.config[V].header = W;
48920 this.fireEvent("headerchange", this, V, W);
48924 * Returns the tooltip for the specified column.
48925 * @param {Number} col The column index
48928 getColumnTooltip : function(X){
48929 return this.config[X].tooltip;
48932 * Sets the tooltip for a column.
48933 * @param {Number} col The column index
48934 * @param {String} tooltip The new tooltip
48936 setColumnTooltip : function(Y, Z){
48937 this.config[Y].tooltip = Z;
48941 * Returns the dataIndex for the specified column.
48942 * @param {Number} col The column index
48945 getDataIndex : function(a){
48946 return this.config[a].dataIndex;
48950 * Sets the dataIndex for a column.
48951 * @param {Number} col The column index
48952 * @param {Number} dataIndex The new dataIndex
48954 setDataIndex : function(b, d){
48955 this.config[b].dataIndex = d;
48961 * Returns true if the cell is editable.
48962 * @param {Number} colIndex The column index
48963 * @param {Number} rowIndex The row index
48964 * @return {Boolean}
48966 isCellEditable : function(e, f){
48967 return (this.config[e].editable || (typeof this.config[e].editable == "undefined" && this.config[e].editor)) ? true : false;
48971 * Returns the editor defined for the cell/column.
48972 * return false or null to disable editing.
48973 * @param {Number} colIndex The column index
48974 * @param {Number} rowIndex The row index
48977 getCellEditor : function(g, h){
48978 return this.config[g].editor;
48982 * Sets if a column is editable.
48983 * @param {Number} col The column index
48984 * @param {Boolean} editable True if the column is editable
48986 setEditable : function(j, k){
48987 this.config[j].editable = k;
48992 * Returns true if the column is hidden.
48993 * @param {Number} colIndex The column index
48994 * @return {Boolean}
48996 isHidden : function(l){
48997 return this.config[l].hidden;
49002 * Returns true if the column width cannot be changed
49004 isFixed : function(m){
49005 return this.config[m].fixed;
49009 * Returns true if the column can be resized
49010 * @return {Boolean}
49012 isResizable : function(n){
49013 return n >= 0 && this.config[n].resizable !== false && this.config[n].fixed !== true;
49016 * Sets if a column is hidden.
49017 * @param {Number} colIndex The column index
49018 * @param {Boolean} hidden True if the column is hidden
49020 setHidden : function(o, p){
49021 this.config[o].hidden = p;
49022 this.totalWidth = null;
49023 this.fireEvent("hiddenchange", this, o, p);
49027 * Sets the editor for a column.
49028 * @param {Number} col The column index
49029 * @param {Object} editor The editor object
49031 setEditor : function(q, s){
49032 this.config[q].editor = s;
49036 Roo.grid.ColumnModel.defaultRenderer = function(t){
49037 if(typeof t == "string" && t.length < 1){
49043 // Alias for backwards compatibility
49044 Roo.grid.DefaultColumnModel = Roo.grid.ColumnModel;
49048 * Ext JS Library 1.1.1
49049 * Copyright(c) 2006-2007, Ext JS, LLC.
49051 * Originally Released Under LGPL - original licence link has changed is not relivant.
49054 * <script type="text/javascript">
49058 * @class Roo.grid.AbstractSelectionModel
49059 * @extends Roo.util.Observable
49060 * Abstract base class for grid SelectionModels. It provides the interface that should be
49061 * implemented by descendant classes. This class should not be directly instantiated.
49064 Roo.grid.AbstractSelectionModel = function(){
49065 this.locked = false;
49066 Roo.grid.AbstractSelectionModel.superclass.constructor.call(this);
49069 Roo.extend(Roo.grid.AbstractSelectionModel, Roo.util.Observable, {
49070 /** @ignore Called by the grid automatically. Do not call directly. */
49071 init : function(A){
49077 * Locks the selections.
49080 this.locked = true;
49084 * Unlocks the selections.
49086 unlock : function(){
49087 this.locked = false;
49091 * Returns true if the selections are locked.
49092 * @return {Boolean}
49094 isLocked : function(){
49095 return this.locked;
49100 * Ext JS Library 1.1.1
49101 * Copyright(c) 2006-2007, Ext JS, LLC.
49103 * Originally Released Under LGPL - original licence link has changed is not relivant.
49106 * <script type="text/javascript">
49109 * @extends Roo.grid.AbstractSelectionModel
49110 * @class Roo.grid.RowSelectionModel
49111 * The default SelectionModel used by {@link Roo.grid.Grid}.
49112 * It supports multiple selections and keyboard selection/navigation.
49114 * @param {Object} config
49116 Roo.grid.RowSelectionModel = function(A){
49117 Roo.apply(this, A);
49118 this.selections = new Roo.util.MixedCollection(false, function(o){
49123 this.lastActive = false;
49127 * @event selectionchange
49128 * Fires when the selection changes
49129 * @param {SelectionModel} this
49131 "selectionchange" : true,
49133 * @event afterselectionchange
49134 * Fires after the selection changes (eg. by key press or clicking)
49135 * @param {SelectionModel} this
49137 "afterselectionchange" : true,
49139 * @event beforerowselect
49140 * Fires when a row is selected being selected, return false to cancel.
49141 * @param {SelectionModel} this
49142 * @param {Number} rowIndex The selected index
49143 * @param {Boolean} keepExisting False if other selections will be cleared
49145 "beforerowselect" : true,
49148 * Fires when a row is selected.
49149 * @param {SelectionModel} this
49150 * @param {Number} rowIndex The selected index
49151 * @param {Roo.data.Record} r The record
49153 "rowselect" : true,
49155 * @event rowdeselect
49156 * Fires when a row is deselected.
49157 * @param {SelectionModel} this
49158 * @param {Number} rowIndex The selected index
49160 "rowdeselect" : true
49162 Roo.grid.RowSelectionModel.superclass.constructor.call(this);
49163 this.locked = false;
49166 Roo.extend(Roo.grid.RowSelectionModel, Roo.grid.AbstractSelectionModel, {
49168 * @cfg {Boolean} singleSelect
49169 * True to allow selection of only one row at a time (defaults to false)
49171 singleSelect : false,
49174 initEvents : function(){
49176 if(!this.grid.enableDragDrop && !this.grid.enableDrag){
49177 this.grid.on("mousedown", this.handleMouseDown, this);
49178 }else { // allow click to work like normal
49179 this.grid.on("rowclick", this.handleDragableRowClick, this);
49183 this.rowNav = new Roo.KeyNav(this.grid.getGridEl(), {
49184 "up" : function(e){
49186 this.selectPrevious(e.shiftKey);
49187 }else if(this.last !== false && this.lastActive !== false){
49188 var last = this.last;
49189 this.selectRange(this.last, this.lastActive-1);
49190 this.grid.getView().focusRow(this.lastActive);
49191 if(last !== false){
49195 this.selectFirstRow();
49198 this.fireEvent("afterselectionchange", this);
49200 "down" : function(e){
49202 this.selectNext(e.shiftKey);
49203 }else if(this.last !== false && this.lastActive !== false){
49204 var last = this.last;
49205 this.selectRange(this.last, this.lastActive+1);
49206 this.grid.getView().focusRow(this.lastActive);
49207 if(last !== false){
49211 this.selectFirstRow();
49214 this.fireEvent("afterselectionchange", this);
49219 var B = this.grid.view;
49220 B.on("refresh", this.onRefresh, this);
49221 B.on("rowupdated", this.onRowUpdated, this);
49222 B.on("rowremoved", this.onRemove, this);
49226 onRefresh : function(){
49227 var ds = this.grid.dataSource, i, v = this.grid.view;
49228 var s = this.selections;
49229 s.each(function(r){
49230 if((i = ds.indexOfId(r.id)) != -1){
49239 onRemove : function(v, C, r){
49240 this.selections.remove(r);
49244 onRowUpdated : function(v, D, r){
49245 if(this.isSelected(r)){
49252 * @param {Array} records The records to select
49253 * @param {Boolean} keepExisting (optional) True to keep existing selections
49255 selectRecords : function(E, F){
49257 this.clearSelections();
49259 var ds = this.grid.dataSource;
49260 for(var i = 0, len = E.length; i < len; i++){
49261 this.selectRow(ds.indexOf(E[i]), true);
49266 * Gets the number of selected rows.
49269 getCount : function(){
49270 return this.selections.length;
49274 * Selects the first row in the grid.
49276 selectFirstRow : function(){
49281 * Select the last row.
49282 * @param {Boolean} keepExisting (optional) True to keep existing selections
49284 selectLastRow : function(G){
49285 this.selectRow(this.grid.dataSource.getCount() - 1, G);
49289 * Selects the row immediately following the last selected row.
49290 * @param {Boolean} keepExisting (optional) True to keep existing selections
49292 selectNext : function(H){
49293 if(this.last !== false && (this.last+1) < this.grid.dataSource.getCount()){
49294 this.selectRow(this.last+1, H);
49295 this.grid.getView().focusRow(this.last);
49300 * Selects the row that precedes the last selected row.
49301 * @param {Boolean} keepExisting (optional) True to keep existing selections
49303 selectPrevious : function(I){
49305 this.selectRow(this.last-1, I);
49306 this.grid.getView().focusRow(this.last);
49311 * Returns the selected records
49312 * @return {Array} Array of selected records
49314 getSelections : function(){
49315 return [].concat(this.selections.items);
49319 * Returns the first selected record.
49322 getSelected : function(){
49323 return this.selections.itemAt(0);
49328 * Clears all selections.
49330 clearSelections : function(J){
49331 if(this.locked) return;
49333 var ds = this.grid.dataSource;
49334 var s = this.selections;
49335 s.each(function(r){
49336 this.deselectRow(ds.indexOfId(r.id));
49340 this.selections.clear();
49348 * Selects all rows.
49350 selectAll : function(){
49351 if(this.locked) return;
49352 this.selections.clear();
49353 for(var i = 0, len = this.grid.dataSource.getCount(); i < len; i++){
49354 this.selectRow(i, true);
49359 * Returns True if there is a selection.
49360 * @return {Boolean}
49362 hasSelection : function(){
49363 return this.selections.length > 0;
49367 * Returns True if the specified row is selected.
49368 * @param {Number/Record} record The record or index of the record to check
49369 * @return {Boolean}
49371 isSelected : function(K){
49372 var r = typeof K == "number" ? this.grid.dataSource.getAt(K) : K;
49373 return (r && this.selections.key(r.id) ? true : false);
49377 * Returns True if the specified record id is selected.
49378 * @param {String} id The id of record to check
49379 * @return {Boolean}
49381 isIdSelected : function(id){
49382 return (this.selections.key(id) ? true : false);
49386 handleMouseDown : function(e, t){
49387 var L = this.grid.getView(), M;
49388 if(this.isLocked() || (M = L.findRowIndex(t)) === false){
49391 if(e.shiftKey && this.last !== false){
49392 var last = this.last;
49393 this.selectRange(last, M, e.ctrlKey);
49394 this.last = last; // reset the last
49397 var isSelected = this.isSelected(M);
49398 if(e.button !== 0 && isSelected){
49400 }else if(e.ctrlKey && isSelected){
49401 this.deselectRow(M);
49402 }else if(!isSelected){
49403 this.selectRow(M, e.button === 0 && (e.ctrlKey || e.shiftKey));
49408 this.fireEvent("afterselectionchange", this);
49411 handleDragableRowClick : function(N, O, e)
49413 if(e.button === 0 && !e.shiftKey && !e.ctrlKey) {
49414 this.selectRow(O, false);
49415 N.view.focusRow(O);
49416 this.fireEvent("afterselectionchange", this);
49421 * Selects multiple rows.
49422 * @param {Array} rows Array of the indexes of the row to select
49423 * @param {Boolean} keepExisting (optional) True to keep existing selections
49425 selectRows : function(P, Q){
49427 this.clearSelections();
49429 for(var i = 0, len = P.length; i < len; i++){
49430 this.selectRow(P[i], true);
49435 * Selects a range of rows. All rows in between startRow and endRow are also selected.
49436 * @param {Number} startRow The index of the first row in the range
49437 * @param {Number} endRow The index of the last row in the range
49438 * @param {Boolean} keepExisting (optional) True to retain existing selections
49440 selectRange : function(R, S, T){
49441 if(this.locked) return;
49443 this.clearSelections();
49446 for(var i = R; i <= S; i++){
49447 this.selectRow(i, true);
49450 for(var i = R; i >= S; i--){
49451 this.selectRow(i, true);
49457 * Deselects a range of rows. All rows in between startRow and endRow are also deselected.
49458 * @param {Number} startRow The index of the first row in the range
49459 * @param {Number} endRow The index of the last row in the range
49461 deselectRange : function(U, V, W){
49462 if(this.locked) return;
49463 for(var i = U; i <= V; i++){
49464 this.deselectRow(i, W);
49470 * @param {Number} row The index of the row to select
49471 * @param {Boolean} keepExisting (optional) True to keep existing selections
49473 selectRow : function(X, Y, Z){
49474 if(this.locked || (X < 0 || X >= this.grid.dataSource.getCount())) return;
49475 if(this.fireEvent("beforerowselect", this, X, Y) !== false){
49476 if(!Y || this.singleSelect){
49477 this.clearSelections();
49479 var r = this.grid.dataSource.getAt(X);
49480 this.selections.add(r);
49481 this.last = this.lastActive = X;
49483 this.grid.getView().onRowSelect(X);
49486 this.fireEvent("rowselect", this, X, r);
49487 this.fireEvent("selectionchange", this);
49493 * @param {Number} row The index of the row to deselect
49495 deselectRow : function(a, b){
49496 if(this.locked) return;
49497 if(this.last == a){
49500 if(this.lastActive == a){
49501 this.lastActive = false;
49503 var r = this.grid.dataSource.getAt(a);
49504 this.selections.remove(r);
49506 this.grid.getView().onRowDeselect(a);
49509 this.fireEvent("rowdeselect", this, a);
49510 this.fireEvent("selectionchange", this);
49514 restoreLast : function(){
49516 this.last = this._last;
49521 acceptsNav : function(c, d, cm){
49522 return !cm.isHidden(d) && cm.isCellEditable(d, c);
49526 onEditorKey : function(f, e){
49527 var k = e.getKey(), h, g = this.grid, ed = g.activeEditor;
49532 h = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
49534 h = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
49536 }else if(k == e.ENTER && !e.ctrlKey){
49540 h = g.walkCells(ed.row-1, ed.col, -1, this.acceptsNav, this);
49542 h = g.walkCells(ed.row+1, ed.col, 1, this.acceptsNav, this);
49544 }else if(k == e.ESC){
49548 g.startEditing(h[0], h[1]);
49554 * Ext JS Library 1.1.1
49555 * Copyright(c) 2006-2007, Ext JS, LLC.
49557 * Originally Released Under LGPL - original licence link has changed is not relivant.
49560 * <script type="text/javascript">
49563 * @class Roo.grid.CellSelectionModel
49564 * @extends Roo.grid.AbstractSelectionModel
49565 * This class provides the basic implementation for cell selection in a grid.
49567 * @param {Object} config The object containing the configuration of this model.
49569 Roo.grid.CellSelectionModel = function(A){
49570 Roo.apply(this, A);
49572 this.selection = null;
49576 * @event beforerowselect
49577 * Fires before a cell is selected.
49578 * @param {SelectionModel} this
49579 * @param {Number} rowIndex The selected row index
49580 * @param {Number} colIndex The selected cell index
49582 "beforecellselect" : true,
49584 * @event cellselect
49585 * Fires when a cell is selected.
49586 * @param {SelectionModel} this
49587 * @param {Number} rowIndex The selected row index
49588 * @param {Number} colIndex The selected cell index
49590 "cellselect" : true,
49592 * @event selectionchange
49593 * Fires when the active selection changes.
49594 * @param {SelectionModel} this
49595 * @param {Object} selection null for no selection or an object (o) with two properties
49597 <li>o.record: the record object for the row the selection is in</li>
49598 <li>o.cell: An array of [rowIndex, columnIndex]</li>
49601 "selectionchange" : true
49603 Roo.grid.CellSelectionModel.superclass.constructor.call(this);
49606 Roo.extend(Roo.grid.CellSelectionModel, Roo.grid.AbstractSelectionModel, {
49609 initEvents : function(){
49610 this.grid.on("mousedown", this.handleMouseDown, this);
49611 this.grid.getGridEl().on(Roo.isIE ? "keydown" : "keypress", this.handleKeyDown, this);
49612 var B = this.grid.view;
49613 B.on("refresh", this.onViewChange, this);
49614 B.on("rowupdated", this.onRowUpdated, this);
49615 B.on("beforerowremoved", this.clearSelections, this);
49616 B.on("beforerowsinserted", this.clearSelections, this);
49617 if(this.grid.isEditor){
49618 this.grid.on("beforeedit", this.beforeEdit, this);
49623 beforeEdit : function(e){
49624 this.select(e.row, e.column, false, true, e.record);
49628 onRowUpdated : function(v, C, r){
49629 if(this.selection && this.selection.record == r){
49630 v.onCellSelect(C, this.selection.cell[1]);
49635 onViewChange : function(){
49636 this.clearSelections(true);
49640 * Returns the currently selected cell,.
49641 * @return {Array} The selected cell (row, column) or null if none selected.
49643 getSelectedCell : function(){
49644 return this.selection ? this.selection.cell : null;
49648 * Clears all selections.
49649 * @param {Boolean} true to prevent the gridview from being notified about the change.
49651 clearSelections : function(D){
49652 var s = this.selection;
49655 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
49658 this.selection = null;
49659 this.fireEvent("selectionchange", this, null);
49664 * Returns true if there is a selection.
49665 * @return {Boolean}
49667 hasSelection : function(){
49668 return this.selection ? true : false;
49672 handleMouseDown : function(e, t){
49673 var v = this.grid.getView();
49674 if(this.isLocked()){
49677 var E = v.findRowIndex(t);
49678 var F = v.findCellIndex(t);
49679 if(E !== false && F !== false){
49686 * @param {Number} rowIndex
49687 * @param {Number} collIndex
49689 select : function(G, H, I, J, /*internal*/ r){
49690 if(this.fireEvent("beforecellselect", this, G, H) !== false){
49691 this.clearSelections();
49692 r = r || this.grid.dataSource.getAt(G);
49698 var v = this.grid.getView();
49699 v.onCellSelect(G, H);
49705 this.fireEvent("cellselect", this, G, H);
49706 this.fireEvent("selectionchange", this, this.selection);
49711 isSelectable : function(K, L, cm){
49712 return !cm.isHidden(L);
49716 handleKeyDown : function(e){
49717 if(!e.isNavKeyPress()){
49720 var g = this.grid, s = this.selection;
49723 var F = g.walkCells(0, 0, 1, this.isSelectable, this);
49725 this.select(F[0], F[1]);
49730 var M = function(O, P, Q){
49731 return g.walkCells(O, P, Q, sm.isSelectable, sm);
49733 var k = e.getKey(), r = s.cell[0], c = s.cell[1];
49757 if(g.isEditor && !g.editing){
49758 g.startEditing(r, c);
49765 this.select(N[0], N[1]);
49770 acceptsNav : function(O, P, cm){
49771 return !cm.isHidden(P) && cm.isCellEditable(P, O);
49774 onEditorKey : function(Q, e){
49775 var k = e.getKey(), R, g = this.grid, ed = g.activeEditor;
49778 R = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
49780 R = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
49784 }else if(k == e.ENTER && !e.ctrlKey){
49787 }else if(k == e.ESC){
49791 g.startEditing(R[0], R[1]);
49797 * Ext JS Library 1.1.1
49798 * Copyright(c) 2006-2007, Ext JS, LLC.
49800 * Originally Released Under LGPL - original licence link has changed is not relivant.
49803 * <script type="text/javascript">
49807 * @class Roo.grid.EditorGrid
49808 * @extends Roo.grid.Grid
49809 * Class for creating and editable grid.
49810 * @param {String/HTMLElement/Roo.Element} container The element into which this grid will be rendered -
49811 * The container MUST have some type of size defined for the grid to fill. The container will be
49812 * automatically set to position relative if it isn't already.
49813 * @param {Object} dataSource The data model to bind to
49814 * @param {Object} colModel The column model with info about this grid's columns
49816 Roo.grid.EditorGrid = function(A, B){
49817 Roo.grid.EditorGrid.superclass.constructor.call(this, A, B);
49818 this.getGridEl().addClass("xedit-grid");
49820 if(!this.selModel){
49821 this.selModel = new Roo.grid.CellSelectionModel();
49825 this.activeEditor = null;
49829 * @event beforeedit
49830 * Fires before cell editing is triggered. The edit event object has the following properties <br />
49831 * <ul style="padding:5px;padding-left:16px;">
49832 * <li>grid - This grid</li>
49833 * <li>record - The record being edited</li>
49834 * <li>field - The field name being edited</li>
49835 * <li>value - The value for the field being edited.</li>
49836 * <li>row - The grid row index</li>
49837 * <li>column - The grid column index</li>
49838 * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li>
49840 * @param {Object} e An edit event (see above for description)
49842 "beforeedit" : true,
49845 * Fires after a cell is edited. <br />
49846 * <ul style="padding:5px;padding-left:16px;">
49847 * <li>grid - This grid</li>
49848 * <li>record - The record being edited</li>
49849 * <li>field - The field name being edited</li>
49850 * <li>value - The value being set</li>
49851 * <li>originalValue - The original value for the field, before the edit.</li>
49852 * <li>row - The grid row index</li>
49853 * <li>column - The grid column index</li>
49855 * @param {Object} e An edit event (see above for description)
49857 "afteredit" : true,
49859 * @event validateedit
49860 * Fires after a cell is edited, but before the value is set in the record.
49861 * You can use this to modify the value being set in the field, Return false
49862 * to cancel the change. The edit event object has the following properties <br />
49863 * <ul style="padding:5px;padding-left:16px;">
49864 * <li>editor - This editor</li>
49865 * <li>grid - This grid</li>
49866 * <li>record - The record being edited</li>
49867 * <li>field - The field name being edited</li>
49868 * <li>value - The value being set</li>
49869 * <li>originalValue - The original value for the field, before the edit.</li>
49870 * <li>row - The grid row index</li>
49871 * <li>column - The grid column index</li>
49872 * <li>cancel - Set this to true to cancel the edit or return false from your handler.</li>
49874 * @param {Object} e An edit event (see above for description)
49876 "validateedit" : true
49878 this.on("bodyscroll", this.stopEditing, this);
49879 this.on(this.clicksToEdit == 1 ? "cellclick" : "celldblclick", this.onCellDblClick, this);
49882 Roo.extend(Roo.grid.EditorGrid, Roo.grid.Grid, {
49884 * @cfg {Number} clicksToEdit
49885 * The number of clicks on a cell required to display the cell's editor (defaults to 2)
49892 trackMouseOver: false, // causes very odd FF errors
49894 onCellDblClick : function(g, C, D){
49895 this.startEditing(C, D);
49898 onEditComplete : function(ed, E, F){
49899 this.editing = false;
49900 this.activeEditor = null;
49901 ed.un("specialkey", this.selModel.onEditorKey, this.selModel);
49903 var G = this.colModel.getDataIndex(ed.col);
49915 if(String(E) !== String(F)){
49917 if(this.fireEvent("validateedit", e) !== false && !e.cancel){
49919 delete e.cancel; //?? why!!!
49920 this.fireEvent("afteredit", e);
49923 this.fireEvent("afteredit", e); // always fir it!
49926 this.view.focusCell(ed.row, ed.col);
49930 * Starts editing the specified for the specified row/column
49931 * @param {Number} rowIndex
49932 * @param {Number} colIndex
49934 startEditing : function(H, I){
49935 this.stopEditing();
49936 if(this.colModel.isCellEditable(I, H)){
49937 this.view.ensureVisible(H, I, true);
49938 var r = this.dataSource.getAt(H);
49939 var G = this.colModel.getDataIndex(I);
49949 if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
49950 this.editing = true;
49951 var ed = this.colModel.getCellEditor(I, H);
49956 ed.render(ed.parentEl || document.body);
49958 (function(){ // complex but required for focus issues in safari, ie and opera
49962 ed.on("complete", this.onEditComplete, this, {single: true});
49963 ed.on("specialkey", this.selModel.onEditorKey, this.selModel);
49964 this.activeEditor = ed;
49966 ed.startEdit(this.view.getCell(H, I), v);
49967 }).defer(50, this);
49973 * Stops any active editing
49975 stopEditing : function(){
49976 if(this.activeEditor){
49977 this.activeEditor.completeEdit();
49980 this.activeEditor = null;
49985 * Ext JS Library 1.1.1
49986 * Copyright(c) 2006-2007, Ext JS, LLC.
49988 * Originally Released Under LGPL - original licence link has changed is not relivant.
49991 * <script type="text/javascript">
49994 // private - not really -- you end up using it !
49995 // This is a support class used internally by the Grid components
49998 * @class Roo.grid.GridEditor
49999 * @extends Roo.Editor
50000 * Class for creating and editable grid elements.
50001 * @param {Object} config any settings (must include field)
50003 Roo.grid.GridEditor = function(A, B){
50004 if (!B && A.field) {
50006 A = Roo.factory(B.field, Roo.form);
50009 Roo.grid.GridEditor.superclass.constructor.call(this, A, B);
50010 A.monitorTab = false;
50013 Roo.extend(Roo.grid.GridEditor, Roo.Editor, {
50016 * @cfg {Roo.form.Field} field Field to wrap (or xtyped)
50019 alignment: "tl-tl",
50022 cls: "x-small-editor x-grid-editor",
50028 * Ext JS Library 1.1.1
50029 * Copyright(c) 2006-2007, Ext JS, LLC.
50031 * Originally Released Under LGPL - original licence link has changed is not relivant.
50034 * <script type="text/javascript">
50039 Roo.grid.PropertyRecord = Roo.data.Record.create([
50040 {name:'name',type:'string'}, 'value'
50044 Roo.grid.PropertyStore = function(A, B){
50046 this.store = new Roo.data.Store({
50047 recordType : Roo.grid.PropertyRecord
50049 this.store.on('update', this.onUpdate, this);
50054 Roo.grid.PropertyStore.superclass.constructor.call(this);
50059 Roo.extend(Roo.grid.PropertyStore, Roo.util.Observable, {
50060 setSource : function(o){
50062 this.store.removeAll();
50065 if(this.isEditableValue(o[k])){
50066 C.push(new Roo.grid.PropertyRecord({name: k, value: o[k]}, k));
50070 this.store.loadRecords({records: C}, {}, true);
50073 onUpdate : function(ds, D, E){
50074 if(E == Roo.data.Record.EDIT){
50075 var v = D.data['value'];
50076 var oldValue = D.modified['value'];
50077 if(this.grid.fireEvent('beforepropertychange', this.source, D.id, v, oldValue) !== false){
50078 this.source[D.id] = v;
50080 this.grid.fireEvent('propertychange', this.source, D.id, v, oldValue);
50087 getProperty : function(F){
50088 return this.store.getAt(F);
50091 isEditableValue: function(G){
50092 if(G && G instanceof Date){
50094 }else if(typeof G == 'object' || typeof G == 'function'){
50100 setValue : function(H, I){
50101 this.source[H] = I;
50102 this.store.getById(H).set('value', I);
50105 getSource : function(){
50106 return this.source;
50110 Roo.grid.PropertyColumnModel = function(J, K){
50113 g.PropertyColumnModel.superclass.constructor.call(this, [
50114 {header: this.nameText, sortable: true, dataIndex:'name', id: 'name'},
50115 {header: this.valueText, resizable:false, dataIndex: 'value', id: 'value'}
50118 this.bselect = Roo.DomHelper.append(document.body, {
50119 tag: 'select', style:'display:none', cls: 'x-grid-editor', children: [
50120 {tag: 'option', value: 'true', html: 'true'},
50121 {tag: 'option', value: 'false', html: 'false'}
50124 Roo.id(this.bselect);
50127 'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
50128 'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
50129 'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
50130 'int' : new g.GridEditor(new f.NumberField({selectOnFocus:true, allowDecimals:false, style:'text-align:left;'})),
50131 'boolean' : new g.GridEditor(new f.Field({el:this.bselect,selectOnFocus:true}))
50133 this.renderCellDelegate = this.renderCell.createDelegate(this);
50134 this.renderPropDelegate = this.renderProp.createDelegate(this);
50137 Roo.extend(Roo.grid.PropertyColumnModel, Roo.grid.ColumnModel, {
50141 valueText : 'Value',
50143 dateFormat : 'm/j/Y',
50146 renderDate : function(L){
50147 return L.dateFormat(this.dateFormat);
50150 renderBool : function(M){
50151 return M ? 'true' : 'false';
50154 isCellEditable : function(N, O){
50158 getRenderer : function(P){
50160 this.renderCellDelegate : this.renderPropDelegate;
50163 renderProp : function(v){
50164 return this.getPropertyName(v);
50167 renderCell : function(Q){
50169 if(Q instanceof Date){
50170 rv = this.renderDate(Q);
50171 }else if(typeof Q == 'boolean'){
50172 rv = this.renderBool(Q);
50174 return Roo.util.Format.htmlEncode(rv);
50177 getPropertyName : function(R){
50178 var pn = this.grid.propertyNames;
50179 return pn && pn[R] ? pn[R] : R;
50182 getCellEditor : function(S, T){
50183 var p = this.store.getProperty(T);
50184 var n = p.data['name'], U = p.data['value'];
50186 if(typeof(this.grid.customEditors[n]) == 'string'){
50187 return this.editors[this.grid.customEditors[n]];
50189 if(typeof(this.grid.customEditors[n]) != 'undefined'){
50190 return this.grid.customEditors[n];
50192 if(U instanceof Date){
50193 return this.editors['date'];
50194 }else if(typeof U == 'number'){
50195 return this.editors['number'];
50196 }else if(typeof U == 'boolean'){
50197 return this.editors['boolean'];
50199 return this.editors['string'];
50205 * @class Roo.grid.PropertyGrid
50206 * @extends Roo.grid.EditorGrid
50207 * This class represents the interface of a component based property grid control.
50208 * <br><br>Usage:<pre><code>
50209 var grid = new Roo.grid.PropertyGrid("my-container-id", {
50217 * @param {String/HTMLElement/Roo.Element} container The element into which this grid will be rendered -
50218 * The container MUST have some type of size defined for the grid to fill. The container will be
50219 * automatically set to position relative if it isn't already.
50220 * @param {Object} config A config object that sets properties on this grid.
50222 Roo.grid.PropertyGrid = function(V, W){
50224 var X = new Roo.grid.PropertyStore(this);
50226 var cm = new Roo.grid.PropertyColumnModel(this, X);
50227 X.store.sort('name', 'ASC');
50228 Roo.grid.PropertyGrid.superclass.constructor.call(this, V, Roo.apply({
50231 enableColLock:false,
50232 enableColumnMove:false,
50234 trackMouseOver: false,
50237 this.getGridEl().addClass('x-props-grid');
50238 this.lastEditRow = null;
50239 this.on('columnresize', this.onColumnResize, this);
50242 * @event beforepropertychange
50243 * Fires before a property changes (return false to stop?)
50244 * @param {Roo.grid.PropertyGrid} grid property grid? (check could be store)
50245 * @param {String} id Record Id
50246 * @param {String} newval New Value
50247 * @param {String} oldval Old Value
50249 "beforepropertychange": true,
50251 * @event propertychange
50252 * Fires after a property changes
50253 * @param {Roo.grid.PropertyGrid} grid property grid? (check could be store)
50254 * @param {String} id Record Id
50255 * @param {String} newval New Value
50256 * @param {String} oldval Old Value
50258 "propertychange": true
50260 this.customEditors = this.customEditors || {};
50262 Roo.extend(Roo.grid.PropertyGrid, Roo.grid.EditorGrid, {
50265 * @cfg {Object} customEditors map of colnames=> custom editors.
50266 * the custom editor can be one of the standard ones (date|string|number|int|boolean), or a
50267 * grid editor eg. Roo.grid.GridEditor(new Roo.form.TextArea({selectOnFocus:true})),
50268 * false disables editing of the field.
50272 * @cfg {Object} propertyNames map of property Names to their displayed value
50275 render : function(){
50276 Roo.grid.PropertyGrid.superclass.render.call(this);
50277 this.autoSize.defer(100, this);
50280 autoSize : function(){
50281 Roo.grid.PropertyGrid.superclass.autoSize.call(this);
50283 this.view.fitColumns();
50287 onColumnResize : function(){
50288 this.colModel.setColumnWidth(1, this.container.getWidth(true)-this.colModel.getColumnWidth(0));
50292 * Sets the data for the Grid
50293 * accepts a Key => Value object of all the elements avaiable.
50294 * @param {Object} data to appear in grid.
50296 setSource : function(Y){
50297 this.store.setSource(Y);
50301 * Gets all the data from the grid.
50302 * @return {Object} data data stored in grid
50304 getSource : function(){
50305 return this.store.getSource();
50310 * Ext JS Library 1.1.1
50311 * Copyright(c) 2006-2007, Ext JS, LLC.
50313 * Originally Released Under LGPL - original licence link has changed is not relivant.
50316 * <script type="text/javascript">
50320 * @class Roo.LoadMask
50321 * A simple utility class for generically masking elements while loading data. If the element being masked has
50322 * an underlying {@link Roo.data.Store}, the masking will be automatically synchronized with the store's loading
50323 * process and the mask element will be cached for reuse. For all other elements, this mask will replace the
50324 * element's UpdateManager load indicator and will be destroyed after the initial load.
50326 * Create a new LoadMask
50327 * @param {String/HTMLElement/Roo.Element} el The element or DOM node, or its id
50328 * @param {Object} config The config object
50330 Roo.LoadMask = function(el, A){
50331 this.el = Roo.get(el);
50332 Roo.apply(this, A);
50334 this.store.on('beforeload', this.onBeforeLoad, this);
50335 this.store.on('load', this.onLoad, this);
50336 this.store.on('loadexception', this.onLoad, this);
50337 this.removeMask = false;
50339 var um = this.el.getUpdateManager();
50340 um.showLoadIndicator = false; // disable the default indicator
50341 um.on('beforeupdate', this.onBeforeLoad, this);
50342 um.on('update', this.onLoad, this);
50343 um.on('failure', this.onLoad, this);
50344 this.removeMask = true;
50348 Roo.LoadMask.prototype = {
50350 * @cfg {Boolean} removeMask
50351 * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
50352 * False to persist the mask element reference for multiple uses (e.g., for paged data widgets). Defaults to false.
50355 * @cfg {String} msg
50356 * The text to display in a centered loading message box (defaults to 'Loading...')
50358 msg : 'Loading...',
50360 * @cfg {String} msgCls
50361 * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
50363 msgCls : 'x-mask-loading',
50366 * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
50372 * Disables the mask to prevent it from being displayed
50374 disable : function(){
50375 this.disabled = true;
50379 * Enables the mask so that it can be displayed
50381 enable : function(){
50382 this.disabled = false;
50386 onLoad : function(){
50387 this.el.unmask(this.removeMask);
50391 onBeforeLoad : function(){
50392 if(!this.disabled){
50393 this.el.mask(this.msg, this.msgCls);
50398 destroy : function(){
50400 this.store.un('beforeload', this.onBeforeLoad, this);
50401 this.store.un('load', this.onLoad, this);
50402 this.store.un('loadexception', this.onLoad, this);
50404 var um = this.el.getUpdateManager();
50405 um.un('beforeupdate', this.onBeforeLoad, this);
50406 um.un('update', this.onLoad, this);
50407 um.un('failure', this.onLoad, this);
50413 * Ext JS Library 1.1.1
50414 * Copyright(c) 2006-2007, Ext JS, LLC.
50416 * Originally Released Under LGPL - original licence link has changed is not relivant.
50419 * <script type="text/javascript">
50421 Roo.XTemplate = function(){
50422 Roo.XTemplate.superclass.constructor.apply(this, arguments);
50425 s = ['<tpl>', s, '</tpl>'].join('');
50427 var re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/;
50429 var A = /^<tpl\b[^>]*?for="(.*?)"/;
50430 var B = /^<tpl\b[^>]*?if="(.*?)"/;
50431 var C = /^<tpl\b[^>]*?exec="(.*?)"/;
50435 while(m = s.match(re)){
50436 var m2 = m[0].match(A);
50437 var m3 = m[0].match(B);
50438 var m4 = m[0].match(C);
50439 var exp = null, fn = null, exec = null;
50440 var name = m2 && m2[1] ? m2[1] : '';
50442 exp = m3 && m3[1] ? m3[1] : null;
50444 fn = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(exp))+'; }');
50448 exp = m4 && m4[1] ? m4[1] : null;
50450 exec = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(exp))+'; }');
50455 case '.': name = new Function('values', 'parent', 'with(values){ return values; }'); break;
50456 case '..': name = new Function('values', 'parent', 'with(values){ return parent; }'); break;
50457 default: name = new Function('values', 'parent', 'with(values){ return '+name+'; }');
50468 s = s.replace(m[0], '{xtpl'+ id + '}');
50471 for(var i = D.length-1; i >= 0; --i){
50472 this.compileTpl(D[i]);
50475 this.master = D[D.length-1];
50478 Roo.extend(Roo.XTemplate, Roo.Template, {
50480 re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
50482 applySubTemplate : function(id, E, F){
50483 var t = this.tpls[id];
50484 if(t.test && !t.test.call(this, E, F)){
50487 if(t.exec && t.exec.call(this, E, F)){
50490 var vs = t.target ? t.target.call(this, E, F) : E;
50491 F = t.target ? E : F;
50492 if(t.target && vs instanceof Array){
50494 for(var i = 0, len = vs.length; i < len; i++){
50495 buf[buf.length] = t.compiled.call(this, vs[i], F);
50497 return buf.join('');
50499 return t.compiled.call(this, vs, F);
50502 compileTpl : function(G){
50503 var fm = Roo.util.Format;
50504 var H = this.disableFormats !== true;
50505 var I = Roo.isGecko ? "+" : ",";
50506 var fn = function(m, K, L, M){
50507 if(K.substr(0, 4) == 'xtpl'){
50508 return "'"+ I +'this.applySubTemplate('+K.substr(4)+', values, parent)'+I+"'";
50511 if(K.indexOf('.') != -1){
50514 v = "values['" + K + "']";
50517 M = M ? ',' + M : "";
50518 if(L.substr(0, 5) != "this."){
50519 L = "fm." + L + '(';
50521 L = 'this.call("'+ L.substr(5) + '", ';
50525 M= ''; L = "("+v+" === undefined ? '' : ";
50527 return "'"+ I + L + v + M + ")"+I+"'";
50530 // branched to use + in gecko and [].join() in others
50532 J = "tpl.compiled = function(values, parent){ return '" +
50533 G.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
50536 J = ["tpl.compiled = function(values, parent){ return ['"];
50537 J.push(G.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
50538 J.push("'].join('');};");
50542 /** eval:var:zzzzzzz */
50547 applyTemplate : function(K){
50548 return this.master.compiled.call(this, K, {});
50552 apply : function(){
50553 return this.applyTemplate.apply(this, arguments);
50556 compile : function(){return this;}
50559 Roo.XTemplate.from = function(el){
50560 el = Roo.getDom(el);
50561 return new Roo.XTemplate(el.value || el.innerHTML);