4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isFirefox = ua.indexOf("firefox") > -1,
57 isIE = ua.indexOf("msie") > -1,
58 isIE7 = ua.indexOf("msie 7") > -1,
59 isIE11 = /trident.*rv\:11\./.test(ua),
60 isGecko = !isSafari && ua.indexOf("gecko") > -1,
61 isBorderBox = isIE && !isStrict,
62 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
63 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
64 isLinux = (ua.indexOf("linux") != -1),
65 isSecure = window.location.href.toLowerCase().indexOf("https") === 0,
66 isIOS = /iphone|ipad/.test(ua),
67 isTouch = (function() {
69 if (ua.indexOf('chrome') != -1 && ua.indexOf('android') == -1) {
70 window.addEventListener('touchstart', function __set_has_touch__ () {
72 window.removeEventListener('touchstart', __set_has_touch__);
74 return false; // no touch on chrome!?
76 document.createEvent("TouchEvent");
83 // remove css image flicker
86 document.execCommand("BackgroundImageCache", false, true);
92 * True if the browser is in strict mode
97 * True if the page is running over SSL
102 * True when the document is fully initialized and ready for action
107 * Turn on debugging output (currently only the factory uses this)
114 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
117 enableGarbageCollector : true,
120 * True to automatically purge event listeners after uncaching an element (defaults to false).
121 * Note: this only happens if enableGarbageCollector is true.
124 enableListenerCollection:false,
127 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
128 * the IE insecure content warning (defaults to javascript:false).
131 SSL_SECURE_URL : "javascript:false",
134 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
135 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
138 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
140 emptyFn : function(){},
143 * Copies all the properties of config to obj if they don't already exist.
144 * @param {Object} obj The receiver of the properties
145 * @param {Object} config The source of the properties
146 * @return {Object} returns obj
148 applyIf : function(o, c){
151 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
158 * Applies event listeners to elements by selectors when the document is ready.
159 * The event name is specified with an @ suffix.
162 // add a listener for click on all anchors in element with id foo
163 '#foo a@click' : function(e, t){
167 // add the same listener to multiple selectors (separated by comma BEFORE the @)
168 '#foo a, #bar span.some-class@mouseover' : function(){
173 * @param {Object} obj The list of behaviors to apply
175 addBehaviors : function(o){
177 Roo.onReady(function(){
182 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
184 var parts = b.split('@');
185 if(parts[1]){ // for Object prototype breakers
188 cache[s] = Roo.select(s);
190 cache[s].on(parts[1], o[b]);
197 * Generates unique ids. If the element already has an id, it is unchanged
198 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
199 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
200 * @return {String} The generated Id.
202 id : function(el, prefix){
203 prefix = prefix || "roo-gen";
205 var id = prefix + (++idSeed);
206 return el ? (el.id ? el.id : (el.id = id)) : id;
211 * Extends one class with another class and optionally overrides members with the passed literal. This class
212 * also adds the function "override()" to the class that can be used to override
213 * members on an instance.
214 * @param {Object} subclass The class inheriting the functionality
215 * @param {Object} superclass The class being extended
216 * @param {Object} overrides (optional) A literal with members
221 var io = function(o){
226 return function(sb, sp, overrides){
227 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
230 sb = function(){sp.apply(this, arguments);};
232 var F = function(){}, sbp, spp = sp.prototype;
234 sbp = sb.prototype = new F();
238 if(spp.constructor == Object.prototype.constructor){
243 sb.override = function(o){
247 Roo.override(sb, overrides);
253 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
255 Roo.override(MyClass, {
256 newMethod1: function(){
259 newMethod2: function(foo){
264 * @param {Object} origclass The class to override
265 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
266 * containing one or more methods.
269 override : function(origclass, overrides){
271 var p = origclass.prototype;
272 for(var method in overrides){
273 p[method] = overrides[method];
278 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
280 Roo.namespace('Company', 'Company.data');
281 Company.Widget = function() { ... }
282 Company.data.CustomStore = function(config) { ... }
284 * @param {String} namespace1
285 * @param {String} namespace2
286 * @param {String} etc
289 namespace : function(){
290 var a=arguments, o=null, i, j, d, rt;
291 for (i=0; i<a.length; ++i) {
295 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
296 for (j=1; j<d.length; ++j) {
297 o[d[j]]=o[d[j]] || {};
303 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
305 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
306 Roo.factory(conf, Roo.data);
308 * @param {String} classname
309 * @param {String} namespace (optional)
313 factory : function(c, ns)
315 // no xtype, no ns or c.xns - or forced off by c.xns
316 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
319 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
320 if (c.constructor == ns[c.xtype]) {// already created...
324 if (Roo.debug) { Roo.log("Roo.Factory(" + c.xtype + ")"); }
325 var ret = new ns[c.xtype](c);
329 c.xns = false; // prevent recursion..
333 * Logs to console if it can.
335 * @param {String|Object} string
340 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
347 * 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.
351 urlEncode : function(o){
357 var ov = o[key], k = Roo.encodeURIComponent(key);
358 var type = typeof ov;
359 if(type == 'undefined'){
361 }else if(type != "function" && type != "object"){
362 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
363 }else if(ov instanceof Array){
365 for(var i = 0, len = ov.length; i < len; i++) {
366 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
377 * Safe version of encodeURIComponent
378 * @param {String} data
382 encodeURIComponent : function (data)
385 return encodeURIComponent(data);
386 } catch(e) {} // should be an uri encode error.
388 if (data == '' || data == null){
391 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
392 function nibble_to_hex(nibble){
393 var chars = '0123456789ABCDEF';
394 return chars.charAt(nibble);
396 data = data.toString();
398 for(var i=0; i<data.length; i++){
399 var c = data.charCodeAt(i);
400 var bs = new Array();
403 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
404 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
405 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
406 bs[3] = 0x80 | (c & 0x3F);
407 }else if (c > 0x800){
409 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
410 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
411 bs[2] = 0x80 | (c & 0x3F);
414 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
415 bs[1] = 0x80 | (c & 0x3F);
420 for(var j=0; j<bs.length; j++){
422 var hex = nibble_to_hex((b & 0xF0) >>> 4)
423 + nibble_to_hex(b &0x0F);
432 * 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]}.
433 * @param {String} string
434 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
435 * @return {Object} A literal with members
437 urlDecode : function(string, overwrite){
438 if(!string || !string.length){
442 var pairs = string.split('&');
443 var pair, name, value;
444 for(var i = 0, len = pairs.length; i < len; i++){
445 pair = pairs[i].split('=');
446 name = decodeURIComponent(pair[0]);
447 value = decodeURIComponent(pair[1]);
448 if(overwrite !== true){
449 if(typeof obj[name] == "undefined"){
451 }else if(typeof obj[name] == "string"){
452 obj[name] = [obj[name]];
453 obj[name].push(value);
455 obj[name].push(value);
465 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
466 * passed array is not really an array, your function is called once with it.
467 * The supplied function is called with (Object item, Number index, Array allItems).
468 * @param {Array/NodeList/Mixed} array
469 * @param {Function} fn
470 * @param {Object} scope
472 each : function(array, fn, scope){
473 if(typeof array.length == "undefined" || typeof array == "string"){
476 for(var i = 0, len = array.length; i < len; i++){
477 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
482 combine : function(){
483 var as = arguments, l = as.length, r = [];
484 for(var i = 0; i < l; i++){
486 if(a instanceof Array){
488 }else if(a.length !== undefined && !a.substr){
489 r = r.concat(Array.prototype.slice.call(a, 0));
498 * Escapes the passed string for use in a regular expression
499 * @param {String} str
502 escapeRe : function(s) {
503 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
507 callback : function(cb, scope, args, delay){
508 if(typeof cb == "function"){
510 cb.defer(delay, scope, args || []);
512 cb.apply(scope, args || []);
518 * Return the dom node for the passed string (id), dom node, or Roo.Element
519 * @param {String/HTMLElement/Roo.Element} el
520 * @return HTMLElement
522 getDom : function(el){
526 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
530 * Shorthand for {@link Roo.ComponentMgr#get}
532 * @return Roo.Component
534 getCmp : function(id){
535 return Roo.ComponentMgr.get(id);
538 num : function(v, defaultValue){
539 if(typeof v != 'number'){
545 destroy : function(){
546 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
550 as.removeAllListeners();
554 if(typeof as.purgeListeners == 'function'){
557 if(typeof as.destroy == 'function'){
564 // inpired by a similar function in mootools library
566 * Returns the type of object that is passed in. If the object passed in is null or undefined it
567 * return false otherwise it returns one of the following values:<ul>
568 * <li><b>string</b>: If the object passed is a string</li>
569 * <li><b>number</b>: If the object passed is a number</li>
570 * <li><b>boolean</b>: If the object passed is a boolean value</li>
571 * <li><b>function</b>: If the object passed is a function reference</li>
572 * <li><b>object</b>: If the object passed is an object</li>
573 * <li><b>array</b>: If the object passed is an array</li>
574 * <li><b>regexp</b>: If the object passed is a regular expression</li>
575 * <li><b>element</b>: If the object passed is a DOM Element</li>
576 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
577 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
578 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
579 * @param {Mixed} object
583 if(o === undefined || o === null){
590 if(t == 'object' && o.nodeName) {
592 case 1: return 'element';
593 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
596 if(t == 'object' || t == 'function') {
597 switch(o.constructor) {
598 case Array: return 'array';
599 case RegExp: return 'regexp';
601 if(typeof o.length == 'number' && typeof o.item == 'function') {
609 * Returns true if the passed value is null, undefined or an empty string (optional).
610 * @param {Mixed} value The value to test
611 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
614 isEmpty : function(v, allowBlank){
615 return v === null || v === undefined || (!allowBlank ? v === '' : false);
623 isFirefox : isFirefox,
633 isBorderBox : isBorderBox,
635 isWindows : isWindows,
646 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
647 * you may want to set this to true.
650 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
655 * Selects a single element as a Roo Element
656 * This is about as close as you can get to jQuery's $('do crazy stuff')
657 * @param {String} selector The selector/xpath query
658 * @param {Node} root (optional) The start of the query (defaults to document).
659 * @return {Roo.Element}
661 selectNode : function(selector, root)
663 var node = Roo.DomQuery.selectNode(selector,root);
664 return node ? Roo.get(node) : new Roo.Element(false);
672 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
673 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout",
676 "Roo.bootstrap.dash");
679 * Ext JS Library 1.1.1
680 * Copyright(c) 2006-2007, Ext JS, LLC.
682 * Originally Released Under LGPL - original licence link has changed is not relivant.
685 * <script type="text/javascript">
689 // wrappedn so fnCleanup is not in global scope...
691 function fnCleanUp() {
692 var p = Function.prototype;
693 delete p.createSequence;
695 delete p.createDelegate;
696 delete p.createCallback;
697 delete p.createInterceptor;
699 window.detachEvent("onunload", fnCleanUp);
701 window.attachEvent("onunload", fnCleanUp);
708 * These functions are available on every Function object (any JavaScript function).
710 Roo.apply(Function.prototype, {
712 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
713 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
714 * Will create a function that is bound to those 2 args.
715 * @return {Function} The new function
717 createCallback : function(/*args...*/){
718 // make args available, in function below
719 var args = arguments;
722 return method.apply(window, args);
727 * Creates a delegate (callback) that sets the scope to obj.
728 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
729 * Will create a function that is automatically scoped to this.
730 * @param {Object} obj (optional) The object for which the scope is set
731 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
732 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
733 * if a number the args are inserted at the specified position
734 * @return {Function} The new function
736 createDelegate : function(obj, args, appendArgs){
739 var callArgs = args || arguments;
740 if(appendArgs === true){
741 callArgs = Array.prototype.slice.call(arguments, 0);
742 callArgs = callArgs.concat(args);
743 }else if(typeof appendArgs == "number"){
744 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
745 var applyArgs = [appendArgs, 0].concat(args); // create method call params
746 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
748 return method.apply(obj || window, callArgs);
753 * Calls this function after the number of millseconds specified.
754 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
755 * @param {Object} obj (optional) The object for which the scope is set
756 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
757 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
758 * if a number the args are inserted at the specified position
759 * @return {Number} The timeout id that can be used with clearTimeout
761 defer : function(millis, obj, args, appendArgs){
762 var fn = this.createDelegate(obj, args, appendArgs);
764 return setTimeout(fn, millis);
770 * Create a combined function call sequence of the original function + the passed function.
771 * The resulting function returns the results of the original function.
772 * The passed fcn is called with the parameters of the original function
773 * @param {Function} fcn The function to sequence
774 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
775 * @return {Function} The new function
777 createSequence : function(fcn, scope){
778 if(typeof fcn != "function"){
783 var retval = method.apply(this || window, arguments);
784 fcn.apply(scope || this || window, arguments);
790 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
791 * The resulting function returns the results of the original function.
792 * The passed fcn is called with the parameters of the original function.
794 * @param {Function} fcn The function to call before the original
795 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
796 * @return {Function} The new function
798 createInterceptor : function(fcn, scope){
799 if(typeof fcn != "function"){
806 if(fcn.apply(scope || this || window, arguments) === false){
809 return method.apply(this || window, arguments);
815 * Ext JS Library 1.1.1
816 * Copyright(c) 2006-2007, Ext JS, LLC.
818 * Originally Released Under LGPL - original licence link has changed is not relivant.
821 * <script type="text/javascript">
824 Roo.applyIf(String, {
829 * Escapes the passed string for ' and \
830 * @param {String} string The string to escape
831 * @return {String} The escaped string
834 escape : function(string) {
835 return string.replace(/('|\\)/g, "\\$1");
839 * Pads the left side of a string with a specified character. This is especially useful
840 * for normalizing number and date strings. Example usage:
842 var s = String.leftPad('123', 5, '0');
843 // s now contains the string: '00123'
845 * @param {String} string The original string
846 * @param {Number} size The total length of the output string
847 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
848 * @return {String} The padded string
851 leftPad : function (val, size, ch) {
852 var result = new String(val);
853 if(ch === null || ch === undefined || ch === '') {
856 while (result.length < size) {
857 result = ch + result;
863 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
864 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
866 var cls = 'my-class', text = 'Some text';
867 var s = String.format('<div class="{0}">{1}</div>', cls, text);
868 // s now contains the string: '<div class="my-class">Some text</div>'
870 * @param {String} string The tokenized string to be formatted
871 * @param {String} value1 The value to replace token {0}
872 * @param {String} value2 Etc...
873 * @return {String} The formatted string
876 format : function(format){
877 var args = Array.prototype.slice.call(arguments, 1);
878 return format.replace(/\{(\d+)\}/g, function(m, i){
879 return Roo.util.Format.htmlEncode(args[i]);
885 * Utility function that allows you to easily switch a string between two alternating values. The passed value
886 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
887 * they are already different, the first value passed in is returned. Note that this method returns the new value
888 * but does not change the current string.
890 // alternate sort directions
891 sort = sort.toggle('ASC', 'DESC');
893 // instead of conditional logic:
894 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
896 * @param {String} value The value to compare to the current string
897 * @param {String} other The new value to use if the string already equals the first value passed in
898 * @return {String} The new value
901 String.prototype.toggle = function(value, other){
902 return this == value ? other : value;
905 * Ext JS Library 1.1.1
906 * Copyright(c) 2006-2007, Ext JS, LLC.
908 * Originally Released Under LGPL - original licence link has changed is not relivant.
911 * <script type="text/javascript">
917 Roo.applyIf(Number.prototype, {
919 * Checks whether or not the current number is within a desired range. If the number is already within the
920 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
921 * exceeded. Note that this method returns the constrained value but does not change the current number.
922 * @param {Number} min The minimum number in the range
923 * @param {Number} max The maximum number in the range
924 * @return {Number} The constrained value if outside the range, otherwise the current value
926 constrain : function(min, max){
927 return Math.min(Math.max(this, min), max);
931 * Ext JS Library 1.1.1
932 * Copyright(c) 2006-2007, Ext JS, LLC.
934 * Originally Released Under LGPL - original licence link has changed is not relivant.
937 * <script type="text/javascript">
942 Roo.applyIf(Array.prototype, {
945 * Checks whether or not the specified object exists in the array.
946 * @param {Object} o The object to check for
947 * @return {Number} The index of o in the array (or -1 if it is not found)
949 indexOf : function(o){
950 for (var i = 0, len = this.length; i < len; i++){
951 if(this[i] == o) { return i; }
957 * Removes the specified object from the array. If the object is not found nothing happens.
958 * @param {Object} o The object to remove
960 remove : function(o){
961 var index = this.indexOf(o);
963 this.splice(index, 1);
967 * Map (JS 1.6 compatibility)
968 * @param {Function} function to call
972 var len = this.length >>> 0;
973 if (typeof fun != "function") {
974 throw new TypeError();
976 var res = new Array(len);
977 var thisp = arguments[1];
978 for (var i = 0; i < len; i++)
981 res[i] = fun.call(thisp, this[i], i, this);
994 * Ext JS Library 1.1.1
995 * Copyright(c) 2006-2007, Ext JS, LLC.
997 * Originally Released Under LGPL - original licence link has changed is not relivant.
1000 * <script type="text/javascript">
1006 * The date parsing and format syntax is a subset of
1007 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
1008 * supported will provide results equivalent to their PHP versions.
1010 * Following is the list of all currently supported formats:
1013 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
1015 Format Output Description
1016 ------ ---------- --------------------------------------------------------------
1017 d 10 Day of the month, 2 digits with leading zeros
1018 D Wed A textual representation of a day, three letters
1019 j 10 Day of the month without leading zeros
1020 l Wednesday A full textual representation of the day of the week
1021 S th English ordinal day of month suffix, 2 chars (use with j)
1022 w 3 Numeric representation of the day of the week
1023 z 9 The julian date, or day of the year (0-365)
1024 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
1025 F January A full textual representation of the month
1026 m 01 Numeric representation of a month, with leading zeros
1027 M Jan Month name abbreviation, three letters
1028 n 1 Numeric representation of a month, without leading zeros
1029 t 31 Number of days in the given month
1030 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1031 Y 2007 A full numeric representation of a year, 4 digits
1032 y 07 A two digit representation of a year
1033 a pm Lowercase Ante meridiem and Post meridiem
1034 A PM Uppercase Ante meridiem and Post meridiem
1035 g 3 12-hour format of an hour without leading zeros
1036 G 15 24-hour format of an hour without leading zeros
1037 h 03 12-hour format of an hour with leading zeros
1038 H 15 24-hour format of an hour with leading zeros
1039 i 05 Minutes with leading zeros
1040 s 01 Seconds, with leading zeros
1041 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1042 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1043 T CST Timezone setting of the machine running the code
1044 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1047 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1049 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1050 document.write(dt.format('Y-m-d')); //2007-01-10
1051 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1052 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
1055 * Here are some standard date/time patterns that you might find helpful. They
1056 * are not part of the source of Date.js, but to use them you can simply copy this
1057 * block of code into any script that is included after Date.js and they will also become
1058 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1061 ISO8601Long:"Y-m-d H:i:s",
1062 ISO8601Short:"Y-m-d",
1064 LongDate: "l, F d, Y",
1065 FullDateTime: "l, F d, Y g:i:s A",
1068 LongTime: "g:i:s A",
1069 SortableDateTime: "Y-m-d\\TH:i:s",
1070 UniversalSortableDateTime: "Y-m-d H:i:sO",
1077 var dt = new Date();
1078 document.write(dt.format(Date.patterns.ShortDate));
1083 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1084 * They generate precompiled functions from date formats instead of parsing and
1085 * processing the pattern every time you format a date. These functions are available
1086 * on every Date object (any javascript function).
1088 * The original article and download are here:
1089 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1096 Returns the number of milliseconds between this date and date
1097 @param {Date} date (optional) Defaults to now
1098 @return {Number} The diff in milliseconds
1099 @member Date getElapsed
1101 Date.prototype.getElapsed = function(date) {
1102 return Math.abs((date || new Date()).getTime()-this.getTime());
1104 // was in date file..
1108 Date.parseFunctions = {count:0};
1110 Date.parseRegexes = [];
1112 Date.formatFunctions = {count:0};
1115 Date.prototype.dateFormat = function(format) {
1116 if (Date.formatFunctions[format] == null) {
1117 Date.createNewFormat(format);
1119 var func = Date.formatFunctions[format];
1120 return this[func]();
1125 * Formats a date given the supplied format string
1126 * @param {String} format The format string
1127 * @return {String} The formatted date
1130 Date.prototype.format = Date.prototype.dateFormat;
1133 Date.createNewFormat = function(format) {
1134 var funcName = "format" + Date.formatFunctions.count++;
1135 Date.formatFunctions[format] = funcName;
1136 var code = "Date.prototype." + funcName + " = function(){return ";
1137 var special = false;
1139 for (var i = 0; i < format.length; ++i) {
1140 ch = format.charAt(i);
1141 if (!special && ch == "\\") {
1146 code += "'" + String.escape(ch) + "' + ";
1149 code += Date.getFormatCode(ch);
1152 /** eval:var:zzzzzzzzzzzzz */
1153 eval(code.substring(0, code.length - 3) + ";}");
1157 Date.getFormatCode = function(character) {
1158 switch (character) {
1160 return "String.leftPad(this.getDate(), 2, '0') + ";
1162 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1164 return "this.getDate() + ";
1166 return "Date.dayNames[this.getDay()] + ";
1168 return "this.getSuffix() + ";
1170 return "this.getDay() + ";
1172 return "this.getDayOfYear() + ";
1174 return "this.getWeekOfYear() + ";
1176 return "Date.monthNames[this.getMonth()] + ";
1178 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1180 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1182 return "(this.getMonth() + 1) + ";
1184 return "this.getDaysInMonth() + ";
1186 return "(this.isLeapYear() ? 1 : 0) + ";
1188 return "this.getFullYear() + ";
1190 return "('' + this.getFullYear()).substring(2, 4) + ";
1192 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1194 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1196 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1198 return "this.getHours() + ";
1200 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1202 return "String.leftPad(this.getHours(), 2, '0') + ";
1204 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1206 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1208 return "this.getGMTOffset() + ";
1210 return "this.getGMTColonOffset() + ";
1212 return "this.getTimezone() + ";
1214 return "(this.getTimezoneOffset() * -60) + ";
1216 return "'" + String.escape(character) + "' + ";
1221 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1222 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1223 * the date format that is not specified will default to the current date value for that part. Time parts can also
1224 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1225 * string or the parse operation will fail.
1228 //dt = Fri May 25 2007 (current date)
1229 var dt = new Date();
1231 //dt = Thu May 25 2006 (today's month/day in 2006)
1232 dt = Date.parseDate("2006", "Y");
1234 //dt = Sun Jan 15 2006 (all date parts specified)
1235 dt = Date.parseDate("2006-1-15", "Y-m-d");
1237 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1238 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1240 * @param {String} input The unparsed date as a string
1241 * @param {String} format The format the date is in
1242 * @return {Date} The parsed date
1245 Date.parseDate = function(input, format) {
1246 if (Date.parseFunctions[format] == null) {
1247 Date.createParser(format);
1249 var func = Date.parseFunctions[format];
1250 return Date[func](input);
1256 Date.createParser = function(format) {
1257 var funcName = "parse" + Date.parseFunctions.count++;
1258 var regexNum = Date.parseRegexes.length;
1259 var currentGroup = 1;
1260 Date.parseFunctions[format] = funcName;
1262 var code = "Date." + funcName + " = function(input){\n"
1263 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1264 + "var d = new Date();\n"
1265 + "y = d.getFullYear();\n"
1266 + "m = d.getMonth();\n"
1267 + "d = d.getDate();\n"
1268 + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
1269 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1270 + "if (results && results.length > 0) {";
1273 var special = false;
1275 for (var i = 0; i < format.length; ++i) {
1276 ch = format.charAt(i);
1277 if (!special && ch == "\\") {
1282 regex += String.escape(ch);
1285 var obj = Date.formatCodeToRegex(ch, currentGroup);
1286 currentGroup += obj.g;
1288 if (obj.g && obj.c) {
1294 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1295 + "{v = new Date(y, m, d, h, i, s);}\n"
1296 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1297 + "{v = new Date(y, m, d, h, i);}\n"
1298 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1299 + "{v = new Date(y, m, d, h);}\n"
1300 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1301 + "{v = new Date(y, m, d);}\n"
1302 + "else if (y >= 0 && m >= 0)\n"
1303 + "{v = new Date(y, m);}\n"
1304 + "else if (y >= 0)\n"
1305 + "{v = new Date(y);}\n"
1306 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1307 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1308 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1311 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1312 /** eval:var:zzzzzzzzzzzzz */
1317 Date.formatCodeToRegex = function(character, currentGroup) {
1318 switch (character) {
1322 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1325 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1326 s:"(\\d{1,2})"}; // day of month without leading zeroes
1329 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1330 s:"(\\d{2})"}; // day of month with leading zeroes
1334 s:"(?:" + Date.dayNames.join("|") + ")"};
1338 s:"(?:st|nd|rd|th)"};
1353 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1354 s:"(" + Date.monthNames.join("|") + ")"};
1357 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1358 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1361 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1362 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1365 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1366 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1377 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1381 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1382 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1386 c:"if (results[" + currentGroup + "] == 'am') {\n"
1387 + "if (h == 12) { h = 0; }\n"
1388 + "} else { if (h < 12) { h += 12; }}",
1392 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1393 + "if (h == 12) { h = 0; }\n"
1394 + "} else { if (h < 12) { h += 12; }}",
1399 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1400 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1404 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1405 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1408 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1412 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1417 "o = results[", currentGroup, "];\n",
1418 "var sn = o.substring(0,1);\n", // get + / - sign
1419 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1420 "var mn = o.substring(3,5) % 60;\n", // get minutes
1421 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1422 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1424 s:"([+\-]\\d{2,4})"};
1430 "o = results[", currentGroup, "];\n",
1431 "var sn = o.substring(0,1);\n",
1432 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1433 "var mn = o.substring(4,6) % 60;\n",
1434 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1435 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1441 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1444 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1445 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1446 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1450 s:String.escape(character)};
1455 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1456 * @return {String} The abbreviated timezone name (e.g. 'CST')
1458 Date.prototype.getTimezone = function() {
1459 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1463 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1464 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1466 Date.prototype.getGMTOffset = function() {
1467 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1468 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1469 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1473 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1474 * @return {String} 2-characters representing hours and 2-characters representing minutes
1475 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1477 Date.prototype.getGMTColonOffset = function() {
1478 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1479 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1481 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1485 * Get the numeric day number of the year, adjusted for leap year.
1486 * @return {Number} 0 through 364 (365 in leap years)
1488 Date.prototype.getDayOfYear = function() {
1490 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1491 for (var i = 0; i < this.getMonth(); ++i) {
1492 num += Date.daysInMonth[i];
1494 return num + this.getDate() - 1;
1498 * Get the string representation of the numeric week number of the year
1499 * (equivalent to the format specifier 'W').
1500 * @return {String} '00' through '52'
1502 Date.prototype.getWeekOfYear = function() {
1503 // Skip to Thursday of this week
1504 var now = this.getDayOfYear() + (4 - this.getDay());
1505 // Find the first Thursday of the year
1506 var jan1 = new Date(this.getFullYear(), 0, 1);
1507 var then = (7 - jan1.getDay() + 4);
1508 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1512 * Whether or not the current date is in a leap year.
1513 * @return {Boolean} True if the current date is in a leap year, else false
1515 Date.prototype.isLeapYear = function() {
1516 var year = this.getFullYear();
1517 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1521 * Get the first day of the current month, adjusted for leap year. The returned value
1522 * is the numeric day index within the week (0-6) which can be used in conjunction with
1523 * the {@link #monthNames} array to retrieve the textual day name.
1526 var dt = new Date('1/10/2007');
1527 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1529 * @return {Number} The day number (0-6)
1531 Date.prototype.getFirstDayOfMonth = function() {
1532 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1533 return (day < 0) ? (day + 7) : day;
1537 * Get the last day of the current month, adjusted for leap year. The returned value
1538 * is the numeric day index within the week (0-6) which can be used in conjunction with
1539 * the {@link #monthNames} array to retrieve the textual day name.
1542 var dt = new Date('1/10/2007');
1543 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1545 * @return {Number} The day number (0-6)
1547 Date.prototype.getLastDayOfMonth = function() {
1548 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1549 return (day < 0) ? (day + 7) : day;
1554 * Get the first date of this date's month
1557 Date.prototype.getFirstDateOfMonth = function() {
1558 return new Date(this.getFullYear(), this.getMonth(), 1);
1562 * Get the last date of this date's month
1565 Date.prototype.getLastDateOfMonth = function() {
1566 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1569 * Get the number of days in the current month, adjusted for leap year.
1570 * @return {Number} The number of days in the month
1572 Date.prototype.getDaysInMonth = function() {
1573 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1574 return Date.daysInMonth[this.getMonth()];
1578 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1579 * @return {String} 'st, 'nd', 'rd' or 'th'
1581 Date.prototype.getSuffix = function() {
1582 switch (this.getDate()) {
1599 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1602 * An array of textual month names.
1603 * Override these values for international dates, for example...
1604 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1623 * An array of textual day names.
1624 * Override these values for international dates, for example...
1625 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1641 Date.monthNumbers = {
1656 * Creates and returns a new Date instance with the exact same date value as the called instance.
1657 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1658 * variable will also be changed. When the intention is to create a new variable that will not
1659 * modify the original instance, you should create a clone.
1661 * Example of correctly cloning a date:
1664 var orig = new Date('10/1/2006');
1667 document.write(orig); //returns 'Thu Oct 05 2006'!
1670 var orig = new Date('10/1/2006');
1671 var copy = orig.clone();
1673 document.write(orig); //returns 'Thu Oct 01 2006'
1675 * @return {Date} The new Date instance
1677 Date.prototype.clone = function() {
1678 return new Date(this.getTime());
1682 * Clears any time information from this date
1683 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1684 @return {Date} this or the clone
1686 Date.prototype.clearTime = function(clone){
1688 return this.clone().clearTime();
1693 this.setMilliseconds(0);
1698 // safari setMonth is broken -- check that this is only donw once...
1699 if(Roo.isSafari && typeof(Date.brokenSetMonth) == 'undefined'){
1700 Date.brokenSetMonth = Date.prototype.setMonth;
1701 Date.prototype.setMonth = function(num){
1703 var n = Math.ceil(-num);
1704 var back_year = Math.ceil(n/12);
1705 var month = (n % 12) ? 12 - n % 12 : 0 ;
1706 this.setFullYear(this.getFullYear() - back_year);
1707 return Date.brokenSetMonth.call(this, month);
1709 return Date.brokenSetMonth.apply(this, arguments);
1714 /** Date interval constant
1718 /** Date interval constant
1722 /** Date interval constant
1726 /** Date interval constant
1730 /** Date interval constant
1734 /** Date interval constant
1738 /** Date interval constant
1744 * Provides a convenient method of performing basic date arithmetic. This method
1745 * does not modify the Date instance being called - it creates and returns
1746 * a new Date instance containing the resulting date value.
1751 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1752 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1754 //Negative values will subtract correctly:
1755 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1756 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1758 //You can even chain several calls together in one line!
1759 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1760 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1763 * @param {String} interval A valid date interval enum value
1764 * @param {Number} value The amount to add to the current date
1765 * @return {Date} The new Date instance
1767 Date.prototype.add = function(interval, value){
1768 var d = this.clone();
1769 if (!interval || value === 0) { return d; }
1770 switch(interval.toLowerCase()){
1772 d.setMilliseconds(this.getMilliseconds() + value);
1775 d.setSeconds(this.getSeconds() + value);
1778 d.setMinutes(this.getMinutes() + value);
1781 d.setHours(this.getHours() + value);
1784 d.setDate(this.getDate() + value);
1787 var day = this.getDate();
1789 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1792 d.setMonth(this.getMonth() + value);
1795 d.setFullYear(this.getFullYear() + value);
1802 * Ext JS Library 1.1.1
1803 * Copyright(c) 2006-2007, Ext JS, LLC.
1805 * Originally Released Under LGPL - original licence link has changed is not relivant.
1808 * <script type="text/javascript">
1812 * @class Roo.lib.Dom
1815 * Dom utils (from YIU afaik)
1820 * Get the view width
1821 * @param {Boolean} full True will get the full document, otherwise it's the view width
1822 * @return {Number} The width
1825 getViewWidth : function(full) {
1826 return full ? this.getDocumentWidth() : this.getViewportWidth();
1829 * Get the view height
1830 * @param {Boolean} full True will get the full document, otherwise it's the view height
1831 * @return {Number} The height
1833 getViewHeight : function(full) {
1834 return full ? this.getDocumentHeight() : this.getViewportHeight();
1837 getDocumentHeight: function() {
1838 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1839 return Math.max(scrollHeight, this.getViewportHeight());
1842 getDocumentWidth: function() {
1843 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1844 return Math.max(scrollWidth, this.getViewportWidth());
1847 getViewportHeight: function() {
1848 var height = self.innerHeight;
1849 var mode = document.compatMode;
1851 if ((mode || Roo.isIE) && !Roo.isOpera) {
1852 height = (mode == "CSS1Compat") ?
1853 document.documentElement.clientHeight :
1854 document.body.clientHeight;
1860 getViewportWidth: function() {
1861 var width = self.innerWidth;
1862 var mode = document.compatMode;
1864 if (mode || Roo.isIE) {
1865 width = (mode == "CSS1Compat") ?
1866 document.documentElement.clientWidth :
1867 document.body.clientWidth;
1872 isAncestor : function(p, c) {
1879 if (p.contains && !Roo.isSafari) {
1880 return p.contains(c);
1881 } else if (p.compareDocumentPosition) {
1882 return !!(p.compareDocumentPosition(c) & 16);
1884 var parent = c.parentNode;
1889 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1892 parent = parent.parentNode;
1898 getRegion : function(el) {
1899 return Roo.lib.Region.getRegion(el);
1902 getY : function(el) {
1903 return this.getXY(el)[1];
1906 getX : function(el) {
1907 return this.getXY(el)[0];
1910 getXY : function(el) {
1911 var p, pe, b, scroll, bd = document.body;
1912 el = Roo.getDom(el);
1913 var fly = Roo.lib.AnimBase.fly;
1914 if (el.getBoundingClientRect) {
1915 b = el.getBoundingClientRect();
1916 scroll = fly(document).getScroll();
1917 return [b.left + scroll.left, b.top + scroll.top];
1923 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1930 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1937 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1938 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1945 if (p != el && pe.getStyle('overflow') != 'visible') {
1953 if (Roo.isSafari && hasAbsolute) {
1958 if (Roo.isGecko && !hasAbsolute) {
1960 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1961 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1965 while (p && p != bd) {
1966 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1978 setXY : function(el, xy) {
1979 el = Roo.fly(el, '_setXY');
1981 var pts = el.translatePoints(xy);
1982 if (xy[0] !== false) {
1983 el.dom.style.left = pts.left + "px";
1985 if (xy[1] !== false) {
1986 el.dom.style.top = pts.top + "px";
1990 setX : function(el, x) {
1991 this.setXY(el, [x, false]);
1994 setY : function(el, y) {
1995 this.setXY(el, [false, y]);
1999 * Portions of this file are based on pieces of Yahoo User Interface Library
2000 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2001 * YUI licensed under the BSD License:
2002 * http://developer.yahoo.net/yui/license.txt
2003 * <script type="text/javascript">
2007 Roo.lib.Event = function() {
2008 var loadComplete = false;
2010 var unloadListeners = [];
2012 var onAvailStack = [];
2014 var lastError = null;
2027 startInterval: function() {
2028 if (!this._interval) {
2030 var callback = function() {
2031 self._tryPreloadAttach();
2033 this._interval = setInterval(callback, this.POLL_INTERVAL);
2038 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2039 onAvailStack.push({ id: p_id,
2042 override: p_override,
2043 checkReady: false });
2045 retryCount = this.POLL_RETRYS;
2046 this.startInterval();
2050 addListener: function(el, eventName, fn) {
2051 el = Roo.getDom(el);
2056 if ("unload" == eventName) {
2057 unloadListeners[unloadListeners.length] =
2058 [el, eventName, fn];
2062 var wrappedFn = function(e) {
2063 return fn(Roo.lib.Event.getEvent(e));
2066 var li = [el, eventName, fn, wrappedFn];
2068 var index = listeners.length;
2069 listeners[index] = li;
2071 this.doAdd(el, eventName, wrappedFn, false);
2077 removeListener: function(el, eventName, fn) {
2080 el = Roo.getDom(el);
2083 return this.purgeElement(el, false, eventName);
2087 if ("unload" == eventName) {
2089 for (i = 0,len = unloadListeners.length; i < len; i++) {
2090 var li = unloadListeners[i];
2093 li[1] == eventName &&
2095 unloadListeners.splice(i, 1);
2103 var cacheItem = null;
2106 var index = arguments[3];
2108 if ("undefined" == typeof index) {
2109 index = this._getCacheIndex(el, eventName, fn);
2113 cacheItem = listeners[index];
2116 if (!el || !cacheItem) {
2120 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2122 delete listeners[index][this.WFN];
2123 delete listeners[index][this.FN];
2124 listeners.splice(index, 1);
2131 getTarget: function(ev, resolveTextNode) {
2132 ev = ev.browserEvent || ev;
2133 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2134 var t = ev.target || ev.srcElement;
2135 return this.resolveTextNode(t);
2139 resolveTextNode: function(node) {
2140 if (Roo.isSafari && node && 3 == node.nodeType) {
2141 return node.parentNode;
2148 getPageX: function(ev) {
2149 ev = ev.browserEvent || ev;
2150 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2152 if (!x && 0 !== x) {
2153 x = ev.clientX || 0;
2156 x += this.getScroll()[1];
2164 getPageY: function(ev) {
2165 ev = ev.browserEvent || ev;
2166 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2168 if (!y && 0 !== y) {
2169 y = ev.clientY || 0;
2172 y += this.getScroll()[0];
2181 getXY: function(ev) {
2182 ev = ev.browserEvent || ev;
2183 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2184 return [this.getPageX(ev), this.getPageY(ev)];
2188 getRelatedTarget: function(ev) {
2189 ev = ev.browserEvent || ev;
2190 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2191 var t = ev.relatedTarget;
2193 if (ev.type == "mouseout") {
2195 } else if (ev.type == "mouseover") {
2200 return this.resolveTextNode(t);
2204 getTime: function(ev) {
2205 ev = ev.browserEvent || ev;
2206 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2208 var t = new Date().getTime();
2212 this.lastError = ex;
2221 stopEvent: function(ev) {
2222 this.stopPropagation(ev);
2223 this.preventDefault(ev);
2227 stopPropagation: function(ev) {
2228 ev = ev.browserEvent || ev;
2229 if (ev.stopPropagation) {
2230 ev.stopPropagation();
2232 ev.cancelBubble = true;
2237 preventDefault: function(ev) {
2238 ev = ev.browserEvent || ev;
2239 if(ev.preventDefault) {
2240 ev.preventDefault();
2242 ev.returnValue = false;
2247 getEvent: function(e) {
2248 var ev = e || window.event;
2250 var c = this.getEvent.caller;
2252 ev = c.arguments[0];
2253 if (ev && Event == ev.constructor) {
2263 getCharCode: function(ev) {
2264 ev = ev.browserEvent || ev;
2265 return ev.charCode || ev.keyCode || 0;
2269 _getCacheIndex: function(el, eventName, fn) {
2270 for (var i = 0,len = listeners.length; i < len; ++i) {
2271 var li = listeners[i];
2273 li[this.FN] == fn &&
2274 li[this.EL] == el &&
2275 li[this.TYPE] == eventName) {
2287 getEl: function(id) {
2288 return document.getElementById(id);
2292 clearCache: function() {
2296 _load: function(e) {
2297 loadComplete = true;
2298 var EU = Roo.lib.Event;
2302 EU.doRemove(window, "load", EU._load);
2307 _tryPreloadAttach: function() {
2316 var tryAgain = !loadComplete;
2318 tryAgain = (retryCount > 0);
2323 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2324 var item = onAvailStack[i];
2326 var el = this.getEl(item.id);
2329 if (!item.checkReady ||
2332 (document && document.body)) {
2335 if (item.override) {
2336 if (item.override === true) {
2339 scope = item.override;
2342 item.fn.call(scope, item.obj);
2343 onAvailStack[i] = null;
2346 notAvail.push(item);
2351 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2355 this.startInterval();
2357 clearInterval(this._interval);
2358 this._interval = null;
2361 this.locked = false;
2368 purgeElement: function(el, recurse, eventName) {
2369 var elListeners = this.getListeners(el, eventName);
2371 for (var i = 0,len = elListeners.length; i < len; ++i) {
2372 var l = elListeners[i];
2373 this.removeListener(el, l.type, l.fn);
2377 if (recurse && el && el.childNodes) {
2378 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2379 this.purgeElement(el.childNodes[i], recurse, eventName);
2385 getListeners: function(el, eventName) {
2386 var results = [], searchLists;
2388 searchLists = [listeners, unloadListeners];
2389 } else if (eventName == "unload") {
2390 searchLists = [unloadListeners];
2392 searchLists = [listeners];
2395 for (var j = 0; j < searchLists.length; ++j) {
2396 var searchList = searchLists[j];
2397 if (searchList && searchList.length > 0) {
2398 for (var i = 0,len = searchList.length; i < len; ++i) {
2399 var l = searchList[i];
2400 if (l && l[this.EL] === el &&
2401 (!eventName || eventName === l[this.TYPE])) {
2406 adjust: l[this.ADJ_SCOPE],
2414 return (results.length) ? results : null;
2418 _unload: function(e) {
2420 var EU = Roo.lib.Event, i, j, l, len, index;
2422 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2423 l = unloadListeners[i];
2426 if (l[EU.ADJ_SCOPE]) {
2427 if (l[EU.ADJ_SCOPE] === true) {
2430 scope = l[EU.ADJ_SCOPE];
2433 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2434 unloadListeners[i] = null;
2440 unloadListeners = null;
2442 if (listeners && listeners.length > 0) {
2443 j = listeners.length;
2446 l = listeners[index];
2448 EU.removeListener(l[EU.EL], l[EU.TYPE],
2458 EU.doRemove(window, "unload", EU._unload);
2463 getScroll: function() {
2464 var dd = document.documentElement, db = document.body;
2465 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2466 return [dd.scrollTop, dd.scrollLeft];
2468 return [db.scrollTop, db.scrollLeft];
2475 doAdd: function () {
2476 if (window.addEventListener) {
2477 return function(el, eventName, fn, capture) {
2478 el.addEventListener(eventName, fn, (capture));
2480 } else if (window.attachEvent) {
2481 return function(el, eventName, fn, capture) {
2482 el.attachEvent("on" + eventName, fn);
2491 doRemove: function() {
2492 if (window.removeEventListener) {
2493 return function (el, eventName, fn, capture) {
2494 el.removeEventListener(eventName, fn, (capture));
2496 } else if (window.detachEvent) {
2497 return function (el, eventName, fn) {
2498 el.detachEvent("on" + eventName, fn);
2510 var E = Roo.lib.Event;
2511 E.on = E.addListener;
2512 E.un = E.removeListener;
2514 if (document && document.body) {
2517 E.doAdd(window, "load", E._load);
2519 E.doAdd(window, "unload", E._unload);
2520 E._tryPreloadAttach();
2524 * Portions of this file are based on pieces of Yahoo User Interface Library
2525 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2526 * YUI licensed under the BSD License:
2527 * http://developer.yahoo.net/yui/license.txt
2528 * <script type="text/javascript">
2534 * @class Roo.lib.Ajax
2541 request : function(method, uri, cb, data, options) {
2543 var hs = options.headers;
2546 if(hs.hasOwnProperty(h)){
2547 this.initHeader(h, hs[h], false);
2551 if(options.xmlData){
2552 this.initHeader('Content-Type', 'text/xml', false);
2554 data = options.xmlData;
2558 return this.asyncRequest(method, uri, cb, data);
2561 serializeForm : function(form) {
2562 if(typeof form == 'string') {
2563 form = (document.getElementById(form) || document.forms[form]);
2566 var el, name, val, disabled, data = '', hasSubmit = false;
2567 for (var i = 0; i < form.elements.length; i++) {
2568 el = form.elements[i];
2569 disabled = form.elements[i].disabled;
2570 name = form.elements[i].name;
2571 val = form.elements[i].value;
2573 if (!disabled && name){
2577 case 'select-multiple':
2578 for (var j = 0; j < el.options.length; j++) {
2579 if (el.options[j].selected) {
2581 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2584 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2592 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2605 if(hasSubmit == false) {
2606 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2611 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2616 data = data.substr(0, data.length - 1);
2624 useDefaultHeader:true,
2626 defaultPostHeader:'application/x-www-form-urlencoded',
2628 useDefaultXhrHeader:true,
2630 defaultXhrHeader:'XMLHttpRequest',
2632 hasDefaultHeaders:true,
2644 setProgId:function(id)
2646 this.activeX.unshift(id);
2649 setDefaultPostHeader:function(b)
2651 this.useDefaultHeader = b;
2654 setDefaultXhrHeader:function(b)
2656 this.useDefaultXhrHeader = b;
2659 setPollingInterval:function(i)
2661 if (typeof i == 'number' && isFinite(i)) {
2662 this.pollInterval = i;
2666 createXhrObject:function(transactionId)
2672 http = new XMLHttpRequest();
2674 obj = { conn:http, tId:transactionId };
2678 for (var i = 0; i < this.activeX.length; ++i) {
2682 http = new ActiveXObject(this.activeX[i]);
2684 obj = { conn:http, tId:transactionId };
2697 getConnectionObject:function()
2700 var tId = this.transactionId;
2704 o = this.createXhrObject(tId);
2706 this.transactionId++;
2717 asyncRequest:function(method, uri, callback, postData)
2719 var o = this.getConnectionObject();
2725 o.conn.open(method, uri, true);
2727 if (this.useDefaultXhrHeader) {
2728 if (!this.defaultHeaders['X-Requested-With']) {
2729 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2733 if(postData && this.useDefaultHeader){
2734 this.initHeader('Content-Type', this.defaultPostHeader);
2737 if (this.hasDefaultHeaders || this.hasHeaders) {
2741 this.handleReadyState(o, callback);
2742 o.conn.send(postData || null);
2748 handleReadyState:function(o, callback)
2752 if (callback && callback.timeout) {
2754 this.timeout[o.tId] = window.setTimeout(function() {
2755 oConn.abort(o, callback, true);
2756 }, callback.timeout);
2759 this.poll[o.tId] = window.setInterval(
2761 if (o.conn && o.conn.readyState == 4) {
2762 window.clearInterval(oConn.poll[o.tId]);
2763 delete oConn.poll[o.tId];
2765 if(callback && callback.timeout) {
2766 window.clearTimeout(oConn.timeout[o.tId]);
2767 delete oConn.timeout[o.tId];
2770 oConn.handleTransactionResponse(o, callback);
2773 , this.pollInterval);
2776 handleTransactionResponse:function(o, callback, isAbort)
2780 this.releaseObject(o);
2784 var httpStatus, responseObject;
2788 if (o.conn.status !== undefined && o.conn.status != 0) {
2789 httpStatus = o.conn.status;
2801 if (httpStatus >= 200 && httpStatus < 300) {
2802 responseObject = this.createResponseObject(o, callback.argument);
2803 if (callback.success) {
2804 if (!callback.scope) {
2805 callback.success(responseObject);
2810 callback.success.apply(callback.scope, [responseObject]);
2815 switch (httpStatus) {
2823 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2824 if (callback.failure) {
2825 if (!callback.scope) {
2826 callback.failure(responseObject);
2829 callback.failure.apply(callback.scope, [responseObject]);
2834 responseObject = this.createResponseObject(o, callback.argument);
2835 if (callback.failure) {
2836 if (!callback.scope) {
2837 callback.failure(responseObject);
2840 callback.failure.apply(callback.scope, [responseObject]);
2846 this.releaseObject(o);
2847 responseObject = null;
2850 createResponseObject:function(o, callbackArg)
2857 var headerStr = o.conn.getAllResponseHeaders();
2858 var header = headerStr.split('\n');
2859 for (var i = 0; i < header.length; i++) {
2860 var delimitPos = header[i].indexOf(':');
2861 if (delimitPos != -1) {
2862 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2870 obj.status = o.conn.status;
2871 obj.statusText = o.conn.statusText;
2872 obj.getResponseHeader = headerObj;
2873 obj.getAllResponseHeaders = headerStr;
2874 obj.responseText = o.conn.responseText;
2875 obj.responseXML = o.conn.responseXML;
2877 if (typeof callbackArg !== undefined) {
2878 obj.argument = callbackArg;
2884 createExceptionObject:function(tId, callbackArg, isAbort)
2887 var COMM_ERROR = 'communication failure';
2888 var ABORT_CODE = -1;
2889 var ABORT_ERROR = 'transaction aborted';
2895 obj.status = ABORT_CODE;
2896 obj.statusText = ABORT_ERROR;
2899 obj.status = COMM_CODE;
2900 obj.statusText = COMM_ERROR;
2904 obj.argument = callbackArg;
2910 initHeader:function(label, value, isDefault)
2912 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2914 if (headerObj[label] === undefined) {
2915 headerObj[label] = value;
2920 headerObj[label] = value + "," + headerObj[label];
2924 this.hasDefaultHeaders = true;
2927 this.hasHeaders = true;
2932 setHeader:function(o)
2934 if (this.hasDefaultHeaders) {
2935 for (var prop in this.defaultHeaders) {
2936 if (this.defaultHeaders.hasOwnProperty(prop)) {
2937 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2942 if (this.hasHeaders) {
2943 for (var prop in this.headers) {
2944 if (this.headers.hasOwnProperty(prop)) {
2945 o.conn.setRequestHeader(prop, this.headers[prop]);
2949 this.hasHeaders = false;
2953 resetDefaultHeaders:function() {
2954 delete this.defaultHeaders;
2955 this.defaultHeaders = {};
2956 this.hasDefaultHeaders = false;
2959 abort:function(o, callback, isTimeout)
2961 if(this.isCallInProgress(o)) {
2963 window.clearInterval(this.poll[o.tId]);
2964 delete this.poll[o.tId];
2966 delete this.timeout[o.tId];
2969 this.handleTransactionResponse(o, callback, true);
2979 isCallInProgress:function(o)
2982 return o.conn.readyState != 4 && o.conn.readyState != 0;
2991 releaseObject:function(o)
3000 'MSXML2.XMLHTTP.3.0',
3008 * Portions of this file are based on pieces of Yahoo User Interface Library
3009 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3010 * YUI licensed under the BSD License:
3011 * http://developer.yahoo.net/yui/license.txt
3012 * <script type="text/javascript">
3016 Roo.lib.Region = function(t, r, b, l) {
3026 Roo.lib.Region.prototype = {
3027 contains : function(region) {
3028 return ( region.left >= this.left &&
3029 region.right <= this.right &&
3030 region.top >= this.top &&
3031 region.bottom <= this.bottom );
3035 getArea : function() {
3036 return ( (this.bottom - this.top) * (this.right - this.left) );
3039 intersect : function(region) {
3040 var t = Math.max(this.top, region.top);
3041 var r = Math.min(this.right, region.right);
3042 var b = Math.min(this.bottom, region.bottom);
3043 var l = Math.max(this.left, region.left);
3045 if (b >= t && r >= l) {
3046 return new Roo.lib.Region(t, r, b, l);
3051 union : function(region) {
3052 var t = Math.min(this.top, region.top);
3053 var r = Math.max(this.right, region.right);
3054 var b = Math.max(this.bottom, region.bottom);
3055 var l = Math.min(this.left, region.left);
3057 return new Roo.lib.Region(t, r, b, l);
3060 adjust : function(t, l, b, r) {
3069 Roo.lib.Region.getRegion = function(el) {
3070 var p = Roo.lib.Dom.getXY(el);
3073 var r = p[0] + el.offsetWidth;
3074 var b = p[1] + el.offsetHeight;
3077 return new Roo.lib.Region(t, r, b, l);
3080 * Portions of this file are based on pieces of Yahoo User Interface Library
3081 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3082 * YUI licensed under the BSD License:
3083 * http://developer.yahoo.net/yui/license.txt
3084 * <script type="text/javascript">
3087 //@@dep Roo.lib.Region
3090 Roo.lib.Point = function(x, y) {
3091 if (x instanceof Array) {
3095 this.x = this.right = this.left = this[0] = x;
3096 this.y = this.top = this.bottom = this[1] = y;
3099 Roo.lib.Point.prototype = new Roo.lib.Region();
3101 * Portions of this file are based on pieces of Yahoo User Interface Library
3102 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3103 * YUI licensed under the BSD License:
3104 * http://developer.yahoo.net/yui/license.txt
3105 * <script type="text/javascript">
3112 scroll : function(el, args, duration, easing, cb, scope) {
3113 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3116 motion : function(el, args, duration, easing, cb, scope) {
3117 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3120 color : function(el, args, duration, easing, cb, scope) {
3121 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3124 run : function(el, args, duration, easing, cb, scope, type) {
3125 type = type || Roo.lib.AnimBase;
3126 if (typeof easing == "string") {
3127 easing = Roo.lib.Easing[easing];
3129 var anim = new type(el, args, duration, easing);
3130 anim.animateX(function() {
3131 Roo.callback(cb, scope);
3137 * Portions of this file are based on pieces of Yahoo User Interface Library
3138 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3139 * YUI licensed under the BSD License:
3140 * http://developer.yahoo.net/yui/license.txt
3141 * <script type="text/javascript">
3149 if (!libFlyweight) {
3150 libFlyweight = new Roo.Element.Flyweight();
3152 libFlyweight.dom = el;
3153 return libFlyweight;
3156 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3160 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3162 this.init(el, attributes, duration, method);
3166 Roo.lib.AnimBase.fly = fly;
3170 Roo.lib.AnimBase.prototype = {
3172 toString: function() {
3173 var el = this.getEl();
3174 var id = el.id || el.tagName;
3175 return ("Anim " + id);
3179 noNegatives: /width|height|opacity|padding/i,
3180 offsetAttribute: /^((width|height)|(top|left))$/,
3181 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3182 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3186 doMethod: function(attr, start, end) {
3187 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3191 setAttribute: function(attr, val, unit) {
3192 if (this.patterns.noNegatives.test(attr)) {
3193 val = (val > 0) ? val : 0;
3196 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3200 getAttribute: function(attr) {
3201 var el = this.getEl();
3202 var val = fly(el).getStyle(attr);
3204 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3205 return parseFloat(val);
3208 var a = this.patterns.offsetAttribute.exec(attr) || [];
3209 var pos = !!( a[3] );
3210 var box = !!( a[2] );
3213 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3214 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3223 getDefaultUnit: function(attr) {
3224 if (this.patterns.defaultUnit.test(attr)) {
3231 animateX : function(callback, scope) {
3232 var f = function() {
3233 this.onComplete.removeListener(f);
3234 if (typeof callback == "function") {
3235 callback.call(scope || this, this);
3238 this.onComplete.addListener(f, this);
3243 setRuntimeAttribute: function(attr) {
3246 var attributes = this.attributes;
3248 this.runtimeAttributes[attr] = {};
3250 var isset = function(prop) {
3251 return (typeof prop !== 'undefined');
3254 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3258 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3261 if (isset(attributes[attr]['to'])) {
3262 end = attributes[attr]['to'];
3263 } else if (isset(attributes[attr]['by'])) {
3264 if (start.constructor == Array) {
3266 for (var i = 0, len = start.length; i < len; ++i) {
3267 end[i] = start[i] + attributes[attr]['by'][i];
3270 end = start + attributes[attr]['by'];
3274 this.runtimeAttributes[attr].start = start;
3275 this.runtimeAttributes[attr].end = end;
3278 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3282 init: function(el, attributes, duration, method) {
3284 var isAnimated = false;
3287 var startTime = null;
3290 var actualFrames = 0;
3293 el = Roo.getDom(el);
3296 this.attributes = attributes || {};
3299 this.duration = duration || 1;
3302 this.method = method || Roo.lib.Easing.easeNone;
3305 this.useSeconds = true;
3308 this.currentFrame = 0;
3311 this.totalFrames = Roo.lib.AnimMgr.fps;
3314 this.getEl = function() {
3319 this.isAnimated = function() {
3324 this.getStartTime = function() {
3328 this.runtimeAttributes = {};
3331 this.animate = function() {
3332 if (this.isAnimated()) {
3336 this.currentFrame = 0;
3338 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3340 Roo.lib.AnimMgr.registerElement(this);
3344 this.stop = function(finish) {
3346 this.currentFrame = this.totalFrames;
3347 this._onTween.fire();
3349 Roo.lib.AnimMgr.stop(this);
3352 var onStart = function() {
3353 this.onStart.fire();
3355 this.runtimeAttributes = {};
3356 for (var attr in this.attributes) {
3357 this.setRuntimeAttribute(attr);
3362 startTime = new Date();
3366 var onTween = function() {
3368 duration: new Date() - this.getStartTime(),
3369 currentFrame: this.currentFrame
3372 data.toString = function() {
3374 'duration: ' + data.duration +
3375 ', currentFrame: ' + data.currentFrame
3379 this.onTween.fire(data);
3381 var runtimeAttributes = this.runtimeAttributes;
3383 for (var attr in runtimeAttributes) {
3384 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3390 var onComplete = function() {
3391 var actual_duration = (new Date() - startTime) / 1000 ;
3394 duration: actual_duration,
3395 frames: actualFrames,
3396 fps: actualFrames / actual_duration
3399 data.toString = function() {
3401 'duration: ' + data.duration +
3402 ', frames: ' + data.frames +
3403 ', fps: ' + data.fps
3409 this.onComplete.fire(data);
3413 this._onStart = new Roo.util.Event(this);
3414 this.onStart = new Roo.util.Event(this);
3415 this.onTween = new Roo.util.Event(this);
3416 this._onTween = new Roo.util.Event(this);
3417 this.onComplete = new Roo.util.Event(this);
3418 this._onComplete = new Roo.util.Event(this);
3419 this._onStart.addListener(onStart);
3420 this._onTween.addListener(onTween);
3421 this._onComplete.addListener(onComplete);
3426 * Portions of this file are based on pieces of Yahoo User Interface Library
3427 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3428 * YUI licensed under the BSD License:
3429 * http://developer.yahoo.net/yui/license.txt
3430 * <script type="text/javascript">
3434 Roo.lib.AnimMgr = new function() {
3451 this.registerElement = function(tween) {
3452 queue[queue.length] = tween;
3454 tween._onStart.fire();
3459 this.unRegister = function(tween, index) {
3460 tween._onComplete.fire();
3461 index = index || getIndex(tween);
3463 queue.splice(index, 1);
3467 if (tweenCount <= 0) {
3473 this.start = function() {
3474 if (thread === null) {
3475 thread = setInterval(this.run, this.delay);
3480 this.stop = function(tween) {
3482 clearInterval(thread);
3484 for (var i = 0, len = queue.length; i < len; ++i) {
3485 if (queue[0].isAnimated()) {
3486 this.unRegister(queue[0], 0);
3495 this.unRegister(tween);
3500 this.run = function() {
3501 for (var i = 0, len = queue.length; i < len; ++i) {
3502 var tween = queue[i];
3503 if (!tween || !tween.isAnimated()) {
3507 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3509 tween.currentFrame += 1;
3511 if (tween.useSeconds) {
3512 correctFrame(tween);
3514 tween._onTween.fire();
3517 Roo.lib.AnimMgr.stop(tween, i);
3522 var getIndex = function(anim) {
3523 for (var i = 0, len = queue.length; i < len; ++i) {
3524 if (queue[i] == anim) {
3532 var correctFrame = function(tween) {
3533 var frames = tween.totalFrames;
3534 var frame = tween.currentFrame;
3535 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3536 var elapsed = (new Date() - tween.getStartTime());
3539 if (elapsed < tween.duration * 1000) {
3540 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3542 tweak = frames - (frame + 1);
3544 if (tweak > 0 && isFinite(tweak)) {
3545 if (tween.currentFrame + tweak >= frames) {
3546 tweak = frames - (frame + 1);
3549 tween.currentFrame += tweak;
3555 * Portions of this file are based on pieces of Yahoo User Interface Library
3556 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3557 * YUI licensed under the BSD License:
3558 * http://developer.yahoo.net/yui/license.txt
3559 * <script type="text/javascript">
3562 Roo.lib.Bezier = new function() {
3564 this.getPosition = function(points, t) {
3565 var n = points.length;
3568 for (var i = 0; i < n; ++i) {
3569 tmp[i] = [points[i][0], points[i][1]];
3572 for (var j = 1; j < n; ++j) {
3573 for (i = 0; i < n - j; ++i) {
3574 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3575 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3579 return [ tmp[0][0], tmp[0][1] ];
3583 * Portions of this file are based on pieces of Yahoo User Interface Library
3584 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3585 * YUI licensed under the BSD License:
3586 * http://developer.yahoo.net/yui/license.txt
3587 * <script type="text/javascript">
3592 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3593 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3596 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3598 var fly = Roo.lib.AnimBase.fly;
3600 var superclass = Y.ColorAnim.superclass;
3601 var proto = Y.ColorAnim.prototype;
3603 proto.toString = function() {
3604 var el = this.getEl();
3605 var id = el.id || el.tagName;
3606 return ("ColorAnim " + id);
3609 proto.patterns.color = /color$/i;
3610 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3611 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3612 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3613 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3616 proto.parseColor = function(s) {
3617 if (s.length == 3) {
3621 var c = this.patterns.hex.exec(s);
3622 if (c && c.length == 4) {
3623 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3626 c = this.patterns.rgb.exec(s);
3627 if (c && c.length == 4) {
3628 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3631 c = this.patterns.hex3.exec(s);
3632 if (c && c.length == 4) {
3633 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3638 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3639 proto.getAttribute = function(attr) {
3640 var el = this.getEl();
3641 if (this.patterns.color.test(attr)) {
3642 var val = fly(el).getStyle(attr);
3644 if (this.patterns.transparent.test(val)) {
3645 var parent = el.parentNode;
3646 val = fly(parent).getStyle(attr);
3648 while (parent && this.patterns.transparent.test(val)) {
3649 parent = parent.parentNode;
3650 val = fly(parent).getStyle(attr);
3651 if (parent.tagName.toUpperCase() == 'HTML') {
3657 val = superclass.getAttribute.call(this, attr);
3662 proto.getAttribute = function(attr) {
3663 var el = this.getEl();
3664 if (this.patterns.color.test(attr)) {
3665 var val = fly(el).getStyle(attr);
3667 if (this.patterns.transparent.test(val)) {
3668 var parent = el.parentNode;
3669 val = fly(parent).getStyle(attr);
3671 while (parent && this.patterns.transparent.test(val)) {
3672 parent = parent.parentNode;
3673 val = fly(parent).getStyle(attr);
3674 if (parent.tagName.toUpperCase() == 'HTML') {
3680 val = superclass.getAttribute.call(this, attr);
3686 proto.doMethod = function(attr, start, end) {
3689 if (this.patterns.color.test(attr)) {
3691 for (var i = 0, len = start.length; i < len; ++i) {
3692 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3695 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3698 val = superclass.doMethod.call(this, attr, start, end);
3704 proto.setRuntimeAttribute = function(attr) {
3705 superclass.setRuntimeAttribute.call(this, attr);
3707 if (this.patterns.color.test(attr)) {
3708 var attributes = this.attributes;
3709 var start = this.parseColor(this.runtimeAttributes[attr].start);
3710 var end = this.parseColor(this.runtimeAttributes[attr].end);
3712 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3713 end = this.parseColor(attributes[attr].by);
3715 for (var i = 0, len = start.length; i < len; ++i) {
3716 end[i] = start[i] + end[i];
3720 this.runtimeAttributes[attr].start = start;
3721 this.runtimeAttributes[attr].end = end;
3727 * Portions of this file are based on pieces of Yahoo User Interface Library
3728 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3729 * YUI licensed under the BSD License:
3730 * http://developer.yahoo.net/yui/license.txt
3731 * <script type="text/javascript">
3737 easeNone: function (t, b, c, d) {
3738 return c * t / d + b;
3742 easeIn: function (t, b, c, d) {
3743 return c * (t /= d) * t + b;
3747 easeOut: function (t, b, c, d) {
3748 return -c * (t /= d) * (t - 2) + b;
3752 easeBoth: function (t, b, c, d) {
3753 if ((t /= d / 2) < 1) {
3754 return c / 2 * t * t + b;
3757 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3761 easeInStrong: function (t, b, c, d) {
3762 return c * (t /= d) * t * t * t + b;
3766 easeOutStrong: function (t, b, c, d) {
3767 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3771 easeBothStrong: function (t, b, c, d) {
3772 if ((t /= d / 2) < 1) {
3773 return c / 2 * t * t * t * t + b;
3776 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3781 elasticIn: function (t, b, c, d, a, p) {
3785 if ((t /= d) == 1) {
3792 if (!a || a < Math.abs(c)) {
3797 var s = p / (2 * Math.PI) * Math.asin(c / a);
3800 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3804 elasticOut: function (t, b, c, d, a, p) {
3808 if ((t /= d) == 1) {
3815 if (!a || a < Math.abs(c)) {
3820 var s = p / (2 * Math.PI) * Math.asin(c / a);
3823 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3827 elasticBoth: function (t, b, c, d, a, p) {
3832 if ((t /= d / 2) == 2) {
3840 if (!a || a < Math.abs(c)) {
3845 var s = p / (2 * Math.PI) * Math.asin(c / a);
3849 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3850 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3852 return a * Math.pow(2, -10 * (t -= 1)) *
3853 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3858 backIn: function (t, b, c, d, s) {
3859 if (typeof s == 'undefined') {
3862 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3866 backOut: function (t, b, c, d, s) {
3867 if (typeof s == 'undefined') {
3870 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3874 backBoth: function (t, b, c, d, s) {
3875 if (typeof s == 'undefined') {
3879 if ((t /= d / 2 ) < 1) {
3880 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3882 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3886 bounceIn: function (t, b, c, d) {
3887 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3891 bounceOut: function (t, b, c, d) {
3892 if ((t /= d) < (1 / 2.75)) {
3893 return c * (7.5625 * t * t) + b;
3894 } else if (t < (2 / 2.75)) {
3895 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3896 } else if (t < (2.5 / 2.75)) {
3897 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3899 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3903 bounceBoth: function (t, b, c, d) {
3905 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3907 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3910 * Portions of this file are based on pieces of Yahoo User Interface Library
3911 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3912 * YUI licensed under the BSD License:
3913 * http://developer.yahoo.net/yui/license.txt
3914 * <script type="text/javascript">
3918 Roo.lib.Motion = function(el, attributes, duration, method) {
3920 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3924 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3928 var superclass = Y.Motion.superclass;
3929 var proto = Y.Motion.prototype;
3931 proto.toString = function() {
3932 var el = this.getEl();
3933 var id = el.id || el.tagName;
3934 return ("Motion " + id);
3937 proto.patterns.points = /^points$/i;
3939 proto.setAttribute = function(attr, val, unit) {
3940 if (this.patterns.points.test(attr)) {
3941 unit = unit || 'px';
3942 superclass.setAttribute.call(this, 'left', val[0], unit);
3943 superclass.setAttribute.call(this, 'top', val[1], unit);
3945 superclass.setAttribute.call(this, attr, val, unit);
3949 proto.getAttribute = function(attr) {
3950 if (this.patterns.points.test(attr)) {
3952 superclass.getAttribute.call(this, 'left'),
3953 superclass.getAttribute.call(this, 'top')
3956 val = superclass.getAttribute.call(this, attr);
3962 proto.doMethod = function(attr, start, end) {
3965 if (this.patterns.points.test(attr)) {
3966 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3967 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3969 val = superclass.doMethod.call(this, attr, start, end);
3974 proto.setRuntimeAttribute = function(attr) {
3975 if (this.patterns.points.test(attr)) {
3976 var el = this.getEl();
3977 var attributes = this.attributes;
3979 var control = attributes['points']['control'] || [];
3983 if (control.length > 0 && !(control[0] instanceof Array)) {
3984 control = [control];
3987 for (i = 0,len = control.length; i < len; ++i) {
3988 tmp[i] = control[i];
3993 Roo.fly(el).position();
3995 if (isset(attributes['points']['from'])) {
3996 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3999 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
4002 start = this.getAttribute('points');
4005 if (isset(attributes['points']['to'])) {
4006 end = translateValues.call(this, attributes['points']['to'], start);
4008 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4009 for (i = 0,len = control.length; i < len; ++i) {
4010 control[i] = translateValues.call(this, control[i], start);
4014 } else if (isset(attributes['points']['by'])) {
4015 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
4017 for (i = 0,len = control.length; i < len; ++i) {
4018 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
4022 this.runtimeAttributes[attr] = [start];
4024 if (control.length > 0) {
4025 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4028 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4031 superclass.setRuntimeAttribute.call(this, attr);
4035 var translateValues = function(val, start) {
4036 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4037 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4042 var isset = function(prop) {
4043 return (typeof prop !== 'undefined');
4047 * Portions of this file are based on pieces of Yahoo User Interface Library
4048 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4049 * YUI licensed under the BSD License:
4050 * http://developer.yahoo.net/yui/license.txt
4051 * <script type="text/javascript">
4055 Roo.lib.Scroll = function(el, attributes, duration, method) {
4057 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4061 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4065 var superclass = Y.Scroll.superclass;
4066 var proto = Y.Scroll.prototype;
4068 proto.toString = function() {
4069 var el = this.getEl();
4070 var id = el.id || el.tagName;
4071 return ("Scroll " + id);
4074 proto.doMethod = function(attr, start, end) {
4077 if (attr == 'scroll') {
4079 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4080 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4084 val = superclass.doMethod.call(this, attr, start, end);
4089 proto.getAttribute = function(attr) {
4091 var el = this.getEl();
4093 if (attr == 'scroll') {
4094 val = [ el.scrollLeft, el.scrollTop ];
4096 val = superclass.getAttribute.call(this, attr);
4102 proto.setAttribute = function(attr, val, unit) {
4103 var el = this.getEl();
4105 if (attr == 'scroll') {
4106 el.scrollLeft = val[0];
4107 el.scrollTop = val[1];
4109 superclass.setAttribute.call(this, attr, val, unit);
4115 * Ext JS Library 1.1.1
4116 * Copyright(c) 2006-2007, Ext JS, LLC.
4118 * Originally Released Under LGPL - original licence link has changed is not relivant.
4121 * <script type="text/javascript">
4125 // nasty IE9 hack - what a pile of crap that is..
4127 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4128 Range.prototype.createContextualFragment = function (html) {
4129 var doc = window.document;
4130 var container = doc.createElement("div");
4131 container.innerHTML = html;
4132 var frag = doc.createDocumentFragment(), n;
4133 while ((n = container.firstChild)) {
4134 frag.appendChild(n);
4141 * @class Roo.DomHelper
4142 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4143 * For more information see <a href="http://web.archive.org/web/20071221063734/http://www.jackslocum.com/blog/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
4146 Roo.DomHelper = function(){
4147 var tempTableEl = null;
4148 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4149 var tableRe = /^table|tbody|tr|td$/i;
4151 // build as innerHTML where available
4153 var createHtml = function(o){
4154 if(typeof o == 'string'){
4163 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") { continue; }
4164 if(attr == "style"){
4166 if(typeof s == "function"){
4169 if(typeof s == "string"){
4170 b += ' style="' + s + '"';
4171 }else if(typeof s == "object"){
4174 if(typeof s[key] != "function"){
4175 b += key + ":" + s[key] + ";";
4182 b += ' class="' + o["cls"] + '"';
4183 }else if(attr == "htmlFor"){
4184 b += ' for="' + o["htmlFor"] + '"';
4186 b += " " + attr + '="' + o[attr] + '"';
4190 if(emptyTags.test(o.tag)){
4194 var cn = o.children || o.cn;
4196 //http://bugs.kde.org/show_bug.cgi?id=71506
4197 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4198 for(var i = 0, len = cn.length; i < len; i++) {
4199 b += createHtml(cn[i], b);
4202 b += createHtml(cn, b);
4208 b += "</" + o.tag + ">";
4215 var createDom = function(o, parentNode){
4217 // defininition craeted..
4219 if (o.ns && o.ns != 'html') {
4221 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4222 xmlns[o.ns] = o.xmlns;
4225 if (typeof(xmlns[o.ns]) == 'undefined') {
4226 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4232 if (typeof(o) == 'string') {
4233 return parentNode.appendChild(document.createTextNode(o));
4235 o.tag = o.tag || div;
4236 if (o.ns && Roo.isIE) {
4238 o.tag = o.ns + ':' + o.tag;
4241 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4242 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4245 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4246 attr == "style" || typeof o[attr] == "function") { continue; }
4248 if(attr=="cls" && Roo.isIE){
4249 el.className = o["cls"];
4251 if(useSet) { el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);}
4257 Roo.DomHelper.applyStyles(el, o.style);
4258 var cn = o.children || o.cn;
4260 //http://bugs.kde.org/show_bug.cgi?id=71506
4261 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4262 for(var i = 0, len = cn.length; i < len; i++) {
4263 createDom(cn[i], el);
4270 el.innerHTML = o.html;
4273 parentNode.appendChild(el);
4278 var ieTable = function(depth, s, h, e){
4279 tempTableEl.innerHTML = [s, h, e].join('');
4280 var i = -1, el = tempTableEl;
4287 // kill repeat to save bytes
4291 tbe = '</tbody>'+te,
4297 * Nasty code for IE's broken table implementation
4299 var insertIntoTable = function(tag, where, el, html){
4301 tempTableEl = document.createElement('div');
4306 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4309 if(where == 'beforebegin'){
4313 before = el.nextSibling;
4316 node = ieTable(4, trs, html, tre);
4318 else if(tag == 'tr'){
4319 if(where == 'beforebegin'){
4322 node = ieTable(3, tbs, html, tbe);
4323 } else if(where == 'afterend'){
4324 before = el.nextSibling;
4326 node = ieTable(3, tbs, html, tbe);
4327 } else{ // INTO a TR
4328 if(where == 'afterbegin'){
4329 before = el.firstChild;
4331 node = ieTable(4, trs, html, tre);
4333 } else if(tag == 'tbody'){
4334 if(where == 'beforebegin'){
4337 node = ieTable(2, ts, html, te);
4338 } else if(where == 'afterend'){
4339 before = el.nextSibling;
4341 node = ieTable(2, ts, html, te);
4343 if(where == 'afterbegin'){
4344 before = el.firstChild;
4346 node = ieTable(3, tbs, html, tbe);
4349 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4352 if(where == 'afterbegin'){
4353 before = el.firstChild;
4355 node = ieTable(2, ts, html, te);
4357 el.insertBefore(node, before);
4362 /** True to force the use of DOM instead of html fragments @type Boolean */
4366 * Returns the markup for the passed Element(s) config
4367 * @param {Object} o The Dom object spec (and children)
4370 markup : function(o){
4371 return createHtml(o);
4375 * Applies a style specification to an element
4376 * @param {String/HTMLElement} el The element to apply styles to
4377 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4378 * a function which returns such a specification.
4380 applyStyles : function(el, styles){
4383 if(typeof styles == "string"){
4384 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4386 while ((matches = re.exec(styles)) != null){
4387 el.setStyle(matches[1], matches[2]);
4389 }else if (typeof styles == "object"){
4390 for (var style in styles){
4391 el.setStyle(style, styles[style]);
4393 }else if (typeof styles == "function"){
4394 Roo.DomHelper.applyStyles(el, styles.call());
4400 * Inserts an HTML fragment into the Dom
4401 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4402 * @param {HTMLElement} el The context element
4403 * @param {String} html The HTML fragmenet
4404 * @return {HTMLElement} The new node
4406 insertHtml : function(where, el, html){
4407 where = where.toLowerCase();
4408 if(el.insertAdjacentHTML){
4409 if(tableRe.test(el.tagName)){
4411 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4417 el.insertAdjacentHTML('BeforeBegin', html);
4418 return el.previousSibling;
4420 el.insertAdjacentHTML('AfterBegin', html);
4421 return el.firstChild;
4423 el.insertAdjacentHTML('BeforeEnd', html);
4424 return el.lastChild;
4426 el.insertAdjacentHTML('AfterEnd', html);
4427 return el.nextSibling;
4429 throw 'Illegal insertion point -> "' + where + '"';
4431 var range = el.ownerDocument.createRange();
4435 range.setStartBefore(el);
4436 frag = range.createContextualFragment(html);
4437 el.parentNode.insertBefore(frag, el);
4438 return el.previousSibling;
4441 range.setStartBefore(el.firstChild);
4442 frag = range.createContextualFragment(html);
4443 el.insertBefore(frag, el.firstChild);
4444 return el.firstChild;
4446 el.innerHTML = html;
4447 return el.firstChild;
4451 range.setStartAfter(el.lastChild);
4452 frag = range.createContextualFragment(html);
4453 el.appendChild(frag);
4454 return el.lastChild;
4456 el.innerHTML = html;
4457 return el.lastChild;
4460 range.setStartAfter(el);
4461 frag = range.createContextualFragment(html);
4462 el.parentNode.insertBefore(frag, el.nextSibling);
4463 return el.nextSibling;
4465 throw 'Illegal insertion point -> "' + where + '"';
4469 * Creates new Dom element(s) and inserts them before el
4470 * @param {String/HTMLElement/Element} el The context element
4471 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4472 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4473 * @return {HTMLElement/Roo.Element} The new node
4475 insertBefore : function(el, o, returnElement){
4476 return this.doInsert(el, o, returnElement, "beforeBegin");
4480 * Creates new Dom element(s) and inserts them after el
4481 * @param {String/HTMLElement/Element} el The context element
4482 * @param {Object} o The Dom object spec (and children)
4483 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4484 * @return {HTMLElement/Roo.Element} The new node
4486 insertAfter : function(el, o, returnElement){
4487 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4491 * Creates new Dom element(s) and inserts them as the first child of el
4492 * @param {String/HTMLElement/Element} el The context element
4493 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4494 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4495 * @return {HTMLElement/Roo.Element} The new node
4497 insertFirst : function(el, o, returnElement){
4498 return this.doInsert(el, o, returnElement, "afterBegin");
4502 doInsert : function(el, o, returnElement, pos, sibling){
4503 el = Roo.getDom(el);
4505 if(this.useDom || o.ns){
4506 newNode = createDom(o, null);
4507 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4509 var html = createHtml(o);
4510 newNode = this.insertHtml(pos, el, html);
4512 return returnElement ? Roo.get(newNode, true) : newNode;
4516 * Creates new Dom element(s) and appends them to el
4517 * @param {String/HTMLElement/Element} el The context element
4518 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4519 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4520 * @return {HTMLElement/Roo.Element} The new node
4522 append : function(el, o, returnElement){
4523 el = Roo.getDom(el);
4525 if(this.useDom || o.ns){
4526 newNode = createDom(o, null);
4527 el.appendChild(newNode);
4529 var html = createHtml(o);
4530 newNode = this.insertHtml("beforeEnd", el, html);
4532 return returnElement ? Roo.get(newNode, true) : newNode;
4536 * Creates new Dom element(s) and overwrites the contents of el with them
4537 * @param {String/HTMLElement/Element} el The context element
4538 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4539 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4540 * @return {HTMLElement/Roo.Element} The new node
4542 overwrite : function(el, o, returnElement){
4543 el = Roo.getDom(el);
4546 while (el.childNodes.length) {
4547 el.removeChild(el.firstChild);
4551 el.innerHTML = createHtml(o);
4554 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4558 * Creates a new Roo.DomHelper.Template from the Dom object spec
4559 * @param {Object} o The Dom object spec (and children)
4560 * @return {Roo.DomHelper.Template} The new template
4562 createTemplate : function(o){
4563 var html = createHtml(o);
4564 return new Roo.Template(html);
4570 * Ext JS Library 1.1.1
4571 * Copyright(c) 2006-2007, Ext JS, LLC.
4573 * Originally Released Under LGPL - original licence link has changed is not relivant.
4576 * <script type="text/javascript">
4580 * @class Roo.Template
4581 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4582 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4585 var t = new Roo.Template({
4586 html : '<div name="{id}">' +
4587 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4589 myformat: function (value, allValues) {
4590 return 'XX' + value;
4593 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4595 * For more information see this blog post with examples:
4596 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4597 - Create Elements using DOM, HTML fragments and Templates</a>.
4599 * @param {Object} cfg - Configuration object.
4601 Roo.Template = function(cfg){
4603 if(cfg instanceof Array){
4605 }else if(arguments.length > 1){
4606 cfg = Array.prototype.join.call(arguments, "");
4610 if (typeof(cfg) == 'object') {
4621 Roo.Template.prototype = {
4624 * @cfg {String} url The Url to load the template from. beware if you are loading from a url, the data may not be ready if you use it instantly..
4625 * it should be fixed so that template is observable...
4629 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4633 * Returns an HTML fragment of this template with the specified values applied.
4634 * @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'})
4635 * @return {String} The HTML fragment
4637 applyTemplate : function(values){
4641 return this.compiled(values);
4643 var useF = this.disableFormats !== true;
4644 var fm = Roo.util.Format, tpl = this;
4645 var fn = function(m, name, format, args){
4647 if(format.substr(0, 5) == "this."){
4648 return tpl.call(format.substr(5), values[name], values);
4651 // quoted values are required for strings in compiled templates,
4652 // but for non compiled we need to strip them
4653 // quoted reversed for jsmin
4654 var re = /^\s*['"](.*)["']\s*$/;
4655 args = args.split(',');
4656 for(var i = 0, len = args.length; i < len; i++){
4657 args[i] = args[i].replace(re, "$1");
4659 args = [values[name]].concat(args);
4661 args = [values[name]];
4663 return fm[format].apply(fm, args);
4666 return values[name] !== undefined ? values[name] : "";
4669 return this.html.replace(this.re, fn);
4687 this.loading = true;
4688 this.compiled = false;
4690 var cx = new Roo.data.Connection();
4694 success : function (response) {
4696 _t.html = response.responseText;
4700 failure : function(response) {
4701 Roo.log("Template failed to load from " + _t.url);
4708 * Sets the HTML used as the template and optionally compiles it.
4709 * @param {String} html
4710 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4711 * @return {Roo.Template} this
4713 set : function(html, compile){
4715 this.compiled = null;
4723 * True to disable format functions (defaults to false)
4726 disableFormats : false,
4729 * The regular expression used to match template variables
4733 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4736 * Compiles the template into an internal function, eliminating the RegEx overhead.
4737 * @return {Roo.Template} this
4739 compile : function(){
4740 var fm = Roo.util.Format;
4741 var useF = this.disableFormats !== true;
4742 var sep = Roo.isGecko ? "+" : ",";
4743 var fn = function(m, name, format, args){
4745 args = args ? ',' + args : "";
4746 if(format.substr(0, 5) != "this."){
4747 format = "fm." + format + '(';
4749 format = 'this.call("'+ format.substr(5) + '", ';
4753 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4755 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4758 // branched to use + in gecko and [].join() in others
4760 body = "this.compiled = function(values){ return '" +
4761 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4764 body = ["this.compiled = function(values){ return ['"];
4765 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4766 body.push("'].join('');};");
4767 body = body.join('');
4777 // private function used to call members
4778 call : function(fnName, value, allValues){
4779 return this[fnName](value, allValues);
4783 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4784 * @param {String/HTMLElement/Roo.Element} el The context element
4785 * @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'})
4786 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4787 * @return {HTMLElement/Roo.Element} The new node or Element
4789 insertFirst: function(el, values, returnElement){
4790 return this.doInsert('afterBegin', el, values, returnElement);
4794 * Applies the supplied values to the template and inserts the new node(s) before el.
4795 * @param {String/HTMLElement/Roo.Element} el The context element
4796 * @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'})
4797 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4798 * @return {HTMLElement/Roo.Element} The new node or Element
4800 insertBefore: function(el, values, returnElement){
4801 return this.doInsert('beforeBegin', el, values, returnElement);
4805 * Applies the supplied values to the template and inserts the new node(s) after el.
4806 * @param {String/HTMLElement/Roo.Element} el The context element
4807 * @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'})
4808 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4809 * @return {HTMLElement/Roo.Element} The new node or Element
4811 insertAfter : function(el, values, returnElement){
4812 return this.doInsert('afterEnd', el, values, returnElement);
4816 * Applies the supplied values to the template and appends the new node(s) to el.
4817 * @param {String/HTMLElement/Roo.Element} el The context element
4818 * @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'})
4819 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4820 * @return {HTMLElement/Roo.Element} The new node or Element
4822 append : function(el, values, returnElement){
4823 return this.doInsert('beforeEnd', el, values, returnElement);
4826 doInsert : function(where, el, values, returnEl){
4827 el = Roo.getDom(el);
4828 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4829 return returnEl ? Roo.get(newNode, true) : newNode;
4833 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4834 * @param {String/HTMLElement/Roo.Element} el The context element
4835 * @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'})
4836 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4837 * @return {HTMLElement/Roo.Element} The new node or Element
4839 overwrite : function(el, values, returnElement){
4840 el = Roo.getDom(el);
4841 el.innerHTML = this.applyTemplate(values);
4842 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4846 * Alias for {@link #applyTemplate}
4849 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4852 Roo.DomHelper.Template = Roo.Template;
4855 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4856 * @param {String/HTMLElement} el A DOM element or its id
4857 * @returns {Roo.Template} The created template
4860 Roo.Template.from = function(el){
4861 el = Roo.getDom(el);
4862 return new Roo.Template(el.value || el.innerHTML);
4865 * Ext JS Library 1.1.1
4866 * Copyright(c) 2006-2007, Ext JS, LLC.
4868 * Originally Released Under LGPL - original licence link has changed is not relivant.
4871 * <script type="text/javascript">
4876 * This is code is also distributed under MIT license for use
4877 * with jQuery and prototype JavaScript libraries.
4880 * @class Roo.DomQuery
4881 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).
4883 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>
4886 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.
4888 <h4>Element Selectors:</h4>
4890 <li> <b>*</b> any element</li>
4891 <li> <b>E</b> an element with the tag E</li>
4892 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4893 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4894 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4895 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4897 <h4>Attribute Selectors:</h4>
4898 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4900 <li> <b>E[foo]</b> has an attribute "foo"</li>
4901 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4902 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4903 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4904 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4905 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4906 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4908 <h4>Pseudo Classes:</h4>
4910 <li> <b>E:first-child</b> E is the first child of its parent</li>
4911 <li> <b>E:last-child</b> E is the last child of its parent</li>
4912 <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>
4913 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4914 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4915 <li> <b>E:only-child</b> E is the only child of its parent</li>
4916 <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>
4917 <li> <b>E:first</b> the first E in the resultset</li>
4918 <li> <b>E:last</b> the last E in the resultset</li>
4919 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4920 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4921 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4922 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4923 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4924 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4925 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4926 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4927 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4929 <h4>CSS Value Selectors:</h4>
4931 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4932 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4933 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4934 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4935 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4936 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4940 Roo.DomQuery = function(){
4941 var cache = {}, simpleCache = {}, valueCache = {};
4942 var nonSpace = /\S/;
4943 var trimRe = /^\s+|\s+$/g;
4944 var tplRe = /\{(\d+)\}/g;
4945 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4946 var tagTokenRe = /^(#)?([\w-\*]+)/;
4947 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4949 function child(p, index){
4951 var n = p.firstChild;
4953 if(n.nodeType == 1){
4964 while((n = n.nextSibling) && n.nodeType != 1);
4969 while((n = n.previousSibling) && n.nodeType != 1);
4973 function children(d){
4974 var n = d.firstChild, ni = -1;
4976 var nx = n.nextSibling;
4977 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4987 function byClassName(c, a, v){
4991 var r = [], ri = -1, cn;
4992 for(var i = 0, ci; ci = c[i]; i++){
4993 if((' '+ci.className+' ').indexOf(v) != -1){
5000 function attrValue(n, attr){
5001 if(!n.tagName && typeof n.length != "undefined"){
5010 if(attr == "class" || attr == "className"){
5013 return n.getAttribute(attr) || n[attr];
5017 function getNodes(ns, mode, tagName){
5018 var result = [], ri = -1, cs;
5022 tagName = tagName || "*";
5023 if(typeof ns.getElementsByTagName != "undefined"){
5027 for(var i = 0, ni; ni = ns[i]; i++){
5028 cs = ni.getElementsByTagName(tagName);
5029 for(var j = 0, ci; ci = cs[j]; j++){
5033 }else if(mode == "/" || mode == ">"){
5034 var utag = tagName.toUpperCase();
5035 for(var i = 0, ni, cn; ni = ns[i]; i++){
5036 cn = ni.children || ni.childNodes;
5037 for(var j = 0, cj; cj = cn[j]; j++){
5038 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5043 }else if(mode == "+"){
5044 var utag = tagName.toUpperCase();
5045 for(var i = 0, n; n = ns[i]; i++){
5046 while((n = n.nextSibling) && n.nodeType != 1);
5047 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5051 }else if(mode == "~"){
5052 for(var i = 0, n; n = ns[i]; i++){
5053 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5062 function concat(a, b){
5066 for(var i = 0, l = b.length; i < l; i++){
5072 function byTag(cs, tagName){
5073 if(cs.tagName || cs == document){
5079 var r = [], ri = -1;
5080 tagName = tagName.toLowerCase();
5081 for(var i = 0, ci; ci = cs[i]; i++){
5082 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5089 function byId(cs, attr, id){
5090 if(cs.tagName || cs == document){
5096 var r = [], ri = -1;
5097 for(var i = 0,ci; ci = cs[i]; i++){
5098 if(ci && ci.id == id){
5106 function byAttribute(cs, attr, value, op, custom){
5107 var r = [], ri = -1, st = custom=="{";
5108 var f = Roo.DomQuery.operators[op];
5109 for(var i = 0, ci; ci = cs[i]; i++){
5112 a = Roo.DomQuery.getStyle(ci, attr);
5114 else if(attr == "class" || attr == "className"){
5116 }else if(attr == "for"){
5118 }else if(attr == "href"){
5119 a = ci.getAttribute("href", 2);
5121 a = ci.getAttribute(attr);
5123 if((f && f(a, value)) || (!f && a)){
5130 function byPseudo(cs, name, value){
5131 return Roo.DomQuery.pseudos[name](cs, value);
5134 // This is for IE MSXML which does not support expandos.
5135 // IE runs the same speed using setAttribute, however FF slows way down
5136 // and Safari completely fails so they need to continue to use expandos.
5137 var isIE = window.ActiveXObject ? true : false;
5139 // this eval is stop the compressor from
5140 // renaming the variable to something shorter
5142 /** eval:var:batch */
5147 function nodupIEXml(cs){
5149 cs[0].setAttribute("_nodup", d);
5151 for(var i = 1, len = cs.length; i < len; i++){
5153 if(!c.getAttribute("_nodup") != d){
5154 c.setAttribute("_nodup", d);
5158 for(var i = 0, len = cs.length; i < len; i++){
5159 cs[i].removeAttribute("_nodup");
5168 var len = cs.length, c, i, r = cs, cj, ri = -1;
5169 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5172 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5173 return nodupIEXml(cs);
5177 for(i = 1; c = cs[i]; i++){
5182 for(var j = 0; j < i; j++){
5185 for(j = i+1; cj = cs[j]; j++){
5197 function quickDiffIEXml(c1, c2){
5199 for(var i = 0, len = c1.length; i < len; i++){
5200 c1[i].setAttribute("_qdiff", d);
5203 for(var i = 0, len = c2.length; i < len; i++){
5204 if(c2[i].getAttribute("_qdiff") != d){
5205 r[r.length] = c2[i];
5208 for(var i = 0, len = c1.length; i < len; i++){
5209 c1[i].removeAttribute("_qdiff");
5214 function quickDiff(c1, c2){
5215 var len1 = c1.length;
5219 if(isIE && c1[0].selectSingleNode){
5220 return quickDiffIEXml(c1, c2);
5223 for(var i = 0; i < len1; i++){
5227 for(var i = 0, len = c2.length; i < len; i++){
5228 if(c2[i]._qdiff != d){
5229 r[r.length] = c2[i];
5235 function quickId(ns, mode, root, id){
5237 var d = root.ownerDocument || root;
5238 return d.getElementById(id);
5240 ns = getNodes(ns, mode, "*");
5241 return byId(ns, null, id);
5245 getStyle : function(el, name){
5246 return Roo.fly(el).getStyle(name);
5249 * Compiles a selector/xpath query into a reusable function. The returned function
5250 * takes one parameter "root" (optional), which is the context node from where the query should start.
5251 * @param {String} selector The selector/xpath query
5252 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5253 * @return {Function}
5255 compile : function(path, type){
5256 type = type || "select";
5258 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5259 var q = path, mode, lq;
5260 var tk = Roo.DomQuery.matchers;
5261 var tklen = tk.length;
5264 // accept leading mode switch
5265 var lmode = q.match(modeRe);
5266 if(lmode && lmode[1]){
5267 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5268 q = q.replace(lmode[1], "");
5270 // strip leading slashes
5271 while(path.substr(0, 1)=="/"){
5272 path = path.substr(1);
5275 while(q && lq != q){
5277 var tm = q.match(tagTokenRe);
5278 if(type == "select"){
5281 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5283 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5285 q = q.replace(tm[0], "");
5286 }else if(q.substr(0, 1) != '@'){
5287 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5292 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5294 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5296 q = q.replace(tm[0], "");
5299 while(!(mm = q.match(modeRe))){
5300 var matched = false;
5301 for(var j = 0; j < tklen; j++){
5303 var m = q.match(t.re);
5305 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5308 q = q.replace(m[0], "");
5313 // prevent infinite loop on bad selector
5315 throw 'Error parsing selector, parsing failed at "' + q + '"';
5319 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5320 q = q.replace(mm[1], "");
5323 fn[fn.length] = "return nodup(n);\n}";
5326 * list of variables that need from compression as they are used by eval.
5336 * eval:var:byClassName
5338 * eval:var:byAttribute
5339 * eval:var:attrValue
5347 * Selects a group of elements.
5348 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5349 * @param {Node} root (optional) The start of the query (defaults to document).
5352 select : function(path, root, type){
5353 if(!root || root == document){
5356 if(typeof root == "string"){
5357 root = document.getElementById(root);
5359 var paths = path.split(",");
5361 for(var i = 0, len = paths.length; i < len; i++){
5362 var p = paths[i].replace(trimRe, "");
5364 cache[p] = Roo.DomQuery.compile(p);
5366 throw p + " is not a valid selector";
5369 var result = cache[p](root);
5370 if(result && result != document){
5371 results = results.concat(result);
5374 if(paths.length > 1){
5375 return nodup(results);
5381 * Selects a single element.
5382 * @param {String} selector The selector/xpath query
5383 * @param {Node} root (optional) The start of the query (defaults to document).
5386 selectNode : function(path, root){
5387 return Roo.DomQuery.select(path, root)[0];
5391 * Selects the value of a node, optionally replacing null with the defaultValue.
5392 * @param {String} selector The selector/xpath query
5393 * @param {Node} root (optional) The start of the query (defaults to document).
5394 * @param {String} defaultValue
5396 selectValue : function(path, root, defaultValue){
5397 path = path.replace(trimRe, "");
5398 if(!valueCache[path]){
5399 valueCache[path] = Roo.DomQuery.compile(path, "select");
5401 var n = valueCache[path](root);
5402 n = n[0] ? n[0] : n;
5403 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5404 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5408 * Selects the value of a node, parsing integers and floats.
5409 * @param {String} selector The selector/xpath query
5410 * @param {Node} root (optional) The start of the query (defaults to document).
5411 * @param {Number} defaultValue
5414 selectNumber : function(path, root, defaultValue){
5415 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5416 return parseFloat(v);
5420 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5421 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5422 * @param {String} selector The simple selector to test
5425 is : function(el, ss){
5426 if(typeof el == "string"){
5427 el = document.getElementById(el);
5429 var isArray = (el instanceof Array);
5430 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5431 return isArray ? (result.length == el.length) : (result.length > 0);
5435 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5436 * @param {Array} el An array of elements to filter
5437 * @param {String} selector The simple selector to test
5438 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5439 * the selector instead of the ones that match
5442 filter : function(els, ss, nonMatches){
5443 ss = ss.replace(trimRe, "");
5444 if(!simpleCache[ss]){
5445 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5447 var result = simpleCache[ss](els);
5448 return nonMatches ? quickDiff(result, els) : result;
5452 * Collection of matching regular expressions and code snippets.
5456 select: 'n = byClassName(n, null, " {1} ");'
5458 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5459 select: 'n = byPseudo(n, "{1}", "{2}");'
5461 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5462 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5465 select: 'n = byId(n, null, "{1}");'
5468 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5473 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5474 * 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, > <.
5477 "=" : function(a, v){
5480 "!=" : function(a, v){
5483 "^=" : function(a, v){
5484 return a && a.substr(0, v.length) == v;
5486 "$=" : function(a, v){
5487 return a && a.substr(a.length-v.length) == v;
5489 "*=" : function(a, v){
5490 return a && a.indexOf(v) !== -1;
5492 "%=" : function(a, v){
5493 return (a % v) == 0;
5495 "|=" : function(a, v){
5496 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5498 "~=" : function(a, v){
5499 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5504 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5505 * and the argument (if any) supplied in the selector.
5508 "first-child" : function(c){
5509 var r = [], ri = -1, n;
5510 for(var i = 0, ci; ci = n = c[i]; i++){
5511 while((n = n.previousSibling) && n.nodeType != 1);
5519 "last-child" : function(c){
5520 var r = [], ri = -1, n;
5521 for(var i = 0, ci; ci = n = c[i]; i++){
5522 while((n = n.nextSibling) && n.nodeType != 1);
5530 "nth-child" : function(c, a) {
5531 var r = [], ri = -1;
5532 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5533 var f = (m[1] || 1) - 0, l = m[2] - 0;
5534 for(var i = 0, n; n = c[i]; i++){
5535 var pn = n.parentNode;
5536 if (batch != pn._batch) {
5538 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5539 if(cn.nodeType == 1){
5546 if (l == 0 || n.nodeIndex == l){
5549 } else if ((n.nodeIndex + l) % f == 0){
5557 "only-child" : function(c){
5558 var r = [], ri = -1;;
5559 for(var i = 0, ci; ci = c[i]; i++){
5560 if(!prev(ci) && !next(ci)){
5567 "empty" : function(c){
5568 var r = [], ri = -1;
5569 for(var i = 0, ci; ci = c[i]; i++){
5570 var cns = ci.childNodes, j = 0, cn, empty = true;
5573 if(cn.nodeType == 1 || cn.nodeType == 3){
5585 "contains" : function(c, v){
5586 var r = [], ri = -1;
5587 for(var i = 0, ci; ci = c[i]; i++){
5588 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5595 "nodeValue" : function(c, v){
5596 var r = [], ri = -1;
5597 for(var i = 0, ci; ci = c[i]; i++){
5598 if(ci.firstChild && ci.firstChild.nodeValue == v){
5605 "checked" : function(c){
5606 var r = [], ri = -1;
5607 for(var i = 0, ci; ci = c[i]; i++){
5608 if(ci.checked == true){
5615 "not" : function(c, ss){
5616 return Roo.DomQuery.filter(c, ss, true);
5619 "odd" : function(c){
5620 return this["nth-child"](c, "odd");
5623 "even" : function(c){
5624 return this["nth-child"](c, "even");
5627 "nth" : function(c, a){
5628 return c[a-1] || [];
5631 "first" : function(c){
5635 "last" : function(c){
5636 return c[c.length-1] || [];
5639 "has" : function(c, ss){
5640 var s = Roo.DomQuery.select;
5641 var r = [], ri = -1;
5642 for(var i = 0, ci; ci = c[i]; i++){
5643 if(s(ss, ci).length > 0){
5650 "next" : function(c, ss){
5651 var is = Roo.DomQuery.is;
5652 var r = [], ri = -1;
5653 for(var i = 0, ci; ci = c[i]; i++){
5662 "prev" : function(c, ss){
5663 var is = Roo.DomQuery.is;
5664 var r = [], ri = -1;
5665 for(var i = 0, ci; ci = c[i]; i++){
5678 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5679 * @param {String} path The selector/xpath query
5680 * @param {Node} root (optional) The start of the query (defaults to document).
5685 Roo.query = Roo.DomQuery.select;
5688 * Ext JS Library 1.1.1
5689 * Copyright(c) 2006-2007, Ext JS, LLC.
5691 * Originally Released Under LGPL - original licence link has changed is not relivant.
5694 * <script type="text/javascript">
5698 * @class Roo.util.Observable
5699 * Base class that provides a common interface for publishing events. Subclasses are expected to
5700 * to have a property "events" with all the events defined.<br>
5703 Employee = function(name){
5710 Roo.extend(Employee, Roo.util.Observable);
5712 * @param {Object} config properties to use (incuding events / listeners)
5715 Roo.util.Observable = function(cfg){
5718 this.addEvents(cfg.events || {});
5720 delete cfg.events; // make sure
5723 Roo.apply(this, cfg);
5726 this.on(this.listeners);
5727 delete this.listeners;
5730 Roo.util.Observable.prototype = {
5732 * @cfg {Object} listeners list of events and functions to call for this object,
5736 'click' : function(e) {
5746 * Fires the specified event with the passed parameters (minus the event name).
5747 * @param {String} eventName
5748 * @param {Object...} args Variable number of parameters are passed to handlers
5749 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5751 fireEvent : function(){
5752 var ce = this.events[arguments[0].toLowerCase()];
5753 if(typeof ce == "object"){
5754 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5761 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5764 * Appends an event handler to this component
5765 * @param {String} eventName The type of event to listen for
5766 * @param {Function} handler The method the event invokes
5767 * @param {Object} scope (optional) The scope in which to execute the handler
5768 * function. The handler function's "this" context.
5769 * @param {Object} options (optional) An object containing handler configuration
5770 * properties. This may contain any of the following properties:<ul>
5771 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5772 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5773 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5774 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5775 * by the specified number of milliseconds. If the event fires again within that time, the original
5776 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5779 * <b>Combining Options</b><br>
5780 * Using the options argument, it is possible to combine different types of listeners:<br>
5782 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5784 el.on('click', this.onClick, this, {
5791 * <b>Attaching multiple handlers in 1 call</b><br>
5792 * The method also allows for a single argument to be passed which is a config object containing properties
5793 * which specify multiple handlers.
5802 fn: this.onMouseOver,
5806 fn: this.onMouseOut,
5812 * Or a shorthand syntax which passes the same scope object to all handlers:
5815 'click': this.onClick,
5816 'mouseover': this.onMouseOver,
5817 'mouseout': this.onMouseOut,
5822 addListener : function(eventName, fn, scope, o){
5823 if(typeof eventName == "object"){
5826 if(this.filterOptRe.test(e)){
5829 if(typeof o[e] == "function"){
5831 this.addListener(e, o[e], o.scope, o);
5833 // individual options
5834 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5839 o = (!o || typeof o == "boolean") ? {} : o;
5840 eventName = eventName.toLowerCase();
5841 var ce = this.events[eventName] || true;
5842 if(typeof ce == "boolean"){
5843 ce = new Roo.util.Event(this, eventName);
5844 this.events[eventName] = ce;
5846 ce.addListener(fn, scope, o);
5850 * Removes a listener
5851 * @param {String} eventName The type of event to listen for
5852 * @param {Function} handler The handler to remove
5853 * @param {Object} scope (optional) The scope (this object) for the handler
5855 removeListener : function(eventName, fn, scope){
5856 var ce = this.events[eventName.toLowerCase()];
5857 if(typeof ce == "object"){
5858 ce.removeListener(fn, scope);
5863 * Removes all listeners for this object
5865 purgeListeners : function(){
5866 for(var evt in this.events){
5867 if(typeof this.events[evt] == "object"){
5868 this.events[evt].clearListeners();
5873 relayEvents : function(o, events){
5874 var createHandler = function(ename){
5876 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5879 for(var i = 0, len = events.length; i < len; i++){
5880 var ename = events[i];
5881 if(!this.events[ename]){ this.events[ename] = true; };
5882 o.on(ename, createHandler(ename), this);
5887 * Used to define events on this Observable
5888 * @param {Object} object The object with the events defined
5890 addEvents : function(o){
5894 Roo.applyIf(this.events, o);
5898 * Checks to see if this object has any listeners for a specified event
5899 * @param {String} eventName The name of the event to check for
5900 * @return {Boolean} True if the event is being listened for, else false
5902 hasListener : function(eventName){
5903 var e = this.events[eventName];
5904 return typeof e == "object" && e.listeners.length > 0;
5908 * Appends an event handler to this element (shorthand for addListener)
5909 * @param {String} eventName The type of event to listen for
5910 * @param {Function} handler The method the event invokes
5911 * @param {Object} scope (optional) The scope in which to execute the handler
5912 * function. The handler function's "this" context.
5913 * @param {Object} options (optional)
5916 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5918 * Removes a listener (shorthand for removeListener)
5919 * @param {String} eventName The type of event to listen for
5920 * @param {Function} handler The handler to remove
5921 * @param {Object} scope (optional) The scope (this object) for the handler
5924 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5927 * Starts capture on the specified Observable. All events will be passed
5928 * to the supplied function with the event name + standard signature of the event
5929 * <b>before</b> the event is fired. If the supplied function returns false,
5930 * the event will not fire.
5931 * @param {Observable} o The Observable to capture
5932 * @param {Function} fn The function to call
5933 * @param {Object} scope (optional) The scope (this object) for the fn
5936 Roo.util.Observable.capture = function(o, fn, scope){
5937 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5941 * Removes <b>all</b> added captures from the Observable.
5942 * @param {Observable} o The Observable to release
5945 Roo.util.Observable.releaseCapture = function(o){
5946 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5951 var createBuffered = function(h, o, scope){
5952 var task = new Roo.util.DelayedTask();
5954 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5958 var createSingle = function(h, e, fn, scope){
5960 e.removeListener(fn, scope);
5961 return h.apply(scope, arguments);
5965 var createDelayed = function(h, o, scope){
5967 var args = Array.prototype.slice.call(arguments, 0);
5968 setTimeout(function(){
5969 h.apply(scope, args);
5974 Roo.util.Event = function(obj, name){
5977 this.listeners = [];
5980 Roo.util.Event.prototype = {
5981 addListener : function(fn, scope, options){
5982 var o = options || {};
5983 scope = scope || this.obj;
5984 if(!this.isListening(fn, scope)){
5985 var l = {fn: fn, scope: scope, options: o};
5988 h = createDelayed(h, o, scope);
5991 h = createSingle(h, this, fn, scope);
5994 h = createBuffered(h, o, scope);
5997 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5998 this.listeners.push(l);
6000 this.listeners = this.listeners.slice(0);
6001 this.listeners.push(l);
6006 findListener : function(fn, scope){
6007 scope = scope || this.obj;
6008 var ls = this.listeners;
6009 for(var i = 0, len = ls.length; i < len; i++){
6011 if(l.fn == fn && l.scope == scope){
6018 isListening : function(fn, scope){
6019 return this.findListener(fn, scope) != -1;
6022 removeListener : function(fn, scope){
6024 if((index = this.findListener(fn, scope)) != -1){
6026 this.listeners.splice(index, 1);
6028 this.listeners = this.listeners.slice(0);
6029 this.listeners.splice(index, 1);
6036 clearListeners : function(){
6037 this.listeners = [];
6041 var ls = this.listeners, scope, len = ls.length;
6044 var args = Array.prototype.slice.call(arguments, 0);
6045 for(var i = 0; i < len; i++){
6047 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6048 this.firing = false;
6052 this.firing = false;
6059 * Copyright(c) 2007-2017, Roo J Solutions Ltd
6066 * @class Roo.Document
6067 * @extends Roo.util.Observable
6068 * This is a convience class to wrap up the main document loading code.. , rather than adding Roo.onReady(......)
6070 * @param {Object} config the methods and properties of the 'base' class for the application.
6072 * Generic Page handler - implement this to start your app..
6075 * MyProject = new Roo.Document({
6077 'load' : true // your events..
6080 'ready' : function() {
6081 // fired on Roo.onReady()
6086 Roo.Document = function(cfg) {
6091 Roo.util.Observable.call(this,cfg);
6095 Roo.onReady(function() {
6096 _this.fireEvent('ready');
6102 Roo.extend(Roo.Document, Roo.util.Observable, {});/*
6104 * Ext JS Library 1.1.1
6105 * Copyright(c) 2006-2007, Ext JS, LLC.
6107 * Originally Released Under LGPL - original licence link has changed is not relivant.
6110 * <script type="text/javascript">
6114 * @class Roo.EventManager
6115 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6116 * several useful events directly.
6117 * See {@link Roo.EventObject} for more details on normalized event objects.
6120 Roo.EventManager = function(){
6121 var docReadyEvent, docReadyProcId, docReadyState = false;
6122 var resizeEvent, resizeTask, textEvent, textSize;
6123 var E = Roo.lib.Event;
6124 var D = Roo.lib.Dom;
6129 var fireDocReady = function(){
6131 docReadyState = true;
6134 clearInterval(docReadyProcId);
6136 if(Roo.isGecko || Roo.isOpera) {
6137 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6140 var defer = document.getElementById("ie-deferred-loader");
6142 defer.onreadystatechange = null;
6143 defer.parentNode.removeChild(defer);
6147 docReadyEvent.fire();
6148 docReadyEvent.clearListeners();
6153 var initDocReady = function(){
6154 docReadyEvent = new Roo.util.Event();
6155 if(Roo.isGecko || Roo.isOpera) {
6156 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6158 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6159 var defer = document.getElementById("ie-deferred-loader");
6160 defer.onreadystatechange = function(){
6161 if(this.readyState == "complete"){
6165 }else if(Roo.isSafari){
6166 docReadyProcId = setInterval(function(){
6167 var rs = document.readyState;
6168 if(rs == "complete") {
6173 // no matter what, make sure it fires on load
6174 E.on(window, "load", fireDocReady);
6177 var createBuffered = function(h, o){
6178 var task = new Roo.util.DelayedTask(h);
6180 // create new event object impl so new events don't wipe out properties
6181 e = new Roo.EventObjectImpl(e);
6182 task.delay(o.buffer, h, null, [e]);
6186 var createSingle = function(h, el, ename, fn){
6188 Roo.EventManager.removeListener(el, ename, fn);
6193 var createDelayed = function(h, o){
6195 // create new event object impl so new events don't wipe out properties
6196 e = new Roo.EventObjectImpl(e);
6197 setTimeout(function(){
6202 var transitionEndVal = false;
6204 var transitionEnd = function()
6206 if (transitionEndVal) {
6207 return transitionEndVal;
6209 var el = document.createElement('div');
6211 var transEndEventNames = {
6212 WebkitTransition : 'webkitTransitionEnd',
6213 MozTransition : 'transitionend',
6214 OTransition : 'oTransitionEnd otransitionend',
6215 transition : 'transitionend'
6218 for (var name in transEndEventNames) {
6219 if (el.style[name] !== undefined) {
6220 transitionEndVal = transEndEventNames[name];
6221 return transitionEndVal ;
6227 var listen = function(element, ename, opt, fn, scope){
6228 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6229 fn = fn || o.fn; scope = scope || o.scope;
6230 var el = Roo.getDom(element);
6234 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6237 if (ename == 'transitionend') {
6238 ename = transitionEnd();
6240 var h = function(e){
6241 e = Roo.EventObject.setEvent(e);
6244 t = e.getTarget(o.delegate, el);
6251 if(o.stopEvent === true){
6254 if(o.preventDefault === true){
6257 if(o.stopPropagation === true){
6258 e.stopPropagation();
6261 if(o.normalized === false){
6265 fn.call(scope || el, e, t, o);
6268 h = createDelayed(h, o);
6271 h = createSingle(h, el, ename, fn);
6274 h = createBuffered(h, o);
6276 fn._handlers = fn._handlers || [];
6279 fn._handlers.push([Roo.id(el), ename, h]);
6284 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6285 el.addEventListener("DOMMouseScroll", h, false);
6286 E.on(window, 'unload', function(){
6287 el.removeEventListener("DOMMouseScroll", h, false);
6290 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6291 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6296 var stopListening = function(el, ename, fn){
6297 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6299 for(var i = 0, len = hds.length; i < len; i++){
6301 if(h[0] == id && h[1] == ename){
6308 E.un(el, ename, hd);
6309 el = Roo.getDom(el);
6310 if(ename == "mousewheel" && el.addEventListener){
6311 el.removeEventListener("DOMMouseScroll", hd, false);
6313 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6314 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6318 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6325 * @scope Roo.EventManager
6330 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6331 * object with a Roo.EventObject
6332 * @param {Function} fn The method the event invokes
6333 * @param {Object} scope An object that becomes the scope of the handler
6334 * @param {boolean} override If true, the obj passed in becomes
6335 * the execution scope of the listener
6336 * @return {Function} The wrapped function
6339 wrap : function(fn, scope, override){
6341 Roo.EventObject.setEvent(e);
6342 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6347 * Appends an event handler to an element (shorthand for addListener)
6348 * @param {String/HTMLElement} element The html element or id to assign the
6349 * @param {String} eventName The type of event to listen for
6350 * @param {Function} handler The method the event invokes
6351 * @param {Object} scope (optional) The scope in which to execute the handler
6352 * function. The handler function's "this" context.
6353 * @param {Object} options (optional) An object containing handler configuration
6354 * properties. This may contain any of the following properties:<ul>
6355 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6356 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6357 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6358 * <li>preventDefault {Boolean} True to prevent the default action</li>
6359 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6360 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6361 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6362 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6363 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6364 * by the specified number of milliseconds. If the event fires again within that time, the original
6365 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6368 * <b>Combining Options</b><br>
6369 * Using the options argument, it is possible to combine different types of listeners:<br>
6371 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6373 el.on('click', this.onClick, this, {
6380 * <b>Attaching multiple handlers in 1 call</b><br>
6381 * The method also allows for a single argument to be passed which is a config object containing properties
6382 * which specify multiple handlers.
6392 fn: this.onMouseOver
6401 * Or a shorthand syntax:<br>
6404 'click' : this.onClick,
6405 'mouseover' : this.onMouseOver,
6406 'mouseout' : this.onMouseOut
6410 addListener : function(element, eventName, fn, scope, options){
6411 if(typeof eventName == "object"){
6417 if(typeof o[e] == "function"){
6419 listen(element, e, o, o[e], o.scope);
6421 // individual options
6422 listen(element, e, o[e]);
6427 return listen(element, eventName, options, fn, scope);
6431 * Removes an event handler
6433 * @param {String/HTMLElement} element The id or html element to remove the
6435 * @param {String} eventName The type of event
6436 * @param {Function} fn
6437 * @return {Boolean} True if a listener was actually removed
6439 removeListener : function(element, eventName, fn){
6440 return stopListening(element, eventName, fn);
6444 * Fires when the document is ready (before onload and before images are loaded). Can be
6445 * accessed shorthanded Roo.onReady().
6446 * @param {Function} fn The method the event invokes
6447 * @param {Object} scope An object that becomes the scope of the handler
6448 * @param {boolean} options
6450 onDocumentReady : function(fn, scope, options){
6451 if(docReadyState){ // if it already fired
6452 docReadyEvent.addListener(fn, scope, options);
6453 docReadyEvent.fire();
6454 docReadyEvent.clearListeners();
6460 docReadyEvent.addListener(fn, scope, options);
6464 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6465 * @param {Function} fn The method the event invokes
6466 * @param {Object} scope An object that becomes the scope of the handler
6467 * @param {boolean} options
6469 onWindowResize : function(fn, scope, options){
6471 resizeEvent = new Roo.util.Event();
6472 resizeTask = new Roo.util.DelayedTask(function(){
6473 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6475 E.on(window, "resize", function(){
6477 resizeTask.delay(50);
6479 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6483 resizeEvent.addListener(fn, scope, options);
6487 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6488 * @param {Function} fn The method the event invokes
6489 * @param {Object} scope An object that becomes the scope of the handler
6490 * @param {boolean} options
6492 onTextResize : function(fn, scope, options){
6494 textEvent = new Roo.util.Event();
6495 var textEl = new Roo.Element(document.createElement('div'));
6496 textEl.dom.className = 'x-text-resize';
6497 textEl.dom.innerHTML = 'X';
6498 textEl.appendTo(document.body);
6499 textSize = textEl.dom.offsetHeight;
6500 setInterval(function(){
6501 if(textEl.dom.offsetHeight != textSize){
6502 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6504 }, this.textResizeInterval);
6506 textEvent.addListener(fn, scope, options);
6510 * Removes the passed window resize listener.
6511 * @param {Function} fn The method the event invokes
6512 * @param {Object} scope The scope of handler
6514 removeResizeListener : function(fn, scope){
6516 resizeEvent.removeListener(fn, scope);
6521 fireResize : function(){
6523 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6527 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6531 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6533 textResizeInterval : 50
6538 * @scopeAlias pub=Roo.EventManager
6542 * Appends an event handler to an element (shorthand for addListener)
6543 * @param {String/HTMLElement} element The html element or id to assign the
6544 * @param {String} eventName The type of event to listen for
6545 * @param {Function} handler The method the event invokes
6546 * @param {Object} scope (optional) The scope in which to execute the handler
6547 * function. The handler function's "this" context.
6548 * @param {Object} options (optional) An object containing handler configuration
6549 * properties. This may contain any of the following properties:<ul>
6550 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6551 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6552 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6553 * <li>preventDefault {Boolean} True to prevent the default action</li>
6554 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6555 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6556 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6557 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6558 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6559 * by the specified number of milliseconds. If the event fires again within that time, the original
6560 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6563 * <b>Combining Options</b><br>
6564 * Using the options argument, it is possible to combine different types of listeners:<br>
6566 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6568 el.on('click', this.onClick, this, {
6575 * <b>Attaching multiple handlers in 1 call</b><br>
6576 * The method also allows for a single argument to be passed which is a config object containing properties
6577 * which specify multiple handlers.
6587 fn: this.onMouseOver
6596 * Or a shorthand syntax:<br>
6599 'click' : this.onClick,
6600 'mouseover' : this.onMouseOver,
6601 'mouseout' : this.onMouseOut
6605 pub.on = pub.addListener;
6606 pub.un = pub.removeListener;
6608 pub.stoppedMouseDownEvent = new Roo.util.Event();
6612 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6613 * @param {Function} fn The method the event invokes
6614 * @param {Object} scope An object that becomes the scope of the handler
6615 * @param {boolean} override If true, the obj passed in becomes
6616 * the execution scope of the listener
6620 Roo.onReady = Roo.EventManager.onDocumentReady;
6622 Roo.onReady(function(){
6623 var bd = Roo.get(document.body);
6628 : Roo.isGecko ? "roo-gecko"
6629 : Roo.isOpera ? "roo-opera"
6630 : Roo.isSafari ? "roo-safari" : ""];
6633 cls.push("roo-mac");
6636 cls.push("roo-linux");
6639 cls.push("roo-ios");
6642 cls.push("roo-touch");
6644 if(Roo.isBorderBox){
6645 cls.push('roo-border-box');
6647 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6648 var p = bd.dom.parentNode;
6650 p.className += ' roo-strict';
6653 bd.addClass(cls.join(' '));
6657 * @class Roo.EventObject
6658 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6659 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6662 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6664 var target = e.getTarget();
6667 var myDiv = Roo.get("myDiv");
6668 myDiv.on("click", handleClick);
6670 Roo.EventManager.on("myDiv", 'click', handleClick);
6671 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6675 Roo.EventObject = function(){
6677 var E = Roo.lib.Event;
6679 // safari keypress events for special keys return bad keycodes
6682 63235 : 39, // right
6685 63276 : 33, // page up
6686 63277 : 34, // page down
6687 63272 : 46, // delete
6692 // normalize button clicks
6693 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6694 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6696 Roo.EventObjectImpl = function(e){
6698 this.setEvent(e.browserEvent || e);
6701 Roo.EventObjectImpl.prototype = {
6703 * Used to fix doc tools.
6704 * @scope Roo.EventObject.prototype
6710 /** The normal browser event */
6711 browserEvent : null,
6712 /** The button pressed in a mouse event */
6714 /** True if the shift key was down during the event */
6716 /** True if the control key was down during the event */
6718 /** True if the alt key was down during the event */
6780 setEvent : function(e){
6781 if(e == this || (e && e.browserEvent)){ // already wrapped
6784 this.browserEvent = e;
6786 // normalize buttons
6787 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6788 if(e.type == 'click' && this.button == -1){
6792 this.shiftKey = e.shiftKey;
6793 // mac metaKey behaves like ctrlKey
6794 this.ctrlKey = e.ctrlKey || e.metaKey;
6795 this.altKey = e.altKey;
6796 // in getKey these will be normalized for the mac
6797 this.keyCode = e.keyCode;
6798 // keyup warnings on firefox.
6799 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6800 // cache the target for the delayed and or buffered events
6801 this.target = E.getTarget(e);
6803 this.xy = E.getXY(e);
6806 this.shiftKey = false;
6807 this.ctrlKey = false;
6808 this.altKey = false;
6818 * Stop the event (preventDefault and stopPropagation)
6820 stopEvent : function(){
6821 if(this.browserEvent){
6822 if(this.browserEvent.type == 'mousedown'){
6823 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6825 E.stopEvent(this.browserEvent);
6830 * Prevents the browsers default handling of the event.
6832 preventDefault : function(){
6833 if(this.browserEvent){
6834 E.preventDefault(this.browserEvent);
6839 isNavKeyPress : function(){
6840 var k = this.keyCode;
6841 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6842 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6845 isSpecialKey : function(){
6846 var k = this.keyCode;
6847 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6848 (k == 16) || (k == 17) ||
6849 (k >= 18 && k <= 20) ||
6850 (k >= 33 && k <= 35) ||
6851 (k >= 36 && k <= 39) ||
6852 (k >= 44 && k <= 45);
6855 * Cancels bubbling of the event.
6857 stopPropagation : function(){
6858 if(this.browserEvent){
6859 if(this.type == 'mousedown'){
6860 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6862 E.stopPropagation(this.browserEvent);
6867 * Gets the key code for the event.
6870 getCharCode : function(){
6871 return this.charCode || this.keyCode;
6875 * Returns a normalized keyCode for the event.
6876 * @return {Number} The key code
6878 getKey : function(){
6879 var k = this.keyCode || this.charCode;
6880 return Roo.isSafari ? (safariKeys[k] || k) : k;
6884 * Gets the x coordinate of the event.
6887 getPageX : function(){
6892 * Gets the y coordinate of the event.
6895 getPageY : function(){
6900 * Gets the time of the event.
6903 getTime : function(){
6904 if(this.browserEvent){
6905 return E.getTime(this.browserEvent);
6911 * Gets the page coordinates of the event.
6912 * @return {Array} The xy values like [x, y]
6919 * Gets the target for the event.
6920 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6921 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6922 search as a number or element (defaults to 10 || document.body)
6923 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6924 * @return {HTMLelement}
6926 getTarget : function(selector, maxDepth, returnEl){
6927 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6930 * Gets the related target.
6931 * @return {HTMLElement}
6933 getRelatedTarget : function(){
6934 if(this.browserEvent){
6935 return E.getRelatedTarget(this.browserEvent);
6941 * Normalizes mouse wheel delta across browsers
6942 * @return {Number} The delta
6944 getWheelDelta : function(){
6945 var e = this.browserEvent;
6947 if(e.wheelDelta){ /* IE/Opera. */
6948 delta = e.wheelDelta/120;
6949 }else if(e.detail){ /* Mozilla case. */
6950 delta = -e.detail/3;
6956 * Returns true if the control, meta, shift or alt key was pressed during this event.
6959 hasModifier : function(){
6960 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6964 * Returns true if the target of this event equals el or is a child of el
6965 * @param {String/HTMLElement/Element} el
6966 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6969 within : function(el, related){
6970 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6971 return t && Roo.fly(el).contains(t);
6974 getPoint : function(){
6975 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6979 return new Roo.EventObjectImpl();
6984 * Ext JS Library 1.1.1
6985 * Copyright(c) 2006-2007, Ext JS, LLC.
6987 * Originally Released Under LGPL - original licence link has changed is not relivant.
6990 * <script type="text/javascript">
6994 // was in Composite Element!??!?!
6997 var D = Roo.lib.Dom;
6998 var E = Roo.lib.Event;
6999 var A = Roo.lib.Anim;
7001 // local style camelizing for speed
7003 var camelRe = /(-[a-z])/gi;
7004 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
7005 var view = document.defaultView;
7008 * @class Roo.Element
7009 * Represents an Element in the DOM.<br><br>
7012 var el = Roo.get("my-div");
7015 var el = getEl("my-div");
7017 // or with a DOM element
7018 var el = Roo.get(myDivElement);
7020 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
7021 * each call instead of constructing a new one.<br><br>
7022 * <b>Animations</b><br />
7023 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
7024 * should either be a boolean (true) or an object literal with animation options. The animation options are:
7026 Option Default Description
7027 --------- -------- ---------------------------------------------
7028 duration .35 The duration of the animation in seconds
7029 easing easeOut The YUI easing method
7030 callback none A function to execute when the anim completes
7031 scope this The scope (this) of the callback function
7033 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
7034 * manipulate the animation. Here's an example:
7036 var el = Roo.get("my-div");
7041 // default animation
7042 el.setWidth(100, true);
7044 // animation with some options set
7051 // using the "anim" property to get the Anim object
7057 el.setWidth(100, opt);
7059 if(opt.anim.isAnimated()){
7063 * <b> Composite (Collections of) Elements</b><br />
7064 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
7065 * @constructor Create a new Element directly.
7066 * @param {String/HTMLElement} element
7067 * @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).
7069 Roo.Element = function(element, forceNew){
7070 var dom = typeof element == "string" ?
7071 document.getElementById(element) : element;
7072 if(!dom){ // invalid id/element
7076 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7077 return Roo.Element.cache[id];
7087 * The DOM element ID
7090 this.id = id || Roo.id(dom);
7093 var El = Roo.Element;
7097 * The element's default display mode (defaults to "")
7100 originalDisplay : "",
7104 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7110 * Sets the element's visibility mode. When setVisible() is called it
7111 * will use this to determine whether to set the visibility or the display property.
7112 * @param visMode Element.VISIBILITY or Element.DISPLAY
7113 * @return {Roo.Element} this
7115 setVisibilityMode : function(visMode){
7116 this.visibilityMode = visMode;
7120 * Convenience method for setVisibilityMode(Element.DISPLAY)
7121 * @param {String} display (optional) What to set display to when visible
7122 * @return {Roo.Element} this
7124 enableDisplayMode : function(display){
7125 this.setVisibilityMode(El.DISPLAY);
7126 if(typeof display != "undefined") { this.originalDisplay = display; }
7131 * 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)
7132 * @param {String} selector The simple selector to test
7133 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7134 search as a number or element (defaults to 10 || document.body)
7135 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7136 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7138 findParent : function(simpleSelector, maxDepth, returnEl){
7139 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7140 maxDepth = maxDepth || 50;
7141 if(typeof maxDepth != "number"){
7142 stopEl = Roo.getDom(maxDepth);
7145 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7146 if(dq.is(p, simpleSelector)){
7147 return returnEl ? Roo.get(p) : p;
7157 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7158 * @param {String} selector The simple selector to test
7159 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7160 search as a number or element (defaults to 10 || document.body)
7161 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7162 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7164 findParentNode : function(simpleSelector, maxDepth, returnEl){
7165 var p = Roo.fly(this.dom.parentNode, '_internal');
7166 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7170 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7171 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7172 * @param {String} selector The simple selector to test
7173 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7174 search as a number or element (defaults to 10 || document.body)
7175 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7177 up : function(simpleSelector, maxDepth){
7178 return this.findParentNode(simpleSelector, maxDepth, true);
7184 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7185 * @param {String} selector The simple selector to test
7186 * @return {Boolean} True if this element matches the selector, else false
7188 is : function(simpleSelector){
7189 return Roo.DomQuery.is(this.dom, simpleSelector);
7193 * Perform animation on this element.
7194 * @param {Object} args The YUI animation control args
7195 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7196 * @param {Function} onComplete (optional) Function to call when animation completes
7197 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7198 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7199 * @return {Roo.Element} this
7201 animate : function(args, duration, onComplete, easing, animType){
7202 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7207 * @private Internal animation call
7209 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7210 animType = animType || 'run';
7212 var anim = Roo.lib.Anim[animType](
7214 (opt.duration || defaultDur) || .35,
7215 (opt.easing || defaultEase) || 'easeOut',
7217 Roo.callback(cb, this);
7218 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7226 // private legacy anim prep
7227 preanim : function(a, i){
7228 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7232 * Removes worthless text nodes
7233 * @param {Boolean} forceReclean (optional) By default the element
7234 * keeps track if it has been cleaned already so
7235 * you can call this over and over. However, if you update the element and
7236 * need to force a reclean, you can pass true.
7238 clean : function(forceReclean){
7239 if(this.isCleaned && forceReclean !== true){
7243 var d = this.dom, n = d.firstChild, ni = -1;
7245 var nx = n.nextSibling;
7246 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7253 this.isCleaned = true;
7258 calcOffsetsTo : function(el){
7261 var restorePos = false;
7262 if(el.getStyle('position') == 'static'){
7263 el.position('relative');
7268 while(op && op != d && op.tagName != 'HTML'){
7271 op = op.offsetParent;
7274 el.position('static');
7280 * Scrolls this element into view within the passed container.
7281 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7282 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7283 * @return {Roo.Element} this
7285 scrollIntoView : function(container, hscroll){
7286 var c = Roo.getDom(container) || document.body;
7289 var o = this.calcOffsetsTo(c),
7292 b = t+el.offsetHeight,
7293 r = l+el.offsetWidth;
7295 var ch = c.clientHeight;
7296 var ct = parseInt(c.scrollTop, 10);
7297 var cl = parseInt(c.scrollLeft, 10);
7299 var cr = cl + c.clientWidth;
7307 if(hscroll !== false){
7311 c.scrollLeft = r-c.clientWidth;
7318 scrollChildIntoView : function(child, hscroll){
7319 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7323 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7324 * the new height may not be available immediately.
7325 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7326 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7327 * @param {Function} onComplete (optional) Function to call when animation completes
7328 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7329 * @return {Roo.Element} this
7331 autoHeight : function(animate, duration, onComplete, easing){
7332 var oldHeight = this.getHeight();
7334 this.setHeight(1); // force clipping
7335 setTimeout(function(){
7336 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7338 this.setHeight(height);
7340 if(typeof onComplete == "function"){
7344 this.setHeight(oldHeight); // restore original height
7345 this.setHeight(height, animate, duration, function(){
7347 if(typeof onComplete == "function") { onComplete(); }
7348 }.createDelegate(this), easing);
7350 }.createDelegate(this), 0);
7355 * Returns true if this element is an ancestor of the passed element
7356 * @param {HTMLElement/String} el The element to check
7357 * @return {Boolean} True if this element is an ancestor of el, else false
7359 contains : function(el){
7360 if(!el){return false;}
7361 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7365 * Checks whether the element is currently visible using both visibility and display properties.
7366 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7367 * @return {Boolean} True if the element is currently visible, else false
7369 isVisible : function(deep) {
7370 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7371 if(deep !== true || !vis){
7374 var p = this.dom.parentNode;
7375 while(p && p.tagName.toLowerCase() != "body"){
7376 if(!Roo.fly(p, '_isVisible').isVisible()){
7385 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7386 * @param {String} selector The CSS selector
7387 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7388 * @return {CompositeElement/CompositeElementLite} The composite element
7390 select : function(selector, unique){
7391 return El.select(selector, unique, this.dom);
7395 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7396 * @param {String} selector The CSS selector
7397 * @return {Array} An array of the matched nodes
7399 query : function(selector, unique){
7400 return Roo.DomQuery.select(selector, this.dom);
7404 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7405 * @param {String} selector The CSS selector
7406 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7407 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7409 child : function(selector, returnDom){
7410 var n = Roo.DomQuery.selectNode(selector, this.dom);
7411 return returnDom ? n : Roo.get(n);
7415 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7416 * @param {String} selector The CSS selector
7417 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7418 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7420 down : function(selector, returnDom){
7421 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7422 return returnDom ? n : Roo.get(n);
7426 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7427 * @param {String} group The group the DD object is member of
7428 * @param {Object} config The DD config object
7429 * @param {Object} overrides An object containing methods to override/implement on the DD object
7430 * @return {Roo.dd.DD} The DD object
7432 initDD : function(group, config, overrides){
7433 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7434 return Roo.apply(dd, overrides);
7438 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7439 * @param {String} group The group the DDProxy object is member of
7440 * @param {Object} config The DDProxy config object
7441 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7442 * @return {Roo.dd.DDProxy} The DDProxy object
7444 initDDProxy : function(group, config, overrides){
7445 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7446 return Roo.apply(dd, overrides);
7450 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7451 * @param {String} group The group the DDTarget object is member of
7452 * @param {Object} config The DDTarget config object
7453 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7454 * @return {Roo.dd.DDTarget} The DDTarget object
7456 initDDTarget : function(group, config, overrides){
7457 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7458 return Roo.apply(dd, overrides);
7462 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7463 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7464 * @param {Boolean} visible Whether the element is visible
7465 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7466 * @return {Roo.Element} this
7468 setVisible : function(visible, animate){
7470 if(this.visibilityMode == El.DISPLAY){
7471 this.setDisplayed(visible);
7474 this.dom.style.visibility = visible ? "visible" : "hidden";
7477 // closure for composites
7479 var visMode = this.visibilityMode;
7481 this.setOpacity(.01);
7482 this.setVisible(true);
7484 this.anim({opacity: { to: (visible?1:0) }},
7485 this.preanim(arguments, 1),
7486 null, .35, 'easeIn', function(){
7488 if(visMode == El.DISPLAY){
7489 dom.style.display = "none";
7491 dom.style.visibility = "hidden";
7493 Roo.get(dom).setOpacity(1);
7501 * Returns true if display is not "none"
7504 isDisplayed : function() {
7505 return this.getStyle("display") != "none";
7509 * Toggles the element's visibility or display, depending on visibility mode.
7510 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7511 * @return {Roo.Element} this
7513 toggle : function(animate){
7514 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7519 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7520 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7521 * @return {Roo.Element} this
7523 setDisplayed : function(value) {
7524 if(typeof value == "boolean"){
7525 value = value ? this.originalDisplay : "none";
7527 this.setStyle("display", value);
7532 * Tries to focus the element. Any exceptions are caught and ignored.
7533 * @return {Roo.Element} this
7535 focus : function() {
7543 * Tries to blur the element. Any exceptions are caught and ignored.
7544 * @return {Roo.Element} this
7554 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7555 * @param {String/Array} className The CSS class to add, or an array of classes
7556 * @return {Roo.Element} this
7558 addClass : function(className){
7559 if(className instanceof Array){
7560 for(var i = 0, len = className.length; i < len; i++) {
7561 this.addClass(className[i]);
7564 if(className && !this.hasClass(className)){
7565 this.dom.className = this.dom.className + " " + className;
7572 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7573 * @param {String/Array} className The CSS class to add, or an array of classes
7574 * @return {Roo.Element} this
7576 radioClass : function(className){
7577 var siblings = this.dom.parentNode.childNodes;
7578 for(var i = 0; i < siblings.length; i++) {
7579 var s = siblings[i];
7580 if(s.nodeType == 1){
7581 Roo.get(s).removeClass(className);
7584 this.addClass(className);
7589 * Removes one or more CSS classes from the element.
7590 * @param {String/Array} className The CSS class to remove, or an array of classes
7591 * @return {Roo.Element} this
7593 removeClass : function(className){
7594 if(!className || !this.dom.className){
7597 if(className instanceof Array){
7598 for(var i = 0, len = className.length; i < len; i++) {
7599 this.removeClass(className[i]);
7602 if(this.hasClass(className)){
7603 var re = this.classReCache[className];
7605 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7606 this.classReCache[className] = re;
7608 this.dom.className =
7609 this.dom.className.replace(re, " ");
7619 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7620 * @param {String} className The CSS class to toggle
7621 * @return {Roo.Element} this
7623 toggleClass : function(className){
7624 if(this.hasClass(className)){
7625 this.removeClass(className);
7627 this.addClass(className);
7633 * Checks if the specified CSS class exists on this element's DOM node.
7634 * @param {String} className The CSS class to check for
7635 * @return {Boolean} True if the class exists, else false
7637 hasClass : function(className){
7638 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7642 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7643 * @param {String} oldClassName The CSS class to replace
7644 * @param {String} newClassName The replacement CSS class
7645 * @return {Roo.Element} this
7647 replaceClass : function(oldClassName, newClassName){
7648 this.removeClass(oldClassName);
7649 this.addClass(newClassName);
7654 * Returns an object with properties matching the styles requested.
7655 * For example, el.getStyles('color', 'font-size', 'width') might return
7656 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7657 * @param {String} style1 A style name
7658 * @param {String} style2 A style name
7659 * @param {String} etc.
7660 * @return {Object} The style object
7662 getStyles : function(){
7663 var a = arguments, len = a.length, r = {};
7664 for(var i = 0; i < len; i++){
7665 r[a[i]] = this.getStyle(a[i]);
7671 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7672 * @param {String} property The style property whose value is returned.
7673 * @return {String} The current value of the style property for this element.
7675 getStyle : function(){
7676 return view && view.getComputedStyle ?
7678 var el = this.dom, v, cs, camel;
7679 if(prop == 'float'){
7682 if(el.style && (v = el.style[prop])){
7685 if(cs = view.getComputedStyle(el, "")){
7686 if(!(camel = propCache[prop])){
7687 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7694 var el = this.dom, v, cs, camel;
7695 if(prop == 'opacity'){
7696 if(typeof el.style.filter == 'string'){
7697 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7699 var fv = parseFloat(m[1]);
7701 return fv ? fv / 100 : 0;
7706 }else if(prop == 'float'){
7707 prop = "styleFloat";
7709 if(!(camel = propCache[prop])){
7710 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7712 if(v = el.style[camel]){
7715 if(cs = el.currentStyle){
7723 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7724 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7725 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7726 * @return {Roo.Element} this
7728 setStyle : function(prop, value){
7729 if(typeof prop == "string"){
7731 if (prop == 'float') {
7732 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7737 if(!(camel = propCache[prop])){
7738 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7741 if(camel == 'opacity') {
7742 this.setOpacity(value);
7744 this.dom.style[camel] = value;
7747 for(var style in prop){
7748 if(typeof prop[style] != "function"){
7749 this.setStyle(style, prop[style]);
7757 * More flexible version of {@link #setStyle} for setting style properties.
7758 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7759 * a function which returns such a specification.
7760 * @return {Roo.Element} this
7762 applyStyles : function(style){
7763 Roo.DomHelper.applyStyles(this.dom, style);
7768 * 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).
7769 * @return {Number} The X position of the element
7772 return D.getX(this.dom);
7776 * 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).
7777 * @return {Number} The Y position of the element
7780 return D.getY(this.dom);
7784 * 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).
7785 * @return {Array} The XY position of the element
7788 return D.getXY(this.dom);
7792 * 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).
7793 * @param {Number} The X position of the element
7794 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7795 * @return {Roo.Element} this
7797 setX : function(x, animate){
7799 D.setX(this.dom, x);
7801 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7807 * 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).
7808 * @param {Number} The Y position of the element
7809 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7810 * @return {Roo.Element} this
7812 setY : function(y, animate){
7814 D.setY(this.dom, y);
7816 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7822 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7823 * @param {String} left The left CSS property value
7824 * @return {Roo.Element} this
7826 setLeft : function(left){
7827 this.setStyle("left", this.addUnits(left));
7832 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7833 * @param {String} top The top CSS property value
7834 * @return {Roo.Element} this
7836 setTop : function(top){
7837 this.setStyle("top", this.addUnits(top));
7842 * Sets the element's CSS right style.
7843 * @param {String} right The right CSS property value
7844 * @return {Roo.Element} this
7846 setRight : function(right){
7847 this.setStyle("right", this.addUnits(right));
7852 * Sets the element's CSS bottom style.
7853 * @param {String} bottom The bottom CSS property value
7854 * @return {Roo.Element} this
7856 setBottom : function(bottom){
7857 this.setStyle("bottom", this.addUnits(bottom));
7862 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7863 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7864 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7865 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7866 * @return {Roo.Element} this
7868 setXY : function(pos, animate){
7870 D.setXY(this.dom, pos);
7872 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7878 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7879 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7880 * @param {Number} x X value for new position (coordinates are page-based)
7881 * @param {Number} y Y value for new position (coordinates are page-based)
7882 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7883 * @return {Roo.Element} this
7885 setLocation : function(x, y, animate){
7886 this.setXY([x, y], this.preanim(arguments, 2));
7891 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7892 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7893 * @param {Number} x X value for new position (coordinates are page-based)
7894 * @param {Number} y Y value for new position (coordinates are page-based)
7895 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7896 * @return {Roo.Element} this
7898 moveTo : function(x, y, animate){
7899 this.setXY([x, y], this.preanim(arguments, 2));
7904 * Returns the region of the given element.
7905 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7906 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7908 getRegion : function(){
7909 return D.getRegion(this.dom);
7913 * Returns the offset height of the element
7914 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7915 * @return {Number} The element's height
7917 getHeight : function(contentHeight){
7918 var h = this.dom.offsetHeight || 0;
7919 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7923 * Returns the offset width of the element
7924 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7925 * @return {Number} The element's width
7927 getWidth : function(contentWidth){
7928 var w = this.dom.offsetWidth || 0;
7929 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7933 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7934 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7935 * if a height has not been set using CSS.
7938 getComputedHeight : function(){
7939 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7941 h = parseInt(this.getStyle('height'), 10) || 0;
7942 if(!this.isBorderBox()){
7943 h += this.getFrameWidth('tb');
7950 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7951 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7952 * if a width has not been set using CSS.
7955 getComputedWidth : function(){
7956 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7958 w = parseInt(this.getStyle('width'), 10) || 0;
7959 if(!this.isBorderBox()){
7960 w += this.getFrameWidth('lr');
7967 * Returns the size of the element.
7968 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7969 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7971 getSize : function(contentSize){
7972 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7976 * Returns the width and height of the viewport.
7977 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7979 getViewSize : function(){
7980 var d = this.dom, doc = document, aw = 0, ah = 0;
7981 if(d == doc || d == doc.body){
7982 return {width : D.getViewWidth(), height: D.getViewHeight()};
7985 width : d.clientWidth,
7986 height: d.clientHeight
7992 * Returns the value of the "value" attribute
7993 * @param {Boolean} asNumber true to parse the value as a number
7994 * @return {String/Number}
7996 getValue : function(asNumber){
7997 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
8001 adjustWidth : function(width){
8002 if(typeof width == "number"){
8003 if(this.autoBoxAdjust && !this.isBorderBox()){
8004 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8014 adjustHeight : function(height){
8015 if(typeof height == "number"){
8016 if(this.autoBoxAdjust && !this.isBorderBox()){
8017 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8027 * Set the width of the element
8028 * @param {Number} width The new width
8029 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8030 * @return {Roo.Element} this
8032 setWidth : function(width, animate){
8033 width = this.adjustWidth(width);
8035 this.dom.style.width = this.addUnits(width);
8037 this.anim({width: {to: width}}, this.preanim(arguments, 1));
8043 * Set the height of the element
8044 * @param {Number} height The new height
8045 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8046 * @return {Roo.Element} this
8048 setHeight : function(height, animate){
8049 height = this.adjustHeight(height);
8051 this.dom.style.height = this.addUnits(height);
8053 this.anim({height: {to: height}}, this.preanim(arguments, 1));
8059 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
8060 * @param {Number} width The new width
8061 * @param {Number} height The new height
8062 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8063 * @return {Roo.Element} this
8065 setSize : function(width, height, animate){
8066 if(typeof width == "object"){ // in case of object from getSize()
8067 height = width.height; width = width.width;
8069 width = this.adjustWidth(width); height = this.adjustHeight(height);
8071 this.dom.style.width = this.addUnits(width);
8072 this.dom.style.height = this.addUnits(height);
8074 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8080 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8081 * @param {Number} x X value for new position (coordinates are page-based)
8082 * @param {Number} y Y value for new position (coordinates are page-based)
8083 * @param {Number} width The new width
8084 * @param {Number} height The new height
8085 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8086 * @return {Roo.Element} this
8088 setBounds : function(x, y, width, height, animate){
8090 this.setSize(width, height);
8091 this.setLocation(x, y);
8093 width = this.adjustWidth(width); height = this.adjustHeight(height);
8094 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8095 this.preanim(arguments, 4), 'motion');
8101 * 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.
8102 * @param {Roo.lib.Region} region The region to fill
8103 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8104 * @return {Roo.Element} this
8106 setRegion : function(region, animate){
8107 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8112 * Appends an event handler
8114 * @param {String} eventName The type of event to append
8115 * @param {Function} fn The method the event invokes
8116 * @param {Object} scope (optional) The scope (this object) of the fn
8117 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8119 addListener : function(eventName, fn, scope, options){
8121 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8126 * Removes an event handler from this element
8127 * @param {String} eventName the type of event to remove
8128 * @param {Function} fn the method the event invokes
8129 * @return {Roo.Element} this
8131 removeListener : function(eventName, fn){
8132 Roo.EventManager.removeListener(this.dom, eventName, fn);
8137 * Removes all previous added listeners from this element
8138 * @return {Roo.Element} this
8140 removeAllListeners : function(){
8141 E.purgeElement(this.dom);
8145 relayEvent : function(eventName, observable){
8146 this.on(eventName, function(e){
8147 observable.fireEvent(eventName, e);
8152 * Set the opacity of the element
8153 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8154 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8155 * @return {Roo.Element} this
8157 setOpacity : function(opacity, animate){
8159 var s = this.dom.style;
8162 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8163 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8165 s.opacity = opacity;
8168 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8174 * Gets the left X coordinate
8175 * @param {Boolean} local True to get the local css position instead of page coordinate
8178 getLeft : function(local){
8182 return parseInt(this.getStyle("left"), 10) || 0;
8187 * Gets the right X coordinate of the element (element X position + element width)
8188 * @param {Boolean} local True to get the local css position instead of page coordinate
8191 getRight : function(local){
8193 return this.getX() + this.getWidth();
8195 return (this.getLeft(true) + this.getWidth()) || 0;
8200 * Gets the top Y coordinate
8201 * @param {Boolean} local True to get the local css position instead of page coordinate
8204 getTop : function(local) {
8208 return parseInt(this.getStyle("top"), 10) || 0;
8213 * Gets the bottom Y coordinate of the element (element Y position + element height)
8214 * @param {Boolean} local True to get the local css position instead of page coordinate
8217 getBottom : function(local){
8219 return this.getY() + this.getHeight();
8221 return (this.getTop(true) + this.getHeight()) || 0;
8226 * Initializes positioning on this element. If a desired position is not passed, it will make the
8227 * the element positioned relative IF it is not already positioned.
8228 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8229 * @param {Number} zIndex (optional) The zIndex to apply
8230 * @param {Number} x (optional) Set the page X position
8231 * @param {Number} y (optional) Set the page Y position
8233 position : function(pos, zIndex, x, y){
8235 if(this.getStyle('position') == 'static'){
8236 this.setStyle('position', 'relative');
8239 this.setStyle("position", pos);
8242 this.setStyle("z-index", zIndex);
8244 if(x !== undefined && y !== undefined){
8246 }else if(x !== undefined){
8248 }else if(y !== undefined){
8254 * Clear positioning back to the default when the document was loaded
8255 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8256 * @return {Roo.Element} this
8258 clearPositioning : function(value){
8266 "position" : "static"
8272 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8273 * snapshot before performing an update and then restoring the element.
8276 getPositioning : function(){
8277 var l = this.getStyle("left");
8278 var t = this.getStyle("top");
8280 "position" : this.getStyle("position"),
8282 "right" : l ? "" : this.getStyle("right"),
8284 "bottom" : t ? "" : this.getStyle("bottom"),
8285 "z-index" : this.getStyle("z-index")
8290 * Gets the width of the border(s) for the specified side(s)
8291 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8292 * passing lr would get the border (l)eft width + the border (r)ight width.
8293 * @return {Number} The width of the sides passed added together
8295 getBorderWidth : function(side){
8296 return this.addStyles(side, El.borders);
8300 * Gets the width of the padding(s) for the specified side(s)
8301 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8302 * passing lr would get the padding (l)eft + the padding (r)ight.
8303 * @return {Number} The padding of the sides passed added together
8305 getPadding : function(side){
8306 return this.addStyles(side, El.paddings);
8310 * Set positioning with an object returned by getPositioning().
8311 * @param {Object} posCfg
8312 * @return {Roo.Element} this
8314 setPositioning : function(pc){
8315 this.applyStyles(pc);
8316 if(pc.right == "auto"){
8317 this.dom.style.right = "";
8319 if(pc.bottom == "auto"){
8320 this.dom.style.bottom = "";
8326 fixDisplay : function(){
8327 if(this.getStyle("display") == "none"){
8328 this.setStyle("visibility", "hidden");
8329 this.setStyle("display", this.originalDisplay); // first try reverting to default
8330 if(this.getStyle("display") == "none"){ // if that fails, default to block
8331 this.setStyle("display", "block");
8337 * Quick set left and top adding default units
8338 * @param {String} left The left CSS property value
8339 * @param {String} top The top CSS property value
8340 * @return {Roo.Element} this
8342 setLeftTop : function(left, top){
8343 this.dom.style.left = this.addUnits(left);
8344 this.dom.style.top = this.addUnits(top);
8349 * Move this element relative to its current position.
8350 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8351 * @param {Number} distance How far to move the element in pixels
8352 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8353 * @return {Roo.Element} this
8355 move : function(direction, distance, animate){
8356 var xy = this.getXY();
8357 direction = direction.toLowerCase();
8361 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8365 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8370 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8375 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8382 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8383 * @return {Roo.Element} this
8386 if(!this.isClipped){
8387 this.isClipped = true;
8388 this.originalClip = {
8389 "o": this.getStyle("overflow"),
8390 "x": this.getStyle("overflow-x"),
8391 "y": this.getStyle("overflow-y")
8393 this.setStyle("overflow", "hidden");
8394 this.setStyle("overflow-x", "hidden");
8395 this.setStyle("overflow-y", "hidden");
8401 * Return clipping (overflow) to original clipping before clip() was called
8402 * @return {Roo.Element} this
8404 unclip : function(){
8406 this.isClipped = false;
8407 var o = this.originalClip;
8408 if(o.o){this.setStyle("overflow", o.o);}
8409 if(o.x){this.setStyle("overflow-x", o.x);}
8410 if(o.y){this.setStyle("overflow-y", o.y);}
8417 * Gets the x,y coordinates specified by the anchor position on the element.
8418 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8419 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8420 * {width: (target width), height: (target height)} (defaults to the element's current size)
8421 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8422 * @return {Array} [x, y] An array containing the element's x and y coordinates
8424 getAnchorXY : function(anchor, local, s){
8425 //Passing a different size is useful for pre-calculating anchors,
8426 //especially for anchored animations that change the el size.
8428 var w, h, vp = false;
8431 if(d == document.body || d == document){
8433 w = D.getViewWidth(); h = D.getViewHeight();
8435 w = this.getWidth(); h = this.getHeight();
8438 w = s.width; h = s.height;
8440 var x = 0, y = 0, r = Math.round;
8441 switch((anchor || "tl").toLowerCase()){
8483 var sc = this.getScroll();
8484 return [x + sc.left, y + sc.top];
8486 //Add the element's offset xy
8487 var o = this.getXY();
8488 return [x+o[0], y+o[1]];
8492 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8493 * supported position values.
8494 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8495 * @param {String} position The position to align to.
8496 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8497 * @return {Array} [x, y]
8499 getAlignToXY : function(el, p, o){
8503 throw "Element.alignTo with an element that doesn't exist";
8505 var c = false; //constrain to viewport
8506 var p1 = "", p2 = "";
8513 }else if(p.indexOf("-") == -1){
8516 p = p.toLowerCase();
8517 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8519 throw "Element.alignTo with an invalid alignment " + p;
8521 p1 = m[1]; p2 = m[2]; c = !!m[3];
8523 //Subtract the aligned el's internal xy from the target's offset xy
8524 //plus custom offset to get the aligned el's new offset xy
8525 var a1 = this.getAnchorXY(p1, true);
8526 var a2 = el.getAnchorXY(p2, false);
8527 var x = a2[0] - a1[0] + o[0];
8528 var y = a2[1] - a1[1] + o[1];
8530 //constrain the aligned el to viewport if necessary
8531 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8532 // 5px of margin for ie
8533 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8535 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8536 //perpendicular to the vp border, allow the aligned el to slide on that border,
8537 //otherwise swap the aligned el to the opposite border of the target.
8538 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8539 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8540 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8541 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8544 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8545 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8547 if((x+w) > dw + scrollX){
8548 x = swapX ? r.left-w : dw+scrollX-w;
8551 x = swapX ? r.right : scrollX;
8553 if((y+h) > dh + scrollY){
8554 y = swapY ? r.top-h : dh+scrollY-h;
8557 y = swapY ? r.bottom : scrollY;
8564 getConstrainToXY : function(){
8565 var os = {top:0, left:0, bottom:0, right: 0};
8567 return function(el, local, offsets, proposedXY){
8569 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8571 var vw, vh, vx = 0, vy = 0;
8572 if(el.dom == document.body || el.dom == document){
8573 vw = Roo.lib.Dom.getViewWidth();
8574 vh = Roo.lib.Dom.getViewHeight();
8576 vw = el.dom.clientWidth;
8577 vh = el.dom.clientHeight;
8579 var vxy = el.getXY();
8585 var s = el.getScroll();
8587 vx += offsets.left + s.left;
8588 vy += offsets.top + s.top;
8590 vw -= offsets.right;
8591 vh -= offsets.bottom;
8596 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8597 var x = xy[0], y = xy[1];
8598 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8600 // only move it if it needs it
8603 // first validate right/bottom
8612 // then make sure top/left isn't negative
8621 return moved ? [x, y] : false;
8626 adjustForConstraints : function(xy, parent, offsets){
8627 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8631 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8632 * document it aligns it to the viewport.
8633 * The position parameter is optional, and can be specified in any one of the following formats:
8635 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8636 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8637 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8638 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8639 * <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
8640 * element's anchor point, and the second value is used as the target's anchor point.</li>
8642 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8643 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8644 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8645 * that specified in order to enforce the viewport constraints.
8646 * Following are all of the supported anchor positions:
8649 ----- -----------------------------
8650 tl The top left corner (default)
8651 t The center of the top edge
8652 tr The top right corner
8653 l The center of the left edge
8654 c In the center of the element
8655 r The center of the right edge
8656 bl The bottom left corner
8657 b The center of the bottom edge
8658 br The bottom right corner
8662 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8663 el.alignTo("other-el");
8665 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8666 el.alignTo("other-el", "tr?");
8668 // align the bottom right corner of el with the center left edge of other-el
8669 el.alignTo("other-el", "br-l?");
8671 // align the center of el with the bottom left corner of other-el and
8672 // adjust the x position by -6 pixels (and the y position by 0)
8673 el.alignTo("other-el", "c-bl", [-6, 0]);
8675 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8676 * @param {String} position The position to align to.
8677 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8678 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8679 * @return {Roo.Element} this
8681 alignTo : function(element, position, offsets, animate){
8682 var xy = this.getAlignToXY(element, position, offsets);
8683 this.setXY(xy, this.preanim(arguments, 3));
8688 * Anchors an element to another element and realigns it when the window is resized.
8689 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8690 * @param {String} position The position to align to.
8691 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8692 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8693 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8694 * is a number, it is used as the buffer delay (defaults to 50ms).
8695 * @param {Function} callback The function to call after the animation finishes
8696 * @return {Roo.Element} this
8698 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8699 var action = function(){
8700 this.alignTo(el, alignment, offsets, animate);
8701 Roo.callback(callback, this);
8703 Roo.EventManager.onWindowResize(action, this);
8704 var tm = typeof monitorScroll;
8705 if(tm != 'undefined'){
8706 Roo.EventManager.on(window, 'scroll', action, this,
8707 {buffer: tm == 'number' ? monitorScroll : 50});
8709 action.call(this); // align immediately
8713 * Clears any opacity settings from this element. Required in some cases for IE.
8714 * @return {Roo.Element} this
8716 clearOpacity : function(){
8717 if (window.ActiveXObject) {
8718 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8719 this.dom.style.filter = "";
8722 this.dom.style.opacity = "";
8723 this.dom.style["-moz-opacity"] = "";
8724 this.dom.style["-khtml-opacity"] = "";
8730 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8731 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8732 * @return {Roo.Element} this
8734 hide : function(animate){
8735 this.setVisible(false, this.preanim(arguments, 0));
8740 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8741 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8742 * @return {Roo.Element} this
8744 show : function(animate){
8745 this.setVisible(true, this.preanim(arguments, 0));
8750 * @private Test if size has a unit, otherwise appends the default
8752 addUnits : function(size){
8753 return Roo.Element.addUnits(size, this.defaultUnit);
8757 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8758 * @return {Roo.Element} this
8760 beginMeasure : function(){
8762 if(el.offsetWidth || el.offsetHeight){
8763 return this; // offsets work already
8766 var p = this.dom, b = document.body; // start with this element
8767 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8768 var pe = Roo.get(p);
8769 if(pe.getStyle('display') == 'none'){
8770 changed.push({el: p, visibility: pe.getStyle("visibility")});
8771 p.style.visibility = "hidden";
8772 p.style.display = "block";
8776 this._measureChanged = changed;
8782 * Restores displays to before beginMeasure was called
8783 * @return {Roo.Element} this
8785 endMeasure : function(){
8786 var changed = this._measureChanged;
8788 for(var i = 0, len = changed.length; i < len; i++) {
8790 r.el.style.visibility = r.visibility;
8791 r.el.style.display = "none";
8793 this._measureChanged = null;
8799 * Update the innerHTML of this element, optionally searching for and processing scripts
8800 * @param {String} html The new HTML
8801 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8802 * @param {Function} callback For async script loading you can be noticed when the update completes
8803 * @return {Roo.Element} this
8805 update : function(html, loadScripts, callback){
8806 if(typeof html == "undefined"){
8809 if(loadScripts !== true){
8810 this.dom.innerHTML = html;
8811 if(typeof callback == "function"){
8819 html += '<span id="' + id + '"></span>';
8821 E.onAvailable(id, function(){
8822 var hd = document.getElementsByTagName("head")[0];
8823 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8824 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8825 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8828 while(match = re.exec(html)){
8829 var attrs = match[1];
8830 var srcMatch = attrs ? attrs.match(srcRe) : false;
8831 if(srcMatch && srcMatch[2]){
8832 var s = document.createElement("script");
8833 s.src = srcMatch[2];
8834 var typeMatch = attrs.match(typeRe);
8835 if(typeMatch && typeMatch[2]){
8836 s.type = typeMatch[2];
8839 }else if(match[2] && match[2].length > 0){
8840 if(window.execScript) {
8841 window.execScript(match[2]);
8849 window.eval(match[2]);
8853 var el = document.getElementById(id);
8854 if(el){el.parentNode.removeChild(el);}
8855 if(typeof callback == "function"){
8859 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8864 * Direct access to the UpdateManager update() method (takes the same parameters).
8865 * @param {String/Function} url The url for this request or a function to call to get the url
8866 * @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}
8867 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8868 * @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.
8869 * @return {Roo.Element} this
8872 var um = this.getUpdateManager();
8873 um.update.apply(um, arguments);
8878 * Gets this element's UpdateManager
8879 * @return {Roo.UpdateManager} The UpdateManager
8881 getUpdateManager : function(){
8882 if(!this.updateManager){
8883 this.updateManager = new Roo.UpdateManager(this);
8885 return this.updateManager;
8889 * Disables text selection for this element (normalized across browsers)
8890 * @return {Roo.Element} this
8892 unselectable : function(){
8893 this.dom.unselectable = "on";
8894 this.swallowEvent("selectstart", true);
8895 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8896 this.addClass("x-unselectable");
8901 * Calculates the x, y to center this element on the screen
8902 * @return {Array} The x, y values [x, y]
8904 getCenterXY : function(){
8905 return this.getAlignToXY(document, 'c-c');
8909 * Centers the Element in either the viewport, or another Element.
8910 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8912 center : function(centerIn){
8913 this.alignTo(centerIn || document, 'c-c');
8918 * Tests various css rules/browsers to determine if this element uses a border box
8921 isBorderBox : function(){
8922 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8926 * Return a box {x, y, width, height} that can be used to set another elements
8927 * size/location to match this element.
8928 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8929 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8930 * @return {Object} box An object in the format {x, y, width, height}
8932 getBox : function(contentBox, local){
8937 var left = parseInt(this.getStyle("left"), 10) || 0;
8938 var top = parseInt(this.getStyle("top"), 10) || 0;
8941 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8943 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8945 var l = this.getBorderWidth("l")+this.getPadding("l");
8946 var r = this.getBorderWidth("r")+this.getPadding("r");
8947 var t = this.getBorderWidth("t")+this.getPadding("t");
8948 var b = this.getBorderWidth("b")+this.getPadding("b");
8949 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)};
8951 bx.right = bx.x + bx.width;
8952 bx.bottom = bx.y + bx.height;
8957 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8958 for more information about the sides.
8959 * @param {String} sides
8962 getFrameWidth : function(sides, onlyContentBox){
8963 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8967 * 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.
8968 * @param {Object} box The box to fill {x, y, width, height}
8969 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8970 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8971 * @return {Roo.Element} this
8973 setBox : function(box, adjust, animate){
8974 var w = box.width, h = box.height;
8975 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8976 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8977 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8979 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8984 * Forces the browser to repaint this element
8985 * @return {Roo.Element} this
8987 repaint : function(){
8989 this.addClass("x-repaint");
8990 setTimeout(function(){
8991 Roo.get(dom).removeClass("x-repaint");
8997 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8998 * then it returns the calculated width of the sides (see getPadding)
8999 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
9000 * @return {Object/Number}
9002 getMargins : function(side){
9005 top: parseInt(this.getStyle("margin-top"), 10) || 0,
9006 left: parseInt(this.getStyle("margin-left"), 10) || 0,
9007 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
9008 right: parseInt(this.getStyle("margin-right"), 10) || 0
9011 return this.addStyles(side, El.margins);
9016 addStyles : function(sides, styles){
9018 for(var i = 0, len = sides.length; i < len; i++){
9019 v = this.getStyle(styles[sides.charAt(i)]);
9021 w = parseInt(v, 10);
9029 * Creates a proxy element of this element
9030 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
9031 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
9032 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
9033 * @return {Roo.Element} The new proxy element
9035 createProxy : function(config, renderTo, matchBox){
9037 renderTo = Roo.getDom(renderTo);
9039 renderTo = document.body;
9041 config = typeof config == "object" ?
9042 config : {tag : "div", cls: config};
9043 var proxy = Roo.DomHelper.append(renderTo, config, true);
9045 proxy.setBox(this.getBox());
9051 * Puts a mask over this element to disable user interaction. Requires core.css.
9052 * This method can only be applied to elements which accept child nodes.
9053 * @param {String} msg (optional) A message to display in the mask
9054 * @param {String} msgCls (optional) A css class to apply to the msg element
9055 * @return {Element} The mask element
9057 mask : function(msg, msgCls)
9059 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
9060 this.setStyle("position", "relative");
9063 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
9065 this.addClass("x-masked");
9066 this._mask.setDisplayed(true);
9071 while (dom && dom.style) {
9072 if (!isNaN(parseInt(dom.style.zIndex))) {
9073 z = Math.max(z, parseInt(dom.style.zIndex));
9075 dom = dom.parentNode;
9077 // if we are masking the body - then it hides everything..
9078 if (this.dom == document.body) {
9080 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9081 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9084 if(typeof msg == 'string'){
9086 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9088 var mm = this._maskMsg;
9089 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9090 if (mm.dom.firstChild) { // weird IE issue?
9091 mm.dom.firstChild.innerHTML = msg;
9093 mm.setDisplayed(true);
9095 mm.setStyle('z-index', z + 102);
9097 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9098 this._mask.setHeight(this.getHeight());
9100 this._mask.setStyle('z-index', z + 100);
9106 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9107 * it is cached for reuse.
9109 unmask : function(removeEl){
9111 if(removeEl === true){
9112 this._mask.remove();
9115 this._maskMsg.remove();
9116 delete this._maskMsg;
9119 this._mask.setDisplayed(false);
9121 this._maskMsg.setDisplayed(false);
9125 this.removeClass("x-masked");
9129 * Returns true if this element is masked
9132 isMasked : function(){
9133 return this._mask && this._mask.isVisible();
9137 * Creates an iframe shim for this element to keep selects and other windowed objects from
9139 * @return {Roo.Element} The new shim element
9141 createShim : function(){
9142 var el = document.createElement('iframe');
9143 el.frameBorder = 'no';
9144 el.className = 'roo-shim';
9145 if(Roo.isIE && Roo.isSecure){
9146 el.src = Roo.SSL_SECURE_URL;
9148 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9149 shim.autoBoxAdjust = false;
9154 * Removes this element from the DOM and deletes it from the cache
9156 remove : function(){
9157 if(this.dom.parentNode){
9158 this.dom.parentNode.removeChild(this.dom);
9160 delete El.cache[this.dom.id];
9164 * Sets up event handlers to add and remove a css class when the mouse is over this element
9165 * @param {String} className
9166 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9167 * mouseout events for children elements
9168 * @return {Roo.Element} this
9170 addClassOnOver : function(className, preventFlicker){
9171 this.on("mouseover", function(){
9172 Roo.fly(this, '_internal').addClass(className);
9174 var removeFn = function(e){
9175 if(preventFlicker !== true || !e.within(this, true)){
9176 Roo.fly(this, '_internal').removeClass(className);
9179 this.on("mouseout", removeFn, this.dom);
9184 * Sets up event handlers to add and remove a css class when this element has the focus
9185 * @param {String} className
9186 * @return {Roo.Element} this
9188 addClassOnFocus : function(className){
9189 this.on("focus", function(){
9190 Roo.fly(this, '_internal').addClass(className);
9192 this.on("blur", function(){
9193 Roo.fly(this, '_internal').removeClass(className);
9198 * 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)
9199 * @param {String} className
9200 * @return {Roo.Element} this
9202 addClassOnClick : function(className){
9204 this.on("mousedown", function(){
9205 Roo.fly(dom, '_internal').addClass(className);
9206 var d = Roo.get(document);
9207 var fn = function(){
9208 Roo.fly(dom, '_internal').removeClass(className);
9209 d.removeListener("mouseup", fn);
9211 d.on("mouseup", fn);
9217 * Stops the specified event from bubbling and optionally prevents the default action
9218 * @param {String} eventName
9219 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9220 * @return {Roo.Element} this
9222 swallowEvent : function(eventName, preventDefault){
9223 var fn = function(e){
9224 e.stopPropagation();
9229 if(eventName instanceof Array){
9230 for(var i = 0, len = eventName.length; i < len; i++){
9231 this.on(eventName[i], fn);
9235 this.on(eventName, fn);
9242 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9245 * Sizes this element to its parent element's dimensions performing
9246 * neccessary box adjustments.
9247 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9248 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9249 * @return {Roo.Element} this
9251 fitToParent : function(monitorResize, targetParent) {
9252 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9253 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9254 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9257 var p = Roo.get(targetParent || this.dom.parentNode);
9258 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9259 if (monitorResize === true) {
9260 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9261 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9267 * Gets the next sibling, skipping text nodes
9268 * @return {HTMLElement} The next sibling or null
9270 getNextSibling : function(){
9271 var n = this.dom.nextSibling;
9272 while(n && n.nodeType != 1){
9279 * Gets the previous sibling, skipping text nodes
9280 * @return {HTMLElement} The previous sibling or null
9282 getPrevSibling : function(){
9283 var n = this.dom.previousSibling;
9284 while(n && n.nodeType != 1){
9285 n = n.previousSibling;
9292 * Appends the passed element(s) to this element
9293 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9294 * @return {Roo.Element} this
9296 appendChild: function(el){
9303 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9304 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9305 * automatically generated with the specified attributes.
9306 * @param {HTMLElement} insertBefore (optional) a child element of this element
9307 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9308 * @return {Roo.Element} The new child element
9310 createChild: function(config, insertBefore, returnDom){
9311 config = config || {tag:'div'};
9313 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9315 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9319 * Appends this element to the passed element
9320 * @param {String/HTMLElement/Element} el The new parent element
9321 * @return {Roo.Element} this
9323 appendTo: function(el){
9324 el = Roo.getDom(el);
9325 el.appendChild(this.dom);
9330 * Inserts this element before the passed element in the DOM
9331 * @param {String/HTMLElement/Element} el The element to insert before
9332 * @return {Roo.Element} this
9334 insertBefore: function(el){
9335 el = Roo.getDom(el);
9336 el.parentNode.insertBefore(this.dom, el);
9341 * Inserts this element after the passed element in the DOM
9342 * @param {String/HTMLElement/Element} el The element to insert after
9343 * @return {Roo.Element} this
9345 insertAfter: function(el){
9346 el = Roo.getDom(el);
9347 el.parentNode.insertBefore(this.dom, el.nextSibling);
9352 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9353 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9354 * @return {Roo.Element} The new child
9356 insertFirst: function(el, returnDom){
9358 if(typeof el == 'object' && !el.nodeType){ // dh config
9359 return this.createChild(el, this.dom.firstChild, returnDom);
9361 el = Roo.getDom(el);
9362 this.dom.insertBefore(el, this.dom.firstChild);
9363 return !returnDom ? Roo.get(el) : el;
9368 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9369 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9370 * @param {String} where (optional) 'before' or 'after' defaults to before
9371 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9372 * @return {Roo.Element} the inserted Element
9374 insertSibling: function(el, where, returnDom){
9375 where = where ? where.toLowerCase() : 'before';
9377 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9379 if(typeof el == 'object' && !el.nodeType){ // dh config
9380 if(where == 'after' && !this.dom.nextSibling){
9381 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9383 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9387 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9388 where == 'before' ? this.dom : this.dom.nextSibling);
9397 * Creates and wraps this element with another element
9398 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9399 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9400 * @return {HTMLElement/Element} The newly created wrapper element
9402 wrap: function(config, returnDom){
9404 config = {tag: "div"};
9406 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9407 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9412 * Replaces the passed element with this element
9413 * @param {String/HTMLElement/Element} el The element to replace
9414 * @return {Roo.Element} this
9416 replace: function(el){
9418 this.insertBefore(el);
9424 * Inserts an html fragment into this element
9425 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9426 * @param {String} html The HTML fragment
9427 * @param {Boolean} returnEl True to return an Roo.Element
9428 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9430 insertHtml : function(where, html, returnEl){
9431 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9432 return returnEl ? Roo.get(el) : el;
9436 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9437 * @param {Object} o The object with the attributes
9438 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9439 * @return {Roo.Element} this
9441 set : function(o, useSet){
9443 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9445 if(attr == "style" || typeof o[attr] == "function") { continue; }
9447 el.className = o["cls"];
9450 el.setAttribute(attr, o[attr]);
9457 Roo.DomHelper.applyStyles(el, o.style);
9463 * Convenience method for constructing a KeyMap
9464 * @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:
9465 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9466 * @param {Function} fn The function to call
9467 * @param {Object} scope (optional) The scope of the function
9468 * @return {Roo.KeyMap} The KeyMap created
9470 addKeyListener : function(key, fn, scope){
9472 if(typeof key != "object" || key instanceof Array){
9488 return new Roo.KeyMap(this, config);
9492 * Creates a KeyMap for this element
9493 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9494 * @return {Roo.KeyMap} The KeyMap created
9496 addKeyMap : function(config){
9497 return new Roo.KeyMap(this, config);
9501 * Returns true if this element is scrollable.
9504 isScrollable : function(){
9506 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9510 * 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().
9511 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9512 * @param {Number} value The new scroll value
9513 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9514 * @return {Element} this
9517 scrollTo : function(side, value, animate){
9518 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9520 this.dom[prop] = value;
9522 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9523 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9529 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9530 * within this element's scrollable range.
9531 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9532 * @param {Number} distance How far to scroll the element in pixels
9533 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9534 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9535 * was scrolled as far as it could go.
9537 scroll : function(direction, distance, animate){
9538 if(!this.isScrollable()){
9542 var l = el.scrollLeft, t = el.scrollTop;
9543 var w = el.scrollWidth, h = el.scrollHeight;
9544 var cw = el.clientWidth, ch = el.clientHeight;
9545 direction = direction.toLowerCase();
9546 var scrolled = false;
9547 var a = this.preanim(arguments, 2);
9552 var v = Math.min(l + distance, w-cw);
9553 this.scrollTo("left", v, a);
9560 var v = Math.max(l - distance, 0);
9561 this.scrollTo("left", v, a);
9569 var v = Math.max(t - distance, 0);
9570 this.scrollTo("top", v, a);
9578 var v = Math.min(t + distance, h-ch);
9579 this.scrollTo("top", v, a);
9588 * Translates the passed page coordinates into left/top css values for this element
9589 * @param {Number/Array} x The page x or an array containing [x, y]
9590 * @param {Number} y The page y
9591 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9593 translatePoints : function(x, y){
9594 if(typeof x == 'object' || x instanceof Array){
9597 var p = this.getStyle('position');
9598 var o = this.getXY();
9600 var l = parseInt(this.getStyle('left'), 10);
9601 var t = parseInt(this.getStyle('top'), 10);
9604 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9607 t = (p == "relative") ? 0 : this.dom.offsetTop;
9610 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9614 * Returns the current scroll position of the element.
9615 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9617 getScroll : function(){
9618 var d = this.dom, doc = document;
9619 if(d == doc || d == doc.body){
9620 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9621 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9622 return {left: l, top: t};
9624 return {left: d.scrollLeft, top: d.scrollTop};
9629 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9630 * are convert to standard 6 digit hex color.
9631 * @param {String} attr The css attribute
9632 * @param {String} defaultValue The default value to use when a valid color isn't found
9633 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9636 getColor : function(attr, defaultValue, prefix){
9637 var v = this.getStyle(attr);
9638 if(!v || v == "transparent" || v == "inherit") {
9639 return defaultValue;
9641 var color = typeof prefix == "undefined" ? "#" : prefix;
9642 if(v.substr(0, 4) == "rgb("){
9643 var rvs = v.slice(4, v.length -1).split(",");
9644 for(var i = 0; i < 3; i++){
9645 var h = parseInt(rvs[i]).toString(16);
9652 if(v.substr(0, 1) == "#"){
9654 for(var i = 1; i < 4; i++){
9655 var c = v.charAt(i);
9658 }else if(v.length == 7){
9659 color += v.substr(1);
9663 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9667 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9668 * gradient background, rounded corners and a 4-way shadow.
9669 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9670 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9671 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9672 * @return {Roo.Element} this
9674 boxWrap : function(cls){
9675 cls = cls || 'x-box';
9676 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9677 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9682 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9683 * @param {String} namespace The namespace in which to look for the attribute
9684 * @param {String} name The attribute name
9685 * @return {String} The attribute value
9687 getAttributeNS : Roo.isIE ? function(ns, name){
9689 var type = typeof d[ns+":"+name];
9690 if(type != 'undefined' && type != 'unknown'){
9691 return d[ns+":"+name];
9694 } : function(ns, name){
9696 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9701 * Sets or Returns the value the dom attribute value
9702 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9703 * @param {String} value (optional) The value to set the attribute to
9704 * @return {String} The attribute value
9706 attr : function(name){
9707 if (arguments.length > 1) {
9708 this.dom.setAttribute(name, arguments[1]);
9709 return arguments[1];
9711 if (typeof(name) == 'object') {
9712 for(var i in name) {
9713 this.attr(i, name[i]);
9719 if (!this.dom.hasAttribute(name)) {
9722 return this.dom.getAttribute(name);
9729 var ep = El.prototype;
9732 * Appends an event handler (Shorthand for addListener)
9733 * @param {String} eventName The type of event to append
9734 * @param {Function} fn The method the event invokes
9735 * @param {Object} scope (optional) The scope (this object) of the fn
9736 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9739 ep.on = ep.addListener;
9741 ep.mon = ep.addListener;
9744 * Removes an event handler from this element (shorthand for removeListener)
9745 * @param {String} eventName the type of event to remove
9746 * @param {Function} fn the method the event invokes
9747 * @return {Roo.Element} this
9750 ep.un = ep.removeListener;
9753 * true to automatically adjust width and height settings for box-model issues (default to true)
9755 ep.autoBoxAdjust = true;
9758 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9761 El.addUnits = function(v, defaultUnit){
9762 if(v === "" || v == "auto"){
9765 if(v === undefined){
9768 if(typeof v == "number" || !El.unitPattern.test(v)){
9769 return v + (defaultUnit || 'px');
9774 // special markup used throughout Roo when box wrapping elements
9775 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>';
9777 * Visibility mode constant - Use visibility to hide element
9783 * Visibility mode constant - Use display to hide element
9789 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9790 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9791 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9803 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9804 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9805 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9806 * @return {Element} The Element object
9809 El.get = function(el){
9811 if(!el){ return null; }
9812 if(typeof el == "string"){ // element id
9813 if(!(elm = document.getElementById(el))){
9816 if(ex = El.cache[el]){
9819 ex = El.cache[el] = new El(elm);
9822 }else if(el.tagName){ // dom element
9826 if(ex = El.cache[id]){
9829 ex = El.cache[id] = new El(el);
9832 }else if(el instanceof El){
9834 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9835 // catch case where it hasn't been appended
9836 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9839 }else if(el.isComposite){
9841 }else if(el instanceof Array){
9842 return El.select(el);
9843 }else if(el == document){
9844 // create a bogus element object representing the document object
9846 var f = function(){};
9847 f.prototype = El.prototype;
9849 docEl.dom = document;
9857 El.uncache = function(el){
9858 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9860 delete El.cache[a[i].id || a[i]];
9866 // Garbage collection - uncache elements/purge listeners on orphaned elements
9867 // so we don't hold a reference and cause the browser to retain them
9868 El.garbageCollect = function(){
9869 if(!Roo.enableGarbageCollector){
9870 clearInterval(El.collectorThread);
9873 for(var eid in El.cache){
9874 var el = El.cache[eid], d = el.dom;
9875 // -------------------------------------------------------
9876 // Determining what is garbage:
9877 // -------------------------------------------------------
9879 // dom node is null, definitely garbage
9880 // -------------------------------------------------------
9882 // no parentNode == direct orphan, definitely garbage
9883 // -------------------------------------------------------
9884 // !d.offsetParent && !document.getElementById(eid)
9885 // display none elements have no offsetParent so we will
9886 // also try to look it up by it's id. However, check
9887 // offsetParent first so we don't do unneeded lookups.
9888 // This enables collection of elements that are not orphans
9889 // directly, but somewhere up the line they have an orphan
9891 // -------------------------------------------------------
9892 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9893 delete El.cache[eid];
9894 if(d && Roo.enableListenerCollection){
9900 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9904 El.Flyweight = function(dom){
9907 El.Flyweight.prototype = El.prototype;
9909 El._flyweights = {};
9911 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9912 * the dom node can be overwritten by other code.
9913 * @param {String/HTMLElement} el The dom node or id
9914 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9915 * prevent conflicts (e.g. internally Roo uses "_internal")
9917 * @return {Element} The shared Element object
9919 El.fly = function(el, named){
9920 named = named || '_global';
9921 el = Roo.getDom(el);
9925 if(!El._flyweights[named]){
9926 El._flyweights[named] = new El.Flyweight();
9928 El._flyweights[named].dom = el;
9929 return El._flyweights[named];
9933 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9934 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9935 * Shorthand of {@link Roo.Element#get}
9936 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9937 * @return {Element} The Element object
9943 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9944 * the dom node can be overwritten by other code.
9945 * Shorthand of {@link Roo.Element#fly}
9946 * @param {String/HTMLElement} el The dom node or id
9947 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9948 * prevent conflicts (e.g. internally Roo uses "_internal")
9950 * @return {Element} The shared Element object
9956 // speedy lookup for elements never to box adjust
9957 var noBoxAdjust = Roo.isStrict ? {
9960 input:1, select:1, textarea:1
9962 if(Roo.isIE || Roo.isGecko){
9963 noBoxAdjust['button'] = 1;
9967 Roo.EventManager.on(window, 'unload', function(){
9969 delete El._flyweights;
9977 Roo.Element.selectorFunction = Roo.DomQuery.select;
9980 Roo.Element.select = function(selector, unique, root){
9982 if(typeof selector == "string"){
9983 els = Roo.Element.selectorFunction(selector, root);
9984 }else if(selector.length !== undefined){
9987 throw "Invalid selector";
9989 if(unique === true){
9990 return new Roo.CompositeElement(els);
9992 return new Roo.CompositeElementLite(els);
9996 * Selects elements based on the passed CSS selector to enable working on them as 1.
9997 * @param {String/Array} selector The CSS selector or an array of elements
9998 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9999 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
10000 * @return {CompositeElementLite/CompositeElement}
10004 Roo.select = Roo.Element.select;
10021 * Ext JS Library 1.1.1
10022 * Copyright(c) 2006-2007, Ext JS, LLC.
10024 * Originally Released Under LGPL - original licence link has changed is not relivant.
10027 * <script type="text/javascript">
10032 //Notifies Element that fx methods are available
10033 Roo.enableFx = true;
10037 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
10038 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
10039 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
10040 * Element effects to work.</p><br/>
10042 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
10043 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
10044 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
10045 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
10046 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
10047 * expected results and should be done with care.</p><br/>
10049 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
10050 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
10053 ----- -----------------------------
10054 tl The top left corner
10055 t The center of the top edge
10056 tr The top right corner
10057 l The center of the left edge
10058 r The center of the right edge
10059 bl The bottom left corner
10060 b The center of the bottom edge
10061 br The bottom right corner
10063 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
10064 * below are common options that can be passed to any Fx method.</b>
10065 * @cfg {Function} callback A function called when the effect is finished
10066 * @cfg {Object} scope The scope of the effect function
10067 * @cfg {String} easing A valid Easing value for the effect
10068 * @cfg {String} afterCls A css class to apply after the effect
10069 * @cfg {Number} duration The length of time (in seconds) that the effect should last
10070 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
10071 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
10072 * effects that end with the element being visually hidden, ignored otherwise)
10073 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
10074 * a function which returns such a specification that will be applied to the Element after the effect finishes
10075 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
10076 * @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
10077 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10081 * Slides the element into view. An anchor point can be optionally passed to set the point of
10082 * origin for the slide effect. This function automatically handles wrapping the element with
10083 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10086 // default: slide the element in from the top
10089 // custom: slide the element in from the right with a 2-second duration
10090 el.slideIn('r', { duration: 2 });
10092 // common config options shown with default values
10098 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10099 * @param {Object} options (optional) Object literal with any of the Fx config options
10100 * @return {Roo.Element} The Element
10102 slideIn : function(anchor, o){
10103 var el = this.getFxEl();
10106 el.queueFx(o, function(){
10108 anchor = anchor || "t";
10110 // fix display to visibility
10113 // restore values after effect
10114 var r = this.getFxRestore();
10115 var b = this.getBox();
10116 // fixed size for slide
10120 var wrap = this.fxWrap(r.pos, o, "hidden");
10122 var st = this.dom.style;
10123 st.visibility = "visible";
10124 st.position = "absolute";
10126 // clear out temp styles after slide and unwrap
10127 var after = function(){
10128 el.fxUnwrap(wrap, r.pos, o);
10129 st.width = r.width;
10130 st.height = r.height;
10133 // time to calc the positions
10134 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10136 switch(anchor.toLowerCase()){
10138 wrap.setSize(b.width, 0);
10139 st.left = st.bottom = "0";
10143 wrap.setSize(0, b.height);
10144 st.right = st.top = "0";
10148 wrap.setSize(0, b.height);
10149 wrap.setX(b.right);
10150 st.left = st.top = "0";
10151 a = {width: bw, points: pt};
10154 wrap.setSize(b.width, 0);
10155 wrap.setY(b.bottom);
10156 st.left = st.top = "0";
10157 a = {height: bh, points: pt};
10160 wrap.setSize(0, 0);
10161 st.right = st.bottom = "0";
10162 a = {width: bw, height: bh};
10165 wrap.setSize(0, 0);
10166 wrap.setY(b.y+b.height);
10167 st.right = st.top = "0";
10168 a = {width: bw, height: bh, points: pt};
10171 wrap.setSize(0, 0);
10172 wrap.setXY([b.right, b.bottom]);
10173 st.left = st.top = "0";
10174 a = {width: bw, height: bh, points: pt};
10177 wrap.setSize(0, 0);
10178 wrap.setX(b.x+b.width);
10179 st.left = st.bottom = "0";
10180 a = {width: bw, height: bh, points: pt};
10183 this.dom.style.visibility = "visible";
10186 arguments.callee.anim = wrap.fxanim(a,
10196 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10197 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10198 * 'hidden') but block elements will still take up space in the document. The element must be removed
10199 * from the DOM using the 'remove' config option if desired. This function automatically handles
10200 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10203 // default: slide the element out to the top
10206 // custom: slide the element out to the right with a 2-second duration
10207 el.slideOut('r', { duration: 2 });
10209 // common config options shown with default values
10217 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10218 * @param {Object} options (optional) Object literal with any of the Fx config options
10219 * @return {Roo.Element} The Element
10221 slideOut : function(anchor, o){
10222 var el = this.getFxEl();
10225 el.queueFx(o, function(){
10227 anchor = anchor || "t";
10229 // restore values after effect
10230 var r = this.getFxRestore();
10232 var b = this.getBox();
10233 // fixed size for slide
10237 var wrap = this.fxWrap(r.pos, o, "visible");
10239 var st = this.dom.style;
10240 st.visibility = "visible";
10241 st.position = "absolute";
10245 var after = function(){
10247 el.setDisplayed(false);
10252 el.fxUnwrap(wrap, r.pos, o);
10254 st.width = r.width;
10255 st.height = r.height;
10260 var a, zero = {to: 0};
10261 switch(anchor.toLowerCase()){
10263 st.left = st.bottom = "0";
10264 a = {height: zero};
10267 st.right = st.top = "0";
10271 st.left = st.top = "0";
10272 a = {width: zero, points: {to:[b.right, b.y]}};
10275 st.left = st.top = "0";
10276 a = {height: zero, points: {to:[b.x, b.bottom]}};
10279 st.right = st.bottom = "0";
10280 a = {width: zero, height: zero};
10283 st.right = st.top = "0";
10284 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10287 st.left = st.top = "0";
10288 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10291 st.left = st.bottom = "0";
10292 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10296 arguments.callee.anim = wrap.fxanim(a,
10306 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10307 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10308 * The element must be removed from the DOM using the 'remove' config option if desired.
10314 // common config options shown with default values
10322 * @param {Object} options (optional) Object literal with any of the Fx config options
10323 * @return {Roo.Element} The Element
10325 puff : function(o){
10326 var el = this.getFxEl();
10329 el.queueFx(o, function(){
10330 this.clearOpacity();
10333 // restore values after effect
10334 var r = this.getFxRestore();
10335 var st = this.dom.style;
10337 var after = function(){
10339 el.setDisplayed(false);
10346 el.setPositioning(r.pos);
10347 st.width = r.width;
10348 st.height = r.height;
10353 var width = this.getWidth();
10354 var height = this.getHeight();
10356 arguments.callee.anim = this.fxanim({
10357 width : {to: this.adjustWidth(width * 2)},
10358 height : {to: this.adjustHeight(height * 2)},
10359 points : {by: [-(width * .5), -(height * .5)]},
10361 fontSize: {to:200, unit: "%"}
10372 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10373 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10374 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10380 // all config options shown with default values
10388 * @param {Object} options (optional) Object literal with any of the Fx config options
10389 * @return {Roo.Element} The Element
10391 switchOff : function(o){
10392 var el = this.getFxEl();
10395 el.queueFx(o, function(){
10396 this.clearOpacity();
10399 // restore values after effect
10400 var r = this.getFxRestore();
10401 var st = this.dom.style;
10403 var after = function(){
10405 el.setDisplayed(false);
10411 el.setPositioning(r.pos);
10412 st.width = r.width;
10413 st.height = r.height;
10418 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10419 this.clearOpacity();
10423 points:{by:[0, this.getHeight() * .5]}
10424 }, o, 'motion', 0.3, 'easeIn', after);
10425 }).defer(100, this);
10432 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10433 * changed using the "attr" config option) and then fading back to the original color. If no original
10434 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10437 // default: highlight background to yellow
10440 // custom: highlight foreground text to blue for 2 seconds
10441 el.highlight("0000ff", { attr: 'color', duration: 2 });
10443 // common config options shown with default values
10444 el.highlight("ffff9c", {
10445 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10446 endColor: (current color) or "ffffff",
10451 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10452 * @param {Object} options (optional) Object literal with any of the Fx config options
10453 * @return {Roo.Element} The Element
10455 highlight : function(color, o){
10456 var el = this.getFxEl();
10459 el.queueFx(o, function(){
10460 color = color || "ffff9c";
10461 attr = o.attr || "backgroundColor";
10463 this.clearOpacity();
10466 var origColor = this.getColor(attr);
10467 var restoreColor = this.dom.style[attr];
10468 endColor = (o.endColor || origColor) || "ffffff";
10470 var after = function(){
10471 el.dom.style[attr] = restoreColor;
10476 a[attr] = {from: color, to: endColor};
10477 arguments.callee.anim = this.fxanim(a,
10487 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10490 // default: a single light blue ripple
10493 // custom: 3 red ripples lasting 3 seconds total
10494 el.frame("ff0000", 3, { duration: 3 });
10496 // common config options shown with default values
10497 el.frame("C3DAF9", 1, {
10498 duration: 1 //duration of entire animation (not each individual ripple)
10499 // Note: Easing is not configurable and will be ignored if included
10502 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10503 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10504 * @param {Object} options (optional) Object literal with any of the Fx config options
10505 * @return {Roo.Element} The Element
10507 frame : function(color, count, o){
10508 var el = this.getFxEl();
10511 el.queueFx(o, function(){
10512 color = color || "#C3DAF9";
10513 if(color.length == 6){
10514 color = "#" + color;
10516 count = count || 1;
10517 duration = o.duration || 1;
10520 var b = this.getBox();
10521 var animFn = function(){
10522 var proxy = this.createProxy({
10525 visbility:"hidden",
10526 position:"absolute",
10527 "z-index":"35000", // yee haw
10528 border:"0px solid " + color
10531 var scale = Roo.isBorderBox ? 2 : 1;
10533 top:{from:b.y, to:b.y - 20},
10534 left:{from:b.x, to:b.x - 20},
10535 borderWidth:{from:0, to:10},
10536 opacity:{from:1, to:0},
10537 height:{from:b.height, to:(b.height + (20*scale))},
10538 width:{from:b.width, to:(b.width + (20*scale))}
10539 }, duration, function(){
10543 animFn.defer((duration/2)*1000, this);
10554 * Creates a pause before any subsequent queued effects begin. If there are
10555 * no effects queued after the pause it will have no effect.
10560 * @param {Number} seconds The length of time to pause (in seconds)
10561 * @return {Roo.Element} The Element
10563 pause : function(seconds){
10564 var el = this.getFxEl();
10567 el.queueFx(o, function(){
10568 setTimeout(function(){
10570 }, seconds * 1000);
10576 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10577 * using the "endOpacity" config option.
10580 // default: fade in from opacity 0 to 100%
10583 // custom: fade in from opacity 0 to 75% over 2 seconds
10584 el.fadeIn({ endOpacity: .75, duration: 2});
10586 // common config options shown with default values
10588 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10593 * @param {Object} options (optional) Object literal with any of the Fx config options
10594 * @return {Roo.Element} The Element
10596 fadeIn : function(o){
10597 var el = this.getFxEl();
10599 el.queueFx(o, function(){
10600 this.setOpacity(0);
10602 this.dom.style.visibility = 'visible';
10603 var to = o.endOpacity || 1;
10604 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10605 o, null, .5, "easeOut", function(){
10607 this.clearOpacity();
10616 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10617 * using the "endOpacity" config option.
10620 // default: fade out from the element's current opacity to 0
10623 // custom: fade out from the element's current opacity to 25% over 2 seconds
10624 el.fadeOut({ endOpacity: .25, duration: 2});
10626 // common config options shown with default values
10628 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10635 * @param {Object} options (optional) Object literal with any of the Fx config options
10636 * @return {Roo.Element} The Element
10638 fadeOut : function(o){
10639 var el = this.getFxEl();
10641 el.queueFx(o, function(){
10642 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10643 o, null, .5, "easeOut", function(){
10644 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10645 this.dom.style.display = "none";
10647 this.dom.style.visibility = "hidden";
10649 this.clearOpacity();
10657 * Animates the transition of an element's dimensions from a starting height/width
10658 * to an ending height/width.
10661 // change height and width to 100x100 pixels
10662 el.scale(100, 100);
10664 // common config options shown with default values. The height and width will default to
10665 // the element's existing values if passed as null.
10668 [element's height], {
10673 * @param {Number} width The new width (pass undefined to keep the original width)
10674 * @param {Number} height The new height (pass undefined to keep the original height)
10675 * @param {Object} options (optional) Object literal with any of the Fx config options
10676 * @return {Roo.Element} The Element
10678 scale : function(w, h, o){
10679 this.shift(Roo.apply({}, o, {
10687 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10688 * Any of these properties not specified in the config object will not be changed. This effect
10689 * requires that at least one new dimension, position or opacity setting must be passed in on
10690 * the config object in order for the function to have any effect.
10693 // slide the element horizontally to x position 200 while changing the height and opacity
10694 el.shift({ x: 200, height: 50, opacity: .8 });
10696 // common config options shown with default values.
10698 width: [element's width],
10699 height: [element's height],
10700 x: [element's x position],
10701 y: [element's y position],
10702 opacity: [element's opacity],
10707 * @param {Object} options Object literal with any of the Fx config options
10708 * @return {Roo.Element} The Element
10710 shift : function(o){
10711 var el = this.getFxEl();
10713 el.queueFx(o, function(){
10714 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10715 if(w !== undefined){
10716 a.width = {to: this.adjustWidth(w)};
10718 if(h !== undefined){
10719 a.height = {to: this.adjustHeight(h)};
10721 if(x !== undefined || y !== undefined){
10723 x !== undefined ? x : this.getX(),
10724 y !== undefined ? y : this.getY()
10727 if(op !== undefined){
10728 a.opacity = {to: op};
10730 if(o.xy !== undefined){
10731 a.points = {to: o.xy};
10733 arguments.callee.anim = this.fxanim(a,
10734 o, 'motion', .35, "easeOut", function(){
10742 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10743 * ending point of the effect.
10746 // default: slide the element downward while fading out
10749 // custom: slide the element out to the right with a 2-second duration
10750 el.ghost('r', { duration: 2 });
10752 // common config options shown with default values
10760 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10761 * @param {Object} options (optional) Object literal with any of the Fx config options
10762 * @return {Roo.Element} The Element
10764 ghost : function(anchor, o){
10765 var el = this.getFxEl();
10768 el.queueFx(o, function(){
10769 anchor = anchor || "b";
10771 // restore values after effect
10772 var r = this.getFxRestore();
10773 var w = this.getWidth(),
10774 h = this.getHeight();
10776 var st = this.dom.style;
10778 var after = function(){
10780 el.setDisplayed(false);
10786 el.setPositioning(r.pos);
10787 st.width = r.width;
10788 st.height = r.height;
10793 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10794 switch(anchor.toLowerCase()){
10821 arguments.callee.anim = this.fxanim(a,
10831 * Ensures that all effects queued after syncFx is called on the element are
10832 * run concurrently. This is the opposite of {@link #sequenceFx}.
10833 * @return {Roo.Element} The Element
10835 syncFx : function(){
10836 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10845 * Ensures that all effects queued after sequenceFx is called on the element are
10846 * run in sequence. This is the opposite of {@link #syncFx}.
10847 * @return {Roo.Element} The Element
10849 sequenceFx : function(){
10850 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10852 concurrent : false,
10859 nextFx : function(){
10860 var ef = this.fxQueue[0];
10867 * Returns true if the element has any effects actively running or queued, else returns false.
10868 * @return {Boolean} True if element has active effects, else false
10870 hasActiveFx : function(){
10871 return this.fxQueue && this.fxQueue[0];
10875 * Stops any running effects and clears the element's internal effects queue if it contains
10876 * any additional effects that haven't started yet.
10877 * @return {Roo.Element} The Element
10879 stopFx : function(){
10880 if(this.hasActiveFx()){
10881 var cur = this.fxQueue[0];
10882 if(cur && cur.anim && cur.anim.isAnimated()){
10883 this.fxQueue = [cur]; // clear out others
10884 cur.anim.stop(true);
10891 beforeFx : function(o){
10892 if(this.hasActiveFx() && !o.concurrent){
10903 * Returns true if the element is currently blocking so that no other effect can be queued
10904 * until this effect is finished, else returns false if blocking is not set. This is commonly
10905 * used to ensure that an effect initiated by a user action runs to completion prior to the
10906 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10907 * @return {Boolean} True if blocking, else false
10909 hasFxBlock : function(){
10910 var q = this.fxQueue;
10911 return q && q[0] && q[0].block;
10915 queueFx : function(o, fn){
10919 if(!this.hasFxBlock()){
10920 Roo.applyIf(o, this.fxDefaults);
10922 var run = this.beforeFx(o);
10923 fn.block = o.block;
10924 this.fxQueue.push(fn);
10936 fxWrap : function(pos, o, vis){
10938 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10941 wrapXY = this.getXY();
10943 var div = document.createElement("div");
10944 div.style.visibility = vis;
10945 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10946 wrap.setPositioning(pos);
10947 if(wrap.getStyle("position") == "static"){
10948 wrap.position("relative");
10950 this.clearPositioning('auto');
10952 wrap.dom.appendChild(this.dom);
10954 wrap.setXY(wrapXY);
10961 fxUnwrap : function(wrap, pos, o){
10962 this.clearPositioning();
10963 this.setPositioning(pos);
10965 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10971 getFxRestore : function(){
10972 var st = this.dom.style;
10973 return {pos: this.getPositioning(), width: st.width, height : st.height};
10977 afterFx : function(o){
10979 this.applyStyles(o.afterStyle);
10982 this.addClass(o.afterCls);
10984 if(o.remove === true){
10987 Roo.callback(o.callback, o.scope, [this]);
10989 this.fxQueue.shift();
10995 getFxEl : function(){ // support for composite element fx
10996 return Roo.get(this.dom);
11000 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
11001 animType = animType || 'run';
11003 var anim = Roo.lib.Anim[animType](
11005 (opt.duration || defaultDur) || .35,
11006 (opt.easing || defaultEase) || 'easeOut',
11008 Roo.callback(cb, this);
11017 // backwords compat
11018 Roo.Fx.resize = Roo.Fx.scale;
11020 //When included, Roo.Fx is automatically applied to Element so that all basic
11021 //effects are available directly via the Element API
11022 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
11024 * Ext JS Library 1.1.1
11025 * Copyright(c) 2006-2007, Ext JS, LLC.
11027 * Originally Released Under LGPL - original licence link has changed is not relivant.
11030 * <script type="text/javascript">
11035 * @class Roo.CompositeElement
11036 * Standard composite class. Creates a Roo.Element for every element in the collection.
11038 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11039 * actions will be performed on all the elements in this collection.</b>
11041 * All methods return <i>this</i> and can be chained.
11043 var els = Roo.select("#some-el div.some-class", true);
11044 // or select directly from an existing element
11045 var el = Roo.get('some-el');
11046 el.select('div.some-class', true);
11048 els.setWidth(100); // all elements become 100 width
11049 els.hide(true); // all elements fade out and hide
11051 els.setWidth(100).hide(true);
11054 Roo.CompositeElement = function(els){
11055 this.elements = [];
11056 this.addElements(els);
11058 Roo.CompositeElement.prototype = {
11060 addElements : function(els){
11064 if(typeof els == "string"){
11065 els = Roo.Element.selectorFunction(els);
11067 var yels = this.elements;
11068 var index = yels.length-1;
11069 for(var i = 0, len = els.length; i < len; i++) {
11070 yels[++index] = Roo.get(els[i]);
11076 * Clears this composite and adds the elements returned by the passed selector.
11077 * @param {String/Array} els A string CSS selector, an array of elements or an element
11078 * @return {CompositeElement} this
11080 fill : function(els){
11081 this.elements = [];
11087 * Filters this composite to only elements that match the passed selector.
11088 * @param {String} selector A string CSS selector
11089 * @param {Boolean} inverse return inverse filter (not matches)
11090 * @return {CompositeElement} this
11092 filter : function(selector, inverse){
11094 inverse = inverse || false;
11095 this.each(function(el){
11096 var match = inverse ? !el.is(selector) : el.is(selector);
11098 els[els.length] = el.dom;
11105 invoke : function(fn, args){
11106 var els = this.elements;
11107 for(var i = 0, len = els.length; i < len; i++) {
11108 Roo.Element.prototype[fn].apply(els[i], args);
11113 * Adds elements to this composite.
11114 * @param {String/Array} els A string CSS selector, an array of elements or an element
11115 * @return {CompositeElement} this
11117 add : function(els){
11118 if(typeof els == "string"){
11119 this.addElements(Roo.Element.selectorFunction(els));
11120 }else if(els.length !== undefined){
11121 this.addElements(els);
11123 this.addElements([els]);
11128 * Calls the passed function passing (el, this, index) for each element in this composite.
11129 * @param {Function} fn The function to call
11130 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11131 * @return {CompositeElement} this
11133 each : function(fn, scope){
11134 var els = this.elements;
11135 for(var i = 0, len = els.length; i < len; i++){
11136 if(fn.call(scope || els[i], els[i], this, i) === false) {
11144 * Returns the Element object at the specified index
11145 * @param {Number} index
11146 * @return {Roo.Element}
11148 item : function(index){
11149 return this.elements[index] || null;
11153 * Returns the first Element
11154 * @return {Roo.Element}
11156 first : function(){
11157 return this.item(0);
11161 * Returns the last Element
11162 * @return {Roo.Element}
11165 return this.item(this.elements.length-1);
11169 * Returns the number of elements in this composite
11172 getCount : function(){
11173 return this.elements.length;
11177 * Returns true if this composite contains the passed element
11180 contains : function(el){
11181 return this.indexOf(el) !== -1;
11185 * Returns true if this composite contains the passed element
11188 indexOf : function(el){
11189 return this.elements.indexOf(Roo.get(el));
11194 * Removes the specified element(s).
11195 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11196 * or an array of any of those.
11197 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11198 * @return {CompositeElement} this
11200 removeElement : function(el, removeDom){
11201 if(el instanceof Array){
11202 for(var i = 0, len = el.length; i < len; i++){
11203 this.removeElement(el[i]);
11207 var index = typeof el == 'number' ? el : this.indexOf(el);
11210 var d = this.elements[index];
11214 d.parentNode.removeChild(d);
11217 this.elements.splice(index, 1);
11223 * Replaces the specified element with the passed element.
11224 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11226 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11227 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11228 * @return {CompositeElement} this
11230 replaceElement : function(el, replacement, domReplace){
11231 var index = typeof el == 'number' ? el : this.indexOf(el);
11234 this.elements[index].replaceWith(replacement);
11236 this.elements.splice(index, 1, Roo.get(replacement))
11243 * Removes all elements.
11245 clear : function(){
11246 this.elements = [];
11250 Roo.CompositeElement.createCall = function(proto, fnName){
11251 if(!proto[fnName]){
11252 proto[fnName] = function(){
11253 return this.invoke(fnName, arguments);
11257 for(var fnName in Roo.Element.prototype){
11258 if(typeof Roo.Element.prototype[fnName] == "function"){
11259 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11265 * Ext JS Library 1.1.1
11266 * Copyright(c) 2006-2007, Ext JS, LLC.
11268 * Originally Released Under LGPL - original licence link has changed is not relivant.
11271 * <script type="text/javascript">
11275 * @class Roo.CompositeElementLite
11276 * @extends Roo.CompositeElement
11277 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11279 var els = Roo.select("#some-el div.some-class");
11280 // or select directly from an existing element
11281 var el = Roo.get('some-el');
11282 el.select('div.some-class');
11284 els.setWidth(100); // all elements become 100 width
11285 els.hide(true); // all elements fade out and hide
11287 els.setWidth(100).hide(true);
11288 </code></pre><br><br>
11289 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11290 * actions will be performed on all the elements in this collection.</b>
11292 Roo.CompositeElementLite = function(els){
11293 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11294 this.el = new Roo.Element.Flyweight();
11296 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11297 addElements : function(els){
11299 if(els instanceof Array){
11300 this.elements = this.elements.concat(els);
11302 var yels = this.elements;
11303 var index = yels.length-1;
11304 for(var i = 0, len = els.length; i < len; i++) {
11305 yels[++index] = els[i];
11311 invoke : function(fn, args){
11312 var els = this.elements;
11314 for(var i = 0, len = els.length; i < len; i++) {
11316 Roo.Element.prototype[fn].apply(el, args);
11321 * Returns a flyweight Element of the dom element object at the specified index
11322 * @param {Number} index
11323 * @return {Roo.Element}
11325 item : function(index){
11326 if(!this.elements[index]){
11329 this.el.dom = this.elements[index];
11333 // fixes scope with flyweight
11334 addListener : function(eventName, handler, scope, opt){
11335 var els = this.elements;
11336 for(var i = 0, len = els.length; i < len; i++) {
11337 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11343 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11344 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11345 * a reference to the dom node, use el.dom.</b>
11346 * @param {Function} fn The function to call
11347 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11348 * @return {CompositeElement} this
11350 each : function(fn, scope){
11351 var els = this.elements;
11353 for(var i = 0, len = els.length; i < len; i++){
11355 if(fn.call(scope || el, el, this, i) === false){
11362 indexOf : function(el){
11363 return this.elements.indexOf(Roo.getDom(el));
11366 replaceElement : function(el, replacement, domReplace){
11367 var index = typeof el == 'number' ? el : this.indexOf(el);
11369 replacement = Roo.getDom(replacement);
11371 var d = this.elements[index];
11372 d.parentNode.insertBefore(replacement, d);
11373 d.parentNode.removeChild(d);
11375 this.elements.splice(index, 1, replacement);
11380 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11384 * Ext JS Library 1.1.1
11385 * Copyright(c) 2006-2007, Ext JS, LLC.
11387 * Originally Released Under LGPL - original licence link has changed is not relivant.
11390 * <script type="text/javascript">
11396 * @class Roo.data.Connection
11397 * @extends Roo.util.Observable
11398 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11399 * either to a configured URL, or to a URL specified at request time.<br><br>
11401 * Requests made by this class are asynchronous, and will return immediately. No data from
11402 * the server will be available to the statement immediately following the {@link #request} call.
11403 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11405 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11406 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11407 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11408 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11409 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11410 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11411 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11412 * standard DOM methods.
11414 * @param {Object} config a configuration object.
11416 Roo.data.Connection = function(config){
11417 Roo.apply(this, config);
11420 * @event beforerequest
11421 * Fires before a network request is made to retrieve a data object.
11422 * @param {Connection} conn This Connection object.
11423 * @param {Object} options The options config object passed to the {@link #request} method.
11425 "beforerequest" : true,
11427 * @event requestcomplete
11428 * Fires if the request was successfully completed.
11429 * @param {Connection} conn This Connection object.
11430 * @param {Object} response The XHR object containing the response data.
11431 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11432 * @param {Object} options The options config object passed to the {@link #request} method.
11434 "requestcomplete" : true,
11436 * @event requestexception
11437 * Fires if an error HTTP status was returned from the server.
11438 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11439 * @param {Connection} conn This Connection object.
11440 * @param {Object} response The XHR object containing the response data.
11441 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11442 * @param {Object} options The options config object passed to the {@link #request} method.
11444 "requestexception" : true
11446 Roo.data.Connection.superclass.constructor.call(this);
11449 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11451 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11454 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11455 * extra parameters to each request made by this object. (defaults to undefined)
11458 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11459 * to each request made by this object. (defaults to undefined)
11462 * @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)
11465 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11469 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11475 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11478 disableCaching: true,
11481 * Sends an HTTP request to a remote server.
11482 * @param {Object} options An object which may contain the following properties:<ul>
11483 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11484 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11485 * request, a url encoded string or a function to call to get either.</li>
11486 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11487 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11488 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11489 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11490 * <li>options {Object} The parameter to the request call.</li>
11491 * <li>success {Boolean} True if the request succeeded.</li>
11492 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11494 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11495 * The callback is passed the following parameters:<ul>
11496 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11497 * <li>options {Object} The parameter to the request call.</li>
11499 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11500 * The callback is passed the following parameters:<ul>
11501 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11502 * <li>options {Object} The parameter to the request call.</li>
11504 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11505 * for the callback function. Defaults to the browser window.</li>
11506 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11507 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11508 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11509 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11510 * params for the post data. Any params will be appended to the URL.</li>
11511 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11513 * @return {Number} transactionId
11515 request : function(o){
11516 if(this.fireEvent("beforerequest", this, o) !== false){
11519 if(typeof p == "function"){
11520 p = p.call(o.scope||window, o);
11522 if(typeof p == "object"){
11523 p = Roo.urlEncode(o.params);
11525 if(this.extraParams){
11526 var extras = Roo.urlEncode(this.extraParams);
11527 p = p ? (p + '&' + extras) : extras;
11530 var url = o.url || this.url;
11531 if(typeof url == 'function'){
11532 url = url.call(o.scope||window, o);
11536 var form = Roo.getDom(o.form);
11537 url = url || form.action;
11539 var enctype = form.getAttribute("enctype");
11540 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11541 return this.doFormUpload(o, p, url);
11543 var f = Roo.lib.Ajax.serializeForm(form);
11544 p = p ? (p + '&' + f) : f;
11547 var hs = o.headers;
11548 if(this.defaultHeaders){
11549 hs = Roo.apply(hs || {}, this.defaultHeaders);
11556 success: this.handleResponse,
11557 failure: this.handleFailure,
11559 argument: {options: o},
11560 timeout : o.timeout || this.timeout
11563 var method = o.method||this.method||(p ? "POST" : "GET");
11565 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11566 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11569 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11573 }else if(this.autoAbort !== false){
11577 if((method == 'GET' && p) || o.xmlData){
11578 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11581 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11582 return this.transId;
11584 Roo.callback(o.callback, o.scope, [o, null, null]);
11590 * Determine whether this object has a request outstanding.
11591 * @param {Number} transactionId (Optional) defaults to the last transaction
11592 * @return {Boolean} True if there is an outstanding request.
11594 isLoading : function(transId){
11596 return Roo.lib.Ajax.isCallInProgress(transId);
11598 return this.transId ? true : false;
11603 * Aborts any outstanding request.
11604 * @param {Number} transactionId (Optional) defaults to the last transaction
11606 abort : function(transId){
11607 if(transId || this.isLoading()){
11608 Roo.lib.Ajax.abort(transId || this.transId);
11613 handleResponse : function(response){
11614 this.transId = false;
11615 var options = response.argument.options;
11616 response.argument = options ? options.argument : null;
11617 this.fireEvent("requestcomplete", this, response, options);
11618 Roo.callback(options.success, options.scope, [response, options]);
11619 Roo.callback(options.callback, options.scope, [options, true, response]);
11623 handleFailure : function(response, e){
11624 this.transId = false;
11625 var options = response.argument.options;
11626 response.argument = options ? options.argument : null;
11627 this.fireEvent("requestexception", this, response, options, e);
11628 Roo.callback(options.failure, options.scope, [response, options]);
11629 Roo.callback(options.callback, options.scope, [options, false, response]);
11633 doFormUpload : function(o, ps, url){
11635 var frame = document.createElement('iframe');
11638 frame.className = 'x-hidden';
11640 frame.src = Roo.SSL_SECURE_URL;
11642 document.body.appendChild(frame);
11645 document.frames[id].name = id;
11648 var form = Roo.getDom(o.form);
11650 form.method = 'POST';
11651 form.enctype = form.encoding = 'multipart/form-data';
11657 if(ps){ // add dynamic params
11659 ps = Roo.urlDecode(ps, false);
11661 if(ps.hasOwnProperty(k)){
11662 hd = document.createElement('input');
11663 hd.type = 'hidden';
11666 form.appendChild(hd);
11673 var r = { // bogus response object
11678 r.argument = o ? o.argument : null;
11683 doc = frame.contentWindow.document;
11685 doc = (frame.contentDocument || window.frames[id].document);
11687 if(doc && doc.body){
11688 r.responseText = doc.body.innerHTML;
11690 if(doc && doc.XMLDocument){
11691 r.responseXML = doc.XMLDocument;
11693 r.responseXML = doc;
11700 Roo.EventManager.removeListener(frame, 'load', cb, this);
11702 this.fireEvent("requestcomplete", this, r, o);
11703 Roo.callback(o.success, o.scope, [r, o]);
11704 Roo.callback(o.callback, o.scope, [o, true, r]);
11706 setTimeout(function(){document.body.removeChild(frame);}, 100);
11709 Roo.EventManager.on(frame, 'load', cb, this);
11712 if(hiddens){ // remove dynamic params
11713 for(var i = 0, len = hiddens.length; i < len; i++){
11714 form.removeChild(hiddens[i]);
11721 * Ext JS Library 1.1.1
11722 * Copyright(c) 2006-2007, Ext JS, LLC.
11724 * Originally Released Under LGPL - original licence link has changed is not relivant.
11727 * <script type="text/javascript">
11731 * Global Ajax request class.
11734 * @extends Roo.data.Connection
11737 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11738 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11739 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11740 * @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)
11741 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11742 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11743 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11745 Roo.Ajax = new Roo.data.Connection({
11754 * Serialize the passed form into a url encoded string
11756 * @param {String/HTMLElement} form
11759 serializeForm : function(form){
11760 return Roo.lib.Ajax.serializeForm(form);
11764 * Ext JS Library 1.1.1
11765 * Copyright(c) 2006-2007, Ext JS, LLC.
11767 * Originally Released Under LGPL - original licence link has changed is not relivant.
11770 * <script type="text/javascript">
11775 * @class Roo.UpdateManager
11776 * @extends Roo.util.Observable
11777 * Provides AJAX-style update for Element object.<br><br>
11780 * // Get it from a Roo.Element object
11781 * var el = Roo.get("foo");
11782 * var mgr = el.getUpdateManager();
11783 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11785 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11787 * // or directly (returns the same UpdateManager instance)
11788 * var mgr = new Roo.UpdateManager("myElementId");
11789 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11790 * mgr.on("update", myFcnNeedsToKnow);
11792 // short handed call directly from the element object
11793 Roo.get("foo").load({
11797 text: "Loading Foo..."
11801 * Create new UpdateManager directly.
11802 * @param {String/HTMLElement/Roo.Element} el The element to update
11803 * @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).
11805 Roo.UpdateManager = function(el, forceNew){
11807 if(!forceNew && el.updateManager){
11808 return el.updateManager;
11811 * The Element object
11812 * @type Roo.Element
11816 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11819 this.defaultUrl = null;
11823 * @event beforeupdate
11824 * Fired before an update is made, return false from your handler and the update is cancelled.
11825 * @param {Roo.Element} el
11826 * @param {String/Object/Function} url
11827 * @param {String/Object} params
11829 "beforeupdate": true,
11832 * Fired after successful update is made.
11833 * @param {Roo.Element} el
11834 * @param {Object} oResponseObject The response Object
11839 * Fired on update failure.
11840 * @param {Roo.Element} el
11841 * @param {Object} oResponseObject The response Object
11845 var d = Roo.UpdateManager.defaults;
11847 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11850 this.sslBlankUrl = d.sslBlankUrl;
11852 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11855 this.disableCaching = d.disableCaching;
11857 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11860 this.indicatorText = d.indicatorText;
11862 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11865 this.showLoadIndicator = d.showLoadIndicator;
11867 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11870 this.timeout = d.timeout;
11873 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11876 this.loadScripts = d.loadScripts;
11879 * Transaction object of current executing transaction
11881 this.transaction = null;
11886 this.autoRefreshProcId = null;
11888 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11891 this.refreshDelegate = this.refresh.createDelegate(this);
11893 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11896 this.updateDelegate = this.update.createDelegate(this);
11898 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11901 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11905 this.successDelegate = this.processSuccess.createDelegate(this);
11909 this.failureDelegate = this.processFailure.createDelegate(this);
11911 if(!this.renderer){
11913 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11915 this.renderer = new Roo.UpdateManager.BasicRenderer();
11918 Roo.UpdateManager.superclass.constructor.call(this);
11921 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11923 * Get the Element this UpdateManager is bound to
11924 * @return {Roo.Element} The element
11926 getEl : function(){
11930 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11931 * @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:
11934 url: "your-url.php",<br/>
11935 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11936 callback: yourFunction,<br/>
11937 scope: yourObject, //(optional scope) <br/>
11938 discardUrl: false, <br/>
11939 nocache: false,<br/>
11940 text: "Loading...",<br/>
11942 scripts: false<br/>
11945 * The only required property is url. The optional properties nocache, text and scripts
11946 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11947 * @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}
11948 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11949 * @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.
11951 update : function(url, params, callback, discardUrl){
11952 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11953 var method = this.method,
11955 if(typeof url == "object"){ // must be config object
11958 params = params || cfg.params;
11959 callback = callback || cfg.callback;
11960 discardUrl = discardUrl || cfg.discardUrl;
11961 if(callback && cfg.scope){
11962 callback = callback.createDelegate(cfg.scope);
11964 if(typeof cfg.method != "undefined"){method = cfg.method;};
11965 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11966 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11967 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11968 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11970 this.showLoading();
11972 this.defaultUrl = url;
11974 if(typeof url == "function"){
11975 url = url.call(this);
11978 method = method || (params ? "POST" : "GET");
11979 if(method == "GET"){
11980 url = this.prepareUrl(url);
11983 var o = Roo.apply(cfg ||{}, {
11986 success: this.successDelegate,
11987 failure: this.failureDelegate,
11988 callback: undefined,
11989 timeout: (this.timeout*1000),
11990 argument: {"url": url, "form": null, "callback": callback, "params": params}
11992 Roo.log("updated manager called with timeout of " + o.timeout);
11993 this.transaction = Roo.Ajax.request(o);
11998 * 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.
11999 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
12000 * @param {String/HTMLElement} form The form Id or form element
12001 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
12002 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
12003 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
12005 formUpdate : function(form, url, reset, callback){
12006 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
12007 if(typeof url == "function"){
12008 url = url.call(this);
12010 form = Roo.getDom(form);
12011 this.transaction = Roo.Ajax.request({
12014 success: this.successDelegate,
12015 failure: this.failureDelegate,
12016 timeout: (this.timeout*1000),
12017 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
12019 this.showLoading.defer(1, this);
12024 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
12025 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12027 refresh : function(callback){
12028 if(this.defaultUrl == null){
12031 this.update(this.defaultUrl, null, callback, true);
12035 * Set this element to auto refresh.
12036 * @param {Number} interval How often to update (in seconds).
12037 * @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)
12038 * @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}
12039 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12040 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
12042 startAutoRefresh : function(interval, url, params, callback, refreshNow){
12044 this.update(url || this.defaultUrl, params, callback, true);
12046 if(this.autoRefreshProcId){
12047 clearInterval(this.autoRefreshProcId);
12049 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
12053 * Stop auto refresh on this element.
12055 stopAutoRefresh : function(){
12056 if(this.autoRefreshProcId){
12057 clearInterval(this.autoRefreshProcId);
12058 delete this.autoRefreshProcId;
12062 isAutoRefreshing : function(){
12063 return this.autoRefreshProcId ? true : false;
12066 * Called to update the element to "Loading" state. Override to perform custom action.
12068 showLoading : function(){
12069 if(this.showLoadIndicator){
12070 this.el.update(this.indicatorText);
12075 * Adds unique parameter to query string if disableCaching = true
12078 prepareUrl : function(url){
12079 if(this.disableCaching){
12080 var append = "_dc=" + (new Date().getTime());
12081 if(url.indexOf("?") !== -1){
12082 url += "&" + append;
12084 url += "?" + append;
12093 processSuccess : function(response){
12094 this.transaction = null;
12095 if(response.argument.form && response.argument.reset){
12096 try{ // put in try/catch since some older FF releases had problems with this
12097 response.argument.form.reset();
12100 if(this.loadScripts){
12101 this.renderer.render(this.el, response, this,
12102 this.updateComplete.createDelegate(this, [response]));
12104 this.renderer.render(this.el, response, this);
12105 this.updateComplete(response);
12109 updateComplete : function(response){
12110 this.fireEvent("update", this.el, response);
12111 if(typeof response.argument.callback == "function"){
12112 response.argument.callback(this.el, true, response);
12119 processFailure : function(response){
12120 this.transaction = null;
12121 this.fireEvent("failure", this.el, response);
12122 if(typeof response.argument.callback == "function"){
12123 response.argument.callback(this.el, false, response);
12128 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12129 * @param {Object} renderer The object implementing the render() method
12131 setRenderer : function(renderer){
12132 this.renderer = renderer;
12135 getRenderer : function(){
12136 return this.renderer;
12140 * Set the defaultUrl used for updates
12141 * @param {String/Function} defaultUrl The url or a function to call to get the url
12143 setDefaultUrl : function(defaultUrl){
12144 this.defaultUrl = defaultUrl;
12148 * Aborts the executing transaction
12150 abort : function(){
12151 if(this.transaction){
12152 Roo.Ajax.abort(this.transaction);
12157 * Returns true if an update is in progress
12158 * @return {Boolean}
12160 isUpdating : function(){
12161 if(this.transaction){
12162 return Roo.Ajax.isLoading(this.transaction);
12169 * @class Roo.UpdateManager.defaults
12170 * @static (not really - but it helps the doc tool)
12171 * The defaults collection enables customizing the default properties of UpdateManager
12173 Roo.UpdateManager.defaults = {
12175 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12181 * True to process scripts by default (Defaults to false).
12184 loadScripts : false,
12187 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12190 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12192 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12195 disableCaching : false,
12197 * Whether to show indicatorText when loading (Defaults to true).
12200 showLoadIndicator : true,
12202 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12205 indicatorText : '<div class="loading-indicator">Loading...</div>'
12209 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12211 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12212 * @param {String/HTMLElement/Roo.Element} el The element to update
12213 * @param {String} url The url
12214 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12215 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12218 * @member Roo.UpdateManager
12220 Roo.UpdateManager.updateElement = function(el, url, params, options){
12221 var um = Roo.get(el, true).getUpdateManager();
12222 Roo.apply(um, options);
12223 um.update(url, params, options ? options.callback : null);
12225 // alias for backwards compat
12226 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12228 * @class Roo.UpdateManager.BasicRenderer
12229 * Default Content renderer. Updates the elements innerHTML with the responseText.
12231 Roo.UpdateManager.BasicRenderer = function(){};
12233 Roo.UpdateManager.BasicRenderer.prototype = {
12235 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12236 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12237 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12238 * @param {Roo.Element} el The element being rendered
12239 * @param {Object} response The YUI Connect response object
12240 * @param {UpdateManager} updateManager The calling update manager
12241 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12243 render : function(el, response, updateManager, callback){
12244 el.update(response.responseText, updateManager.loadScripts, callback);
12250 * (c)) Alan Knowles
12256 * @class Roo.DomTemplate
12257 * @extends Roo.Template
12258 * An effort at a dom based template engine..
12260 * Similar to XTemplate, except it uses dom parsing to create the template..
12262 * Supported features:
12267 {a_variable} - output encoded.
12268 {a_variable.format:("Y-m-d")} - call a method on the variable
12269 {a_variable:raw} - unencoded output
12270 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12271 {a_variable:this.method_on_template(...)} - call a method on the template object.
12276 <div roo-for="a_variable or condition.."></div>
12277 <div roo-if="a_variable or condition"></div>
12278 <div roo-exec="some javascript"></div>
12279 <div roo-name="named_template"></div>
12284 Roo.DomTemplate = function()
12286 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12293 Roo.extend(Roo.DomTemplate, Roo.Template, {
12295 * id counter for sub templates.
12299 * flag to indicate if dom parser is inside a pre,
12300 * it will strip whitespace if not.
12305 * The various sub templates
12313 * basic tag replacing syntax
12316 * // you can fake an object call by doing this
12320 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12321 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12323 iterChild : function (node, method) {
12325 var oldPre = this.inPre;
12326 if (node.tagName == 'PRE') {
12329 for( var i = 0; i < node.childNodes.length; i++) {
12330 method.call(this, node.childNodes[i]);
12332 this.inPre = oldPre;
12338 * compile the template
12340 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12343 compile: function()
12347 // covert the html into DOM...
12351 doc = document.implementation.createHTMLDocument("");
12352 doc.documentElement.innerHTML = this.html ;
12353 div = doc.documentElement;
12355 // old IE... - nasty -- it causes all sorts of issues.. with
12356 // images getting pulled from server..
12357 div = document.createElement('div');
12358 div.innerHTML = this.html;
12360 //doc.documentElement.innerHTML = htmlBody
12366 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12368 var tpls = this.tpls;
12370 // create a top level template from the snippet..
12372 //Roo.log(div.innerHTML);
12379 body : div.innerHTML,
12392 Roo.each(tpls, function(tp){
12393 this.compileTpl(tp);
12394 this.tpls[tp.id] = tp;
12397 this.master = tpls[0];
12403 compileNode : function(node, istop) {
12408 // skip anything not a tag..
12409 if (node.nodeType != 1) {
12410 if (node.nodeType == 3 && !this.inPre) {
12411 // reduce white space..
12412 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12435 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12436 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12437 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12438 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12444 // just itterate children..
12445 this.iterChild(node,this.compileNode);
12448 tpl.uid = this.id++;
12449 tpl.value = node.getAttribute('roo-' + tpl.attr);
12450 node.removeAttribute('roo-'+ tpl.attr);
12451 if (tpl.attr != 'name') {
12452 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12453 node.parentNode.replaceChild(placeholder, node);
12456 var placeholder = document.createElement('span');
12457 placeholder.className = 'roo-tpl-' + tpl.value;
12458 node.parentNode.replaceChild(placeholder, node);
12461 // parent now sees '{domtplXXXX}
12462 this.iterChild(node,this.compileNode);
12464 // we should now have node body...
12465 var div = document.createElement('div');
12466 div.appendChild(node);
12468 // this has the unfortunate side effect of converting tagged attributes
12469 // eg. href="{...}" into %7C...%7D
12470 // this has been fixed by searching for those combo's although it's a bit hacky..
12473 tpl.body = div.innerHTML;
12480 switch (tpl.value) {
12481 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12482 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12483 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12488 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12492 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12496 tpl.id = tpl.value; // replace non characters???
12502 this.tpls.push(tpl);
12512 * Compile a segment of the template into a 'sub-template'
12518 compileTpl : function(tpl)
12520 var fm = Roo.util.Format;
12521 var useF = this.disableFormats !== true;
12523 var sep = Roo.isGecko ? "+\n" : ",\n";
12525 var undef = function(str) {
12526 Roo.debug && Roo.log("Property not found :" + str);
12530 //Roo.log(tpl.body);
12534 var fn = function(m, lbrace, name, format, args)
12537 //Roo.log(arguments);
12538 args = args ? args.replace(/\\'/g,"'") : args;
12539 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12540 if (typeof(format) == 'undefined') {
12541 format = 'htmlEncode';
12543 if (format == 'raw' ) {
12547 if(name.substr(0, 6) == 'domtpl'){
12548 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12551 // build an array of options to determine if value is undefined..
12553 // basically get 'xxxx.yyyy' then do
12554 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12555 // (function () { Roo.log("Property not found"); return ''; })() :
12560 Roo.each(name.split('.'), function(st) {
12561 lookfor += (lookfor.length ? '.': '') + st;
12562 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12565 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12568 if(format && useF){
12570 args = args ? ',' + args : "";
12572 if(format.substr(0, 5) != "this."){
12573 format = "fm." + format + '(';
12575 format = 'this.call("'+ format.substr(5) + '", ';
12579 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12582 if (args && args.length) {
12583 // called with xxyx.yuu:(test,test)
12585 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12587 // raw.. - :raw modifier..
12588 return "'"+ sep + udef_st + name + ")"+sep+"'";
12592 // branched to use + in gecko and [].join() in others
12594 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12595 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12598 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12599 body.push(tpl.body.replace(/(\r\n|\n)/g,
12600 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12601 body.push("'].join('');};};");
12602 body = body.join('');
12605 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12607 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12614 * same as applyTemplate, except it's done to one of the subTemplates
12615 * when using named templates, you can do:
12617 * var str = pl.applySubTemplate('your-name', values);
12620 * @param {Number} id of the template
12621 * @param {Object} values to apply to template
12622 * @param {Object} parent (normaly the instance of this object)
12624 applySubTemplate : function(id, values, parent)
12628 var t = this.tpls[id];
12632 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12633 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12637 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12644 if(t.execCall && t.execCall.call(this, values, parent)){
12648 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12654 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12655 parent = t.target ? values : parent;
12656 if(t.forCall && vs instanceof Array){
12658 for(var i = 0, len = vs.length; i < len; i++){
12660 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12662 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12664 //Roo.log(t.compiled);
12668 return buf.join('');
12671 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12676 return t.compiled.call(this, vs, parent);
12678 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12680 //Roo.log(t.compiled);
12688 applyTemplate : function(values){
12689 return this.master.compiled.call(this, values, {});
12690 //var s = this.subs;
12693 apply : function(){
12694 return this.applyTemplate.apply(this, arguments);
12699 Roo.DomTemplate.from = function(el){
12700 el = Roo.getDom(el);
12701 return new Roo.Domtemplate(el.value || el.innerHTML);
12704 * Ext JS Library 1.1.1
12705 * Copyright(c) 2006-2007, Ext JS, LLC.
12707 * Originally Released Under LGPL - original licence link has changed is not relivant.
12710 * <script type="text/javascript">
12714 * @class Roo.util.DelayedTask
12715 * Provides a convenient method of performing setTimeout where a new
12716 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12717 * You can use this class to buffer
12718 * the keypress events for a certain number of milliseconds, and perform only if they stop
12719 * for that amount of time.
12720 * @constructor The parameters to this constructor serve as defaults and are not required.
12721 * @param {Function} fn (optional) The default function to timeout
12722 * @param {Object} scope (optional) The default scope of that timeout
12723 * @param {Array} args (optional) The default Array of arguments
12725 Roo.util.DelayedTask = function(fn, scope, args){
12726 var id = null, d, t;
12728 var call = function(){
12729 var now = new Date().getTime();
12733 fn.apply(scope, args || []);
12737 * Cancels any pending timeout and queues a new one
12738 * @param {Number} delay The milliseconds to delay
12739 * @param {Function} newFn (optional) Overrides function passed to constructor
12740 * @param {Object} newScope (optional) Overrides scope passed to constructor
12741 * @param {Array} newArgs (optional) Overrides args passed to constructor
12743 this.delay = function(delay, newFn, newScope, newArgs){
12744 if(id && delay != d){
12748 t = new Date().getTime();
12750 scope = newScope || scope;
12751 args = newArgs || args;
12753 id = setInterval(call, d);
12758 * Cancel the last queued timeout
12760 this.cancel = function(){
12768 * Ext JS Library 1.1.1
12769 * Copyright(c) 2006-2007, Ext JS, LLC.
12771 * Originally Released Under LGPL - original licence link has changed is not relivant.
12774 * <script type="text/javascript">
12778 Roo.util.TaskRunner = function(interval){
12779 interval = interval || 10;
12780 var tasks = [], removeQueue = [];
12782 var running = false;
12784 var stopThread = function(){
12790 var startThread = function(){
12793 id = setInterval(runTasks, interval);
12797 var removeTask = function(task){
12798 removeQueue.push(task);
12804 var runTasks = function(){
12805 if(removeQueue.length > 0){
12806 for(var i = 0, len = removeQueue.length; i < len; i++){
12807 tasks.remove(removeQueue[i]);
12810 if(tasks.length < 1){
12815 var now = new Date().getTime();
12816 for(var i = 0, len = tasks.length; i < len; ++i){
12818 var itime = now - t.taskRunTime;
12819 if(t.interval <= itime){
12820 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12821 t.taskRunTime = now;
12822 if(rt === false || t.taskRunCount === t.repeat){
12827 if(t.duration && t.duration <= (now - t.taskStartTime)){
12834 * Queues a new task.
12835 * @param {Object} task
12837 this.start = function(task){
12839 task.taskStartTime = new Date().getTime();
12840 task.taskRunTime = 0;
12841 task.taskRunCount = 0;
12846 this.stop = function(task){
12851 this.stopAll = function(){
12853 for(var i = 0, len = tasks.length; i < len; i++){
12854 if(tasks[i].onStop){
12863 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12865 * Ext JS Library 1.1.1
12866 * Copyright(c) 2006-2007, Ext JS, LLC.
12868 * Originally Released Under LGPL - original licence link has changed is not relivant.
12871 * <script type="text/javascript">
12876 * @class Roo.util.MixedCollection
12877 * @extends Roo.util.Observable
12878 * A Collection class that maintains both numeric indexes and keys and exposes events.
12880 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12881 * collection (defaults to false)
12882 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12883 * and return the key value for that item. This is used when available to look up the key on items that
12884 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12885 * equivalent to providing an implementation for the {@link #getKey} method.
12887 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12895 * Fires when the collection is cleared.
12900 * Fires when an item is added to the collection.
12901 * @param {Number} index The index at which the item was added.
12902 * @param {Object} o The item added.
12903 * @param {String} key The key associated with the added item.
12908 * Fires when an item is replaced in the collection.
12909 * @param {String} key he key associated with the new added.
12910 * @param {Object} old The item being replaced.
12911 * @param {Object} new The new item.
12916 * Fires when an item is removed from the collection.
12917 * @param {Object} o The item being removed.
12918 * @param {String} key (optional) The key associated with the removed item.
12923 this.allowFunctions = allowFunctions === true;
12925 this.getKey = keyFn;
12927 Roo.util.MixedCollection.superclass.constructor.call(this);
12930 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12931 allowFunctions : false,
12934 * Adds an item to the collection.
12935 * @param {String} key The key to associate with the item
12936 * @param {Object} o The item to add.
12937 * @return {Object} The item added.
12939 add : function(key, o){
12940 if(arguments.length == 1){
12942 key = this.getKey(o);
12944 if(typeof key == "undefined" || key === null){
12946 this.items.push(o);
12947 this.keys.push(null);
12949 var old = this.map[key];
12951 return this.replace(key, o);
12954 this.items.push(o);
12956 this.keys.push(key);
12958 this.fireEvent("add", this.length-1, o, key);
12963 * MixedCollection has a generic way to fetch keys if you implement getKey.
12966 var mc = new Roo.util.MixedCollection();
12967 mc.add(someEl.dom.id, someEl);
12968 mc.add(otherEl.dom.id, otherEl);
12972 var mc = new Roo.util.MixedCollection();
12973 mc.getKey = function(el){
12979 // or via the constructor
12980 var mc = new Roo.util.MixedCollection(false, function(el){
12986 * @param o {Object} The item for which to find the key.
12987 * @return {Object} The key for the passed item.
12989 getKey : function(o){
12994 * Replaces an item in the collection.
12995 * @param {String} key The key associated with the item to replace, or the item to replace.
12996 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12997 * @return {Object} The new item.
12999 replace : function(key, o){
13000 if(arguments.length == 1){
13002 key = this.getKey(o);
13004 var old = this.item(key);
13005 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
13006 return this.add(key, o);
13008 var index = this.indexOfKey(key);
13009 this.items[index] = o;
13011 this.fireEvent("replace", key, old, o);
13016 * Adds all elements of an Array or an Object to the collection.
13017 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
13018 * an Array of values, each of which are added to the collection.
13020 addAll : function(objs){
13021 if(arguments.length > 1 || objs instanceof Array){
13022 var args = arguments.length > 1 ? arguments : objs;
13023 for(var i = 0, len = args.length; i < len; i++){
13027 for(var key in objs){
13028 if(this.allowFunctions || typeof objs[key] != "function"){
13029 this.add(key, objs[key]);
13036 * Executes the specified function once for every item in the collection, passing each
13037 * item as the first and only parameter. returning false from the function will stop the iteration.
13038 * @param {Function} fn The function to execute for each item.
13039 * @param {Object} scope (optional) The scope in which to execute the function.
13041 each : function(fn, scope){
13042 var items = [].concat(this.items); // each safe for removal
13043 for(var i = 0, len = items.length; i < len; i++){
13044 if(fn.call(scope || items[i], items[i], i, len) === false){
13051 * Executes the specified function once for every key in the collection, passing each
13052 * key, and its associated item as the first two parameters.
13053 * @param {Function} fn The function to execute for each item.
13054 * @param {Object} scope (optional) The scope in which to execute the function.
13056 eachKey : function(fn, scope){
13057 for(var i = 0, len = this.keys.length; i < len; i++){
13058 fn.call(scope || window, this.keys[i], this.items[i], i, len);
13063 * Returns the first item in the collection which elicits a true return value from the
13064 * passed selection function.
13065 * @param {Function} fn The selection function to execute for each item.
13066 * @param {Object} scope (optional) The scope in which to execute the function.
13067 * @return {Object} The first item in the collection which returned true from the selection function.
13069 find : function(fn, scope){
13070 for(var i = 0, len = this.items.length; i < len; i++){
13071 if(fn.call(scope || window, this.items[i], this.keys[i])){
13072 return this.items[i];
13079 * Inserts an item at the specified index in the collection.
13080 * @param {Number} index The index to insert the item at.
13081 * @param {String} key The key to associate with the new item, or the item itself.
13082 * @param {Object} o (optional) If the second parameter was a key, the new item.
13083 * @return {Object} The item inserted.
13085 insert : function(index, key, o){
13086 if(arguments.length == 2){
13088 key = this.getKey(o);
13090 if(index >= this.length){
13091 return this.add(key, o);
13094 this.items.splice(index, 0, o);
13095 if(typeof key != "undefined" && key != null){
13098 this.keys.splice(index, 0, key);
13099 this.fireEvent("add", index, o, key);
13104 * Removed an item from the collection.
13105 * @param {Object} o The item to remove.
13106 * @return {Object} The item removed.
13108 remove : function(o){
13109 return this.removeAt(this.indexOf(o));
13113 * Remove an item from a specified index in the collection.
13114 * @param {Number} index The index within the collection of the item to remove.
13116 removeAt : function(index){
13117 if(index < this.length && index >= 0){
13119 var o = this.items[index];
13120 this.items.splice(index, 1);
13121 var key = this.keys[index];
13122 if(typeof key != "undefined"){
13123 delete this.map[key];
13125 this.keys.splice(index, 1);
13126 this.fireEvent("remove", o, key);
13131 * Removed an item associated with the passed key fom the collection.
13132 * @param {String} key The key of the item to remove.
13134 removeKey : function(key){
13135 return this.removeAt(this.indexOfKey(key));
13139 * Returns the number of items in the collection.
13140 * @return {Number} the number of items in the collection.
13142 getCount : function(){
13143 return this.length;
13147 * Returns index within the collection of the passed Object.
13148 * @param {Object} o The item to find the index of.
13149 * @return {Number} index of the item.
13151 indexOf : function(o){
13152 if(!this.items.indexOf){
13153 for(var i = 0, len = this.items.length; i < len; i++){
13154 if(this.items[i] == o) {
13160 return this.items.indexOf(o);
13165 * Returns index within the collection of the passed key.
13166 * @param {String} key The key to find the index of.
13167 * @return {Number} index of the key.
13169 indexOfKey : function(key){
13170 if(!this.keys.indexOf){
13171 for(var i = 0, len = this.keys.length; i < len; i++){
13172 if(this.keys[i] == key) {
13178 return this.keys.indexOf(key);
13183 * Returns the item associated with the passed key OR index. Key has priority over index.
13184 * @param {String/Number} key The key or index of the item.
13185 * @return {Object} The item associated with the passed key.
13187 item : function(key){
13188 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13189 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13193 * Returns the item at the specified index.
13194 * @param {Number} index The index of the item.
13197 itemAt : function(index){
13198 return this.items[index];
13202 * Returns the item associated with the passed key.
13203 * @param {String/Number} key The key of the item.
13204 * @return {Object} The item associated with the passed key.
13206 key : function(key){
13207 return this.map[key];
13211 * Returns true if the collection contains the passed Object as an item.
13212 * @param {Object} o The Object to look for in the collection.
13213 * @return {Boolean} True if the collection contains the Object as an item.
13215 contains : function(o){
13216 return this.indexOf(o) != -1;
13220 * Returns true if the collection contains the passed Object as a key.
13221 * @param {String} key The key to look for in the collection.
13222 * @return {Boolean} True if the collection contains the Object as a key.
13224 containsKey : function(key){
13225 return typeof this.map[key] != "undefined";
13229 * Removes all items from the collection.
13231 clear : function(){
13236 this.fireEvent("clear");
13240 * Returns the first item in the collection.
13241 * @return {Object} the first item in the collection..
13243 first : function(){
13244 return this.items[0];
13248 * Returns the last item in the collection.
13249 * @return {Object} the last item in the collection..
13252 return this.items[this.length-1];
13255 _sort : function(property, dir, fn){
13256 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13257 fn = fn || function(a, b){
13260 var c = [], k = this.keys, items = this.items;
13261 for(var i = 0, len = items.length; i < len; i++){
13262 c[c.length] = {key: k[i], value: items[i], index: i};
13264 c.sort(function(a, b){
13265 var v = fn(a[property], b[property]) * dsc;
13267 v = (a.index < b.index ? -1 : 1);
13271 for(var i = 0, len = c.length; i < len; i++){
13272 items[i] = c[i].value;
13275 this.fireEvent("sort", this);
13279 * Sorts this collection with the passed comparison function
13280 * @param {String} direction (optional) "ASC" or "DESC"
13281 * @param {Function} fn (optional) comparison function
13283 sort : function(dir, fn){
13284 this._sort("value", dir, fn);
13288 * Sorts this collection by keys
13289 * @param {String} direction (optional) "ASC" or "DESC"
13290 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13292 keySort : function(dir, fn){
13293 this._sort("key", dir, fn || function(a, b){
13294 return String(a).toUpperCase()-String(b).toUpperCase();
13299 * Returns a range of items in this collection
13300 * @param {Number} startIndex (optional) defaults to 0
13301 * @param {Number} endIndex (optional) default to the last item
13302 * @return {Array} An array of items
13304 getRange : function(start, end){
13305 var items = this.items;
13306 if(items.length < 1){
13309 start = start || 0;
13310 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13313 for(var i = start; i <= end; i++) {
13314 r[r.length] = items[i];
13317 for(var i = start; i >= end; i--) {
13318 r[r.length] = items[i];
13325 * Filter the <i>objects</i> in this collection by a specific property.
13326 * Returns a new collection that has been filtered.
13327 * @param {String} property A property on your objects
13328 * @param {String/RegExp} value Either string that the property values
13329 * should start with or a RegExp to test against the property
13330 * @return {MixedCollection} The new filtered collection
13332 filter : function(property, value){
13333 if(!value.exec){ // not a regex
13334 value = String(value);
13335 if(value.length == 0){
13336 return this.clone();
13338 value = new RegExp("^" + Roo.escapeRe(value), "i");
13340 return this.filterBy(function(o){
13341 return o && value.test(o[property]);
13346 * Filter by a function. * Returns a new collection that has been filtered.
13347 * The passed function will be called with each
13348 * object in the collection. If the function returns true, the value is included
13349 * otherwise it is filtered.
13350 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13351 * @param {Object} scope (optional) The scope of the function (defaults to this)
13352 * @return {MixedCollection} The new filtered collection
13354 filterBy : function(fn, scope){
13355 var r = new Roo.util.MixedCollection();
13356 r.getKey = this.getKey;
13357 var k = this.keys, it = this.items;
13358 for(var i = 0, len = it.length; i < len; i++){
13359 if(fn.call(scope||this, it[i], k[i])){
13360 r.add(k[i], it[i]);
13367 * Creates a duplicate of this collection
13368 * @return {MixedCollection}
13370 clone : function(){
13371 var r = new Roo.util.MixedCollection();
13372 var k = this.keys, it = this.items;
13373 for(var i = 0, len = it.length; i < len; i++){
13374 r.add(k[i], it[i]);
13376 r.getKey = this.getKey;
13381 * Returns the item associated with the passed key or index.
13383 * @param {String/Number} key The key or index of the item.
13384 * @return {Object} The item associated with the passed key.
13386 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13388 * Ext JS Library 1.1.1
13389 * Copyright(c) 2006-2007, Ext JS, LLC.
13391 * Originally Released Under LGPL - original licence link has changed is not relivant.
13394 * <script type="text/javascript">
13397 * @class Roo.util.JSON
13398 * Modified version of Douglas Crockford"s json.js that doesn"t
13399 * mess with the Object prototype
13400 * http://www.json.org/js.html
13403 Roo.util.JSON = new (function(){
13404 var useHasOwn = {}.hasOwnProperty ? true : false;
13406 // crashes Safari in some instances
13407 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13409 var pad = function(n) {
13410 return n < 10 ? "0" + n : n;
13423 var encodeString = function(s){
13424 if (/["\\\x00-\x1f]/.test(s)) {
13425 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13430 c = b.charCodeAt();
13432 Math.floor(c / 16).toString(16) +
13433 (c % 16).toString(16);
13436 return '"' + s + '"';
13439 var encodeArray = function(o){
13440 var a = ["["], b, i, l = o.length, v;
13441 for (i = 0; i < l; i += 1) {
13443 switch (typeof v) {
13452 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13460 var encodeDate = function(o){
13461 return '"' + o.getFullYear() + "-" +
13462 pad(o.getMonth() + 1) + "-" +
13463 pad(o.getDate()) + "T" +
13464 pad(o.getHours()) + ":" +
13465 pad(o.getMinutes()) + ":" +
13466 pad(o.getSeconds()) + '"';
13470 * Encodes an Object, Array or other value
13471 * @param {Mixed} o The variable to encode
13472 * @return {String} The JSON string
13474 this.encode = function(o)
13476 // should this be extended to fully wrap stringify..
13478 if(typeof o == "undefined" || o === null){
13480 }else if(o instanceof Array){
13481 return encodeArray(o);
13482 }else if(o instanceof Date){
13483 return encodeDate(o);
13484 }else if(typeof o == "string"){
13485 return encodeString(o);
13486 }else if(typeof o == "number"){
13487 return isFinite(o) ? String(o) : "null";
13488 }else if(typeof o == "boolean"){
13491 var a = ["{"], b, i, v;
13493 if(!useHasOwn || o.hasOwnProperty(i)) {
13495 switch (typeof v) {
13504 a.push(this.encode(i), ":",
13505 v === null ? "null" : this.encode(v));
13516 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13517 * @param {String} json The JSON string
13518 * @return {Object} The resulting object
13520 this.decode = function(json){
13522 return /** eval:var:json */ eval("(" + json + ')');
13526 * Shorthand for {@link Roo.util.JSON#encode}
13527 * @member Roo encode
13529 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13531 * Shorthand for {@link Roo.util.JSON#decode}
13532 * @member Roo decode
13534 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13537 * Ext JS Library 1.1.1
13538 * Copyright(c) 2006-2007, Ext JS, LLC.
13540 * Originally Released Under LGPL - original licence link has changed is not relivant.
13543 * <script type="text/javascript">
13547 * @class Roo.util.Format
13548 * Reusable data formatting functions
13551 Roo.util.Format = function(){
13552 var trimRe = /^\s+|\s+$/g;
13555 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13556 * @param {String} value The string to truncate
13557 * @param {Number} length The maximum length to allow before truncating
13558 * @return {String} The converted text
13560 ellipsis : function(value, len){
13561 if(value && value.length > len){
13562 return value.substr(0, len-3)+"...";
13568 * Checks a reference and converts it to empty string if it is undefined
13569 * @param {Mixed} value Reference to check
13570 * @return {Mixed} Empty string if converted, otherwise the original value
13572 undef : function(value){
13573 return typeof value != "undefined" ? value : "";
13577 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13578 * @param {String} value The string to encode
13579 * @return {String} The encoded text
13581 htmlEncode : function(value){
13582 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13586 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13587 * @param {String} value The string to decode
13588 * @return {String} The decoded text
13590 htmlDecode : function(value){
13591 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13595 * Trims any whitespace from either side of a string
13596 * @param {String} value The text to trim
13597 * @return {String} The trimmed text
13599 trim : function(value){
13600 return String(value).replace(trimRe, "");
13604 * Returns a substring from within an original string
13605 * @param {String} value The original text
13606 * @param {Number} start The start index of the substring
13607 * @param {Number} length The length of the substring
13608 * @return {String} The substring
13610 substr : function(value, start, length){
13611 return String(value).substr(start, length);
13615 * Converts a string to all lower case letters
13616 * @param {String} value The text to convert
13617 * @return {String} The converted text
13619 lowercase : function(value){
13620 return String(value).toLowerCase();
13624 * Converts a string to all upper case letters
13625 * @param {String} value The text to convert
13626 * @return {String} The converted text
13628 uppercase : function(value){
13629 return String(value).toUpperCase();
13633 * Converts the first character only of a string to upper case
13634 * @param {String} value The text to convert
13635 * @return {String} The converted text
13637 capitalize : function(value){
13638 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13642 call : function(value, fn){
13643 if(arguments.length > 2){
13644 var args = Array.prototype.slice.call(arguments, 2);
13645 args.unshift(value);
13647 return /** eval:var:value */ eval(fn).apply(window, args);
13649 /** eval:var:value */
13650 return /** eval:var:value */ eval(fn).call(window, value);
13656 * safer version of Math.toFixed..??/
13657 * @param {Number/String} value The numeric value to format
13658 * @param {Number/String} value Decimal places
13659 * @return {String} The formatted currency string
13661 toFixed : function(v, n)
13663 // why not use to fixed - precision is buggered???
13665 return Math.round(v-0);
13667 var fact = Math.pow(10,n+1);
13668 v = (Math.round((v-0)*fact))/fact;
13669 var z = (''+fact).substring(2);
13670 if (v == Math.floor(v)) {
13671 return Math.floor(v) + '.' + z;
13674 // now just padd decimals..
13675 var ps = String(v).split('.');
13676 var fd = (ps[1] + z);
13677 var r = fd.substring(0,n);
13678 var rm = fd.substring(n);
13680 return ps[0] + '.' + r;
13682 r*=1; // turn it into a number;
13684 if (String(r).length != n) {
13687 r = String(r).substring(1); // chop the end off.
13690 return ps[0] + '.' + r;
13695 * Format a number as US currency
13696 * @param {Number/String} value The numeric value to format
13697 * @return {String} The formatted currency string
13699 usMoney : function(v){
13700 return '$' + Roo.util.Format.number(v);
13705 * eventually this should probably emulate php's number_format
13706 * @param {Number/String} value The numeric value to format
13707 * @param {Number} decimals number of decimal places
13708 * @return {String} The formatted currency string
13710 number : function(v,decimals)
13712 // multiply and round.
13713 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13714 var mul = Math.pow(10, decimals);
13715 var zero = String(mul).substring(1);
13716 v = (Math.round((v-0)*mul))/mul;
13718 // if it's '0' number.. then
13720 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13722 var ps = v.split('.');
13726 var r = /(\d+)(\d{3})/;
13728 while (r.test(whole)) {
13729 whole = whole.replace(r, '$1' + ',' + '$2');
13735 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13736 // does not have decimals
13737 (decimals ? ('.' + zero) : '');
13740 return whole + sub ;
13744 * Parse a value into a formatted date using the specified format pattern.
13745 * @param {Mixed} value The value to format
13746 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13747 * @return {String} The formatted date string
13749 date : function(v, format){
13753 if(!(v instanceof Date)){
13754 v = new Date(Date.parse(v));
13756 return v.dateFormat(format || Roo.util.Format.defaults.date);
13760 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13761 * @param {String} format Any valid date format string
13762 * @return {Function} The date formatting function
13764 dateRenderer : function(format){
13765 return function(v){
13766 return Roo.util.Format.date(v, format);
13771 stripTagsRE : /<\/?[^>]+>/gi,
13774 * Strips all HTML tags
13775 * @param {Mixed} value The text from which to strip tags
13776 * @return {String} The stripped text
13778 stripTags : function(v){
13779 return !v ? v : String(v).replace(this.stripTagsRE, "");
13783 Roo.util.Format.defaults = {
13787 * Ext JS Library 1.1.1
13788 * Copyright(c) 2006-2007, Ext JS, LLC.
13790 * Originally Released Under LGPL - original licence link has changed is not relivant.
13793 * <script type="text/javascript">
13800 * @class Roo.MasterTemplate
13801 * @extends Roo.Template
13802 * Provides a template that can have child templates. The syntax is:
13804 var t = new Roo.MasterTemplate(
13805 '<select name="{name}">',
13806 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13809 t.add('options', {value: 'foo', text: 'bar'});
13810 // or you can add multiple child elements in one shot
13811 t.addAll('options', [
13812 {value: 'foo', text: 'bar'},
13813 {value: 'foo2', text: 'bar2'},
13814 {value: 'foo3', text: 'bar3'}
13816 // then append, applying the master template values
13817 t.append('my-form', {name: 'my-select'});
13819 * A name attribute for the child template is not required if you have only one child
13820 * template or you want to refer to them by index.
13822 Roo.MasterTemplate = function(){
13823 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13824 this.originalHtml = this.html;
13826 var m, re = this.subTemplateRe;
13829 while(m = re.exec(this.html)){
13830 var name = m[1], content = m[2];
13835 tpl : new Roo.Template(content)
13838 st[name] = st[subIndex];
13840 st[subIndex].tpl.compile();
13841 st[subIndex].tpl.call = this.call.createDelegate(this);
13844 this.subCount = subIndex;
13847 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13849 * The regular expression used to match sub templates
13853 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13856 * Applies the passed values to a child template.
13857 * @param {String/Number} name (optional) The name or index of the child template
13858 * @param {Array/Object} values The values to be applied to the template
13859 * @return {MasterTemplate} this
13861 add : function(name, values){
13862 if(arguments.length == 1){
13863 values = arguments[0];
13866 var s = this.subs[name];
13867 s.buffer[s.buffer.length] = s.tpl.apply(values);
13872 * Applies all the passed values to a child template.
13873 * @param {String/Number} name (optional) The name or index of the child template
13874 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13875 * @param {Boolean} reset (optional) True to reset the template first
13876 * @return {MasterTemplate} this
13878 fill : function(name, values, reset){
13880 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13888 for(var i = 0, len = values.length; i < len; i++){
13889 this.add(name, values[i]);
13895 * Resets the template for reuse
13896 * @return {MasterTemplate} this
13898 reset : function(){
13900 for(var i = 0; i < this.subCount; i++){
13906 applyTemplate : function(values){
13908 var replaceIndex = -1;
13909 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13910 return s[++replaceIndex].buffer.join("");
13912 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13915 apply : function(){
13916 return this.applyTemplate.apply(this, arguments);
13919 compile : function(){return this;}
13923 * Alias for fill().
13926 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13928 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13929 * var tpl = Roo.MasterTemplate.from('element-id');
13930 * @param {String/HTMLElement} el
13931 * @param {Object} config
13934 Roo.MasterTemplate.from = function(el, config){
13935 el = Roo.getDom(el);
13936 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13939 * Ext JS Library 1.1.1
13940 * Copyright(c) 2006-2007, Ext JS, LLC.
13942 * Originally Released Under LGPL - original licence link has changed is not relivant.
13945 * <script type="text/javascript">
13950 * @class Roo.util.CSS
13951 * Utility class for manipulating CSS rules
13954 Roo.util.CSS = function(){
13956 var doc = document;
13958 var camelRe = /(-[a-z])/gi;
13959 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13963 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13964 * tag and appended to the HEAD of the document.
13965 * @param {String|Object} cssText The text containing the css rules
13966 * @param {String} id An id to add to the stylesheet for later removal
13967 * @return {StyleSheet}
13969 createStyleSheet : function(cssText, id){
13971 var head = doc.getElementsByTagName("head")[0];
13972 var nrules = doc.createElement("style");
13973 nrules.setAttribute("type", "text/css");
13975 nrules.setAttribute("id", id);
13977 if (typeof(cssText) != 'string') {
13978 // support object maps..
13979 // not sure if this a good idea..
13980 // perhaps it should be merged with the general css handling
13981 // and handle js style props.
13982 var cssTextNew = [];
13983 for(var n in cssText) {
13985 for(var k in cssText[n]) {
13986 citems.push( k + ' : ' +cssText[n][k] + ';' );
13988 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13991 cssText = cssTextNew.join("\n");
13997 head.appendChild(nrules);
13998 ss = nrules.styleSheet;
13999 ss.cssText = cssText;
14002 nrules.appendChild(doc.createTextNode(cssText));
14004 nrules.cssText = cssText;
14006 head.appendChild(nrules);
14007 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
14009 this.cacheStyleSheet(ss);
14014 * Removes a style or link tag by id
14015 * @param {String} id The id of the tag
14017 removeStyleSheet : function(id){
14018 var existing = doc.getElementById(id);
14020 existing.parentNode.removeChild(existing);
14025 * Dynamically swaps an existing stylesheet reference for a new one
14026 * @param {String} id The id of an existing link tag to remove
14027 * @param {String} url The href of the new stylesheet to include
14029 swapStyleSheet : function(id, url){
14030 this.removeStyleSheet(id);
14031 var ss = doc.createElement("link");
14032 ss.setAttribute("rel", "stylesheet");
14033 ss.setAttribute("type", "text/css");
14034 ss.setAttribute("id", id);
14035 ss.setAttribute("href", url);
14036 doc.getElementsByTagName("head")[0].appendChild(ss);
14040 * Refresh the rule cache if you have dynamically added stylesheets
14041 * @return {Object} An object (hash) of rules indexed by selector
14043 refreshCache : function(){
14044 return this.getRules(true);
14048 cacheStyleSheet : function(stylesheet){
14052 try{// try catch for cross domain access issue
14053 var ssRules = stylesheet.cssRules || stylesheet.rules;
14054 for(var j = ssRules.length-1; j >= 0; --j){
14055 rules[ssRules[j].selectorText] = ssRules[j];
14061 * Gets all css rules for the document
14062 * @param {Boolean} refreshCache true to refresh the internal cache
14063 * @return {Object} An object (hash) of rules indexed by selector
14065 getRules : function(refreshCache){
14066 if(rules == null || refreshCache){
14068 var ds = doc.styleSheets;
14069 for(var i =0, len = ds.length; i < len; i++){
14071 this.cacheStyleSheet(ds[i]);
14079 * Gets an an individual CSS rule by selector(s)
14080 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
14081 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
14082 * @return {CSSRule} The CSS rule or null if one is not found
14084 getRule : function(selector, refreshCache){
14085 var rs = this.getRules(refreshCache);
14086 if(!(selector instanceof Array)){
14087 return rs[selector];
14089 for(var i = 0; i < selector.length; i++){
14090 if(rs[selector[i]]){
14091 return rs[selector[i]];
14099 * Updates a rule property
14100 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14101 * @param {String} property The css property
14102 * @param {String} value The new value for the property
14103 * @return {Boolean} true If a rule was found and updated
14105 updateRule : function(selector, property, value){
14106 if(!(selector instanceof Array)){
14107 var rule = this.getRule(selector);
14109 rule.style[property.replace(camelRe, camelFn)] = value;
14113 for(var i = 0; i < selector.length; i++){
14114 if(this.updateRule(selector[i], property, value)){
14124 * Ext JS Library 1.1.1
14125 * Copyright(c) 2006-2007, Ext JS, LLC.
14127 * Originally Released Under LGPL - original licence link has changed is not relivant.
14130 * <script type="text/javascript">
14136 * @class Roo.util.ClickRepeater
14137 * @extends Roo.util.Observable
14139 * A wrapper class which can be applied to any element. Fires a "click" event while the
14140 * mouse is pressed. The interval between firings may be specified in the config but
14141 * defaults to 10 milliseconds.
14143 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14145 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14146 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14147 * Similar to an autorepeat key delay.
14148 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14149 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14150 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14151 * "interval" and "delay" are ignored. "immediate" is honored.
14152 * @cfg {Boolean} preventDefault True to prevent the default click event
14153 * @cfg {Boolean} stopDefault True to stop the default click event
14156 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14157 * 2007-02-02 jvs Renamed to ClickRepeater
14158 * 2007-02-03 jvs Modifications for FF Mac and Safari
14161 * @param {String/HTMLElement/Element} el The element to listen on
14162 * @param {Object} config
14164 Roo.util.ClickRepeater = function(el, config)
14166 this.el = Roo.get(el);
14167 this.el.unselectable();
14169 Roo.apply(this, config);
14174 * Fires when the mouse button is depressed.
14175 * @param {Roo.util.ClickRepeater} this
14177 "mousedown" : true,
14180 * Fires on a specified interval during the time the element is pressed.
14181 * @param {Roo.util.ClickRepeater} this
14186 * Fires when the mouse key is released.
14187 * @param {Roo.util.ClickRepeater} this
14192 this.el.on("mousedown", this.handleMouseDown, this);
14193 if(this.preventDefault || this.stopDefault){
14194 this.el.on("click", function(e){
14195 if(this.preventDefault){
14196 e.preventDefault();
14198 if(this.stopDefault){
14204 // allow inline handler
14206 this.on("click", this.handler, this.scope || this);
14209 Roo.util.ClickRepeater.superclass.constructor.call(this);
14212 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14215 preventDefault : true,
14216 stopDefault : false,
14220 handleMouseDown : function(){
14221 clearTimeout(this.timer);
14223 if(this.pressClass){
14224 this.el.addClass(this.pressClass);
14226 this.mousedownTime = new Date();
14228 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14229 this.el.on("mouseout", this.handleMouseOut, this);
14231 this.fireEvent("mousedown", this);
14232 this.fireEvent("click", this);
14234 this.timer = this.click.defer(this.delay || this.interval, this);
14238 click : function(){
14239 this.fireEvent("click", this);
14240 this.timer = this.click.defer(this.getInterval(), this);
14244 getInterval: function(){
14245 if(!this.accelerate){
14246 return this.interval;
14248 var pressTime = this.mousedownTime.getElapsed();
14249 if(pressTime < 500){
14251 }else if(pressTime < 1700){
14253 }else if(pressTime < 2600){
14255 }else if(pressTime < 3500){
14257 }else if(pressTime < 4400){
14259 }else if(pressTime < 5300){
14261 }else if(pressTime < 6200){
14269 handleMouseOut : function(){
14270 clearTimeout(this.timer);
14271 if(this.pressClass){
14272 this.el.removeClass(this.pressClass);
14274 this.el.on("mouseover", this.handleMouseReturn, this);
14278 handleMouseReturn : function(){
14279 this.el.un("mouseover", this.handleMouseReturn);
14280 if(this.pressClass){
14281 this.el.addClass(this.pressClass);
14287 handleMouseUp : function(){
14288 clearTimeout(this.timer);
14289 this.el.un("mouseover", this.handleMouseReturn);
14290 this.el.un("mouseout", this.handleMouseOut);
14291 Roo.get(document).un("mouseup", this.handleMouseUp);
14292 this.el.removeClass(this.pressClass);
14293 this.fireEvent("mouseup", this);
14297 * Ext JS Library 1.1.1
14298 * Copyright(c) 2006-2007, Ext JS, LLC.
14300 * Originally Released Under LGPL - original licence link has changed is not relivant.
14303 * <script type="text/javascript">
14308 * @class Roo.KeyNav
14309 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14310 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14311 * way to implement custom navigation schemes for any UI component.</p>
14312 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14313 * pageUp, pageDown, del, home, end. Usage:</p>
14315 var nav = new Roo.KeyNav("my-element", {
14316 "left" : function(e){
14317 this.moveLeft(e.ctrlKey);
14319 "right" : function(e){
14320 this.moveRight(e.ctrlKey);
14322 "enter" : function(e){
14329 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14330 * @param {Object} config The config
14332 Roo.KeyNav = function(el, config){
14333 this.el = Roo.get(el);
14334 Roo.apply(this, config);
14335 if(!this.disabled){
14336 this.disabled = true;
14341 Roo.KeyNav.prototype = {
14343 * @cfg {Boolean} disabled
14344 * True to disable this KeyNav instance (defaults to false)
14348 * @cfg {String} defaultEventAction
14349 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14350 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14351 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14353 defaultEventAction: "stopEvent",
14355 * @cfg {Boolean} forceKeyDown
14356 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14357 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14358 * handle keydown instead of keypress.
14360 forceKeyDown : false,
14363 prepareEvent : function(e){
14364 var k = e.getKey();
14365 var h = this.keyToHandler[k];
14366 //if(h && this[h]){
14367 // e.stopPropagation();
14369 if(Roo.isSafari && h && k >= 37 && k <= 40){
14375 relay : function(e){
14376 var k = e.getKey();
14377 var h = this.keyToHandler[k];
14379 if(this.doRelay(e, this[h], h) !== true){
14380 e[this.defaultEventAction]();
14386 doRelay : function(e, h, hname){
14387 return h.call(this.scope || this, e);
14390 // possible handlers
14404 // quick lookup hash
14421 * Enable this KeyNav
14423 enable: function(){
14425 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14426 // the EventObject will normalize Safari automatically
14427 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14428 this.el.on("keydown", this.relay, this);
14430 this.el.on("keydown", this.prepareEvent, this);
14431 this.el.on("keypress", this.relay, this);
14433 this.disabled = false;
14438 * Disable this KeyNav
14440 disable: function(){
14441 if(!this.disabled){
14442 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14443 this.el.un("keydown", this.relay);
14445 this.el.un("keydown", this.prepareEvent);
14446 this.el.un("keypress", this.relay);
14448 this.disabled = true;
14453 * Ext JS Library 1.1.1
14454 * Copyright(c) 2006-2007, Ext JS, LLC.
14456 * Originally Released Under LGPL - original licence link has changed is not relivant.
14459 * <script type="text/javascript">
14464 * @class Roo.KeyMap
14465 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14466 * The constructor accepts the same config object as defined by {@link #addBinding}.
14467 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14468 * combination it will call the function with this signature (if the match is a multi-key
14469 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14470 * A KeyMap can also handle a string representation of keys.<br />
14473 // map one key by key code
14474 var map = new Roo.KeyMap("my-element", {
14475 key: 13, // or Roo.EventObject.ENTER
14480 // map multiple keys to one action by string
14481 var map = new Roo.KeyMap("my-element", {
14487 // map multiple keys to multiple actions by strings and array of codes
14488 var map = new Roo.KeyMap("my-element", [
14491 fn: function(){ alert("Return was pressed"); }
14494 fn: function(){ alert('a, b or c was pressed'); }
14499 fn: function(){ alert('Control + shift + tab was pressed.'); }
14503 * <b>Note: A KeyMap starts enabled</b>
14505 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14506 * @param {Object} config The config (see {@link #addBinding})
14507 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14509 Roo.KeyMap = function(el, config, eventName){
14510 this.el = Roo.get(el);
14511 this.eventName = eventName || "keydown";
14512 this.bindings = [];
14514 this.addBinding(config);
14519 Roo.KeyMap.prototype = {
14521 * True to stop the event from bubbling and prevent the default browser action if the
14522 * key was handled by the KeyMap (defaults to false)
14528 * Add a new binding to this KeyMap. The following config object properties are supported:
14530 Property Type Description
14531 ---------- --------------- ----------------------------------------------------------------------
14532 key String/Array A single keycode or an array of keycodes to handle
14533 shift Boolean True to handle key only when shift is pressed (defaults to false)
14534 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14535 alt Boolean True to handle key only when alt is pressed (defaults to false)
14536 fn Function The function to call when KeyMap finds the expected key combination
14537 scope Object The scope of the callback function
14543 var map = new Roo.KeyMap(document, {
14544 key: Roo.EventObject.ENTER,
14549 //Add a new binding to the existing KeyMap later
14557 * @param {Object/Array} config A single KeyMap config or an array of configs
14559 addBinding : function(config){
14560 if(config instanceof Array){
14561 for(var i = 0, len = config.length; i < len; i++){
14562 this.addBinding(config[i]);
14566 var keyCode = config.key,
14567 shift = config.shift,
14568 ctrl = config.ctrl,
14571 scope = config.scope;
14572 if(typeof keyCode == "string"){
14574 var keyString = keyCode.toUpperCase();
14575 for(var j = 0, len = keyString.length; j < len; j++){
14576 ks.push(keyString.charCodeAt(j));
14580 var keyArray = keyCode instanceof Array;
14581 var handler = function(e){
14582 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14583 var k = e.getKey();
14585 for(var i = 0, len = keyCode.length; i < len; i++){
14586 if(keyCode[i] == k){
14587 if(this.stopEvent){
14590 fn.call(scope || window, k, e);
14596 if(this.stopEvent){
14599 fn.call(scope || window, k, e);
14604 this.bindings.push(handler);
14608 * Shorthand for adding a single key listener
14609 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14610 * following options:
14611 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14612 * @param {Function} fn The function to call
14613 * @param {Object} scope (optional) The scope of the function
14615 on : function(key, fn, scope){
14616 var keyCode, shift, ctrl, alt;
14617 if(typeof key == "object" && !(key instanceof Array)){
14636 handleKeyDown : function(e){
14637 if(this.enabled){ //just in case
14638 var b = this.bindings;
14639 for(var i = 0, len = b.length; i < len; i++){
14640 b[i].call(this, e);
14646 * Returns true if this KeyMap is enabled
14647 * @return {Boolean}
14649 isEnabled : function(){
14650 return this.enabled;
14654 * Enables this KeyMap
14656 enable: function(){
14658 this.el.on(this.eventName, this.handleKeyDown, this);
14659 this.enabled = true;
14664 * Disable this KeyMap
14666 disable: function(){
14668 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14669 this.enabled = false;
14674 * Ext JS Library 1.1.1
14675 * Copyright(c) 2006-2007, Ext JS, LLC.
14677 * Originally Released Under LGPL - original licence link has changed is not relivant.
14680 * <script type="text/javascript">
14685 * @class Roo.util.TextMetrics
14686 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14687 * wide, in pixels, a given block of text will be.
14690 Roo.util.TextMetrics = function(){
14694 * Measures the size of the specified text
14695 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14696 * that can affect the size of the rendered text
14697 * @param {String} text The text to measure
14698 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14699 * in order to accurately measure the text height
14700 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14702 measure : function(el, text, fixedWidth){
14704 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14707 shared.setFixedWidth(fixedWidth || 'auto');
14708 return shared.getSize(text);
14712 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14713 * the overhead of multiple calls to initialize the style properties on each measurement.
14714 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14715 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14716 * in order to accurately measure the text height
14717 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14719 createInstance : function(el, fixedWidth){
14720 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14727 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14728 var ml = new Roo.Element(document.createElement('div'));
14729 document.body.appendChild(ml.dom);
14730 ml.position('absolute');
14731 ml.setLeftTop(-1000, -1000);
14735 ml.setWidth(fixedWidth);
14740 * Returns the size of the specified text based on the internal element's style and width properties
14741 * @memberOf Roo.util.TextMetrics.Instance#
14742 * @param {String} text The text to measure
14743 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14745 getSize : function(text){
14747 var s = ml.getSize();
14753 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14754 * that can affect the size of the rendered text
14755 * @memberOf Roo.util.TextMetrics.Instance#
14756 * @param {String/HTMLElement} el The element, dom node or id
14758 bind : function(el){
14760 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14765 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14766 * to set a fixed width in order to accurately measure the text height.
14767 * @memberOf Roo.util.TextMetrics.Instance#
14768 * @param {Number} width The width to set on the element
14770 setFixedWidth : function(width){
14771 ml.setWidth(width);
14775 * Returns the measured width of the specified text
14776 * @memberOf Roo.util.TextMetrics.Instance#
14777 * @param {String} text The text to measure
14778 * @return {Number} width The width in pixels
14780 getWidth : function(text){
14781 ml.dom.style.width = 'auto';
14782 return this.getSize(text).width;
14786 * Returns the measured height of the specified text. For multiline text, be sure to call
14787 * {@link #setFixedWidth} if necessary.
14788 * @memberOf Roo.util.TextMetrics.Instance#
14789 * @param {String} text The text to measure
14790 * @return {Number} height The height in pixels
14792 getHeight : function(text){
14793 return this.getSize(text).height;
14797 instance.bind(bindTo);
14802 // backwards compat
14803 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14805 * Ext JS Library 1.1.1
14806 * Copyright(c) 2006-2007, Ext JS, LLC.
14808 * Originally Released Under LGPL - original licence link has changed is not relivant.
14811 * <script type="text/javascript">
14815 * @class Roo.state.Provider
14816 * Abstract base class for state provider implementations. This class provides methods
14817 * for encoding and decoding <b>typed</b> variables including dates and defines the
14818 * Provider interface.
14820 Roo.state.Provider = function(){
14822 * @event statechange
14823 * Fires when a state change occurs.
14824 * @param {Provider} this This state provider
14825 * @param {String} key The state key which was changed
14826 * @param {String} value The encoded value for the state
14829 "statechange": true
14832 Roo.state.Provider.superclass.constructor.call(this);
14834 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14836 * Returns the current value for a key
14837 * @param {String} name The key name
14838 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14839 * @return {Mixed} The state data
14841 get : function(name, defaultValue){
14842 return typeof this.state[name] == "undefined" ?
14843 defaultValue : this.state[name];
14847 * Clears a value from the state
14848 * @param {String} name The key name
14850 clear : function(name){
14851 delete this.state[name];
14852 this.fireEvent("statechange", this, name, null);
14856 * Sets the value for a key
14857 * @param {String} name The key name
14858 * @param {Mixed} value The value to set
14860 set : function(name, value){
14861 this.state[name] = value;
14862 this.fireEvent("statechange", this, name, value);
14866 * Decodes a string previously encoded with {@link #encodeValue}.
14867 * @param {String} value The value to decode
14868 * @return {Mixed} The decoded value
14870 decodeValue : function(cookie){
14871 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14872 var matches = re.exec(unescape(cookie));
14873 if(!matches || !matches[1]) {
14874 return; // non state cookie
14876 var type = matches[1];
14877 var v = matches[2];
14880 return parseFloat(v);
14882 return new Date(Date.parse(v));
14887 var values = v.split("^");
14888 for(var i = 0, len = values.length; i < len; i++){
14889 all.push(this.decodeValue(values[i]));
14894 var values = v.split("^");
14895 for(var i = 0, len = values.length; i < len; i++){
14896 var kv = values[i].split("=");
14897 all[kv[0]] = this.decodeValue(kv[1]);
14906 * Encodes a value including type information. Decode with {@link #decodeValue}.
14907 * @param {Mixed} value The value to encode
14908 * @return {String} The encoded value
14910 encodeValue : function(v){
14912 if(typeof v == "number"){
14914 }else if(typeof v == "boolean"){
14915 enc = "b:" + (v ? "1" : "0");
14916 }else if(v instanceof Date){
14917 enc = "d:" + v.toGMTString();
14918 }else if(v instanceof Array){
14920 for(var i = 0, len = v.length; i < len; i++){
14921 flat += this.encodeValue(v[i]);
14927 }else if(typeof v == "object"){
14930 if(typeof v[key] != "function"){
14931 flat += key + "=" + this.encodeValue(v[key]) + "^";
14934 enc = "o:" + flat.substring(0, flat.length-1);
14938 return escape(enc);
14944 * Ext JS Library 1.1.1
14945 * Copyright(c) 2006-2007, Ext JS, LLC.
14947 * Originally Released Under LGPL - original licence link has changed is not relivant.
14950 * <script type="text/javascript">
14953 * @class Roo.state.Manager
14954 * This is the global state manager. By default all components that are "state aware" check this class
14955 * for state information if you don't pass them a custom state provider. In order for this class
14956 * to be useful, it must be initialized with a provider when your application initializes.
14958 // in your initialization function
14960 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14962 // supposed you have a {@link Roo.BorderLayout}
14963 var layout = new Roo.BorderLayout(...);
14964 layout.restoreState();
14965 // or a {Roo.BasicDialog}
14966 var dialog = new Roo.BasicDialog(...);
14967 dialog.restoreState();
14971 Roo.state.Manager = function(){
14972 var provider = new Roo.state.Provider();
14976 * Configures the default state provider for your application
14977 * @param {Provider} stateProvider The state provider to set
14979 setProvider : function(stateProvider){
14980 provider = stateProvider;
14984 * Returns the current value for a key
14985 * @param {String} name The key name
14986 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14987 * @return {Mixed} The state data
14989 get : function(key, defaultValue){
14990 return provider.get(key, defaultValue);
14994 * Sets the value for a key
14995 * @param {String} name The key name
14996 * @param {Mixed} value The state data
14998 set : function(key, value){
14999 provider.set(key, value);
15003 * Clears a value from the state
15004 * @param {String} name The key name
15006 clear : function(key){
15007 provider.clear(key);
15011 * Gets the currently configured state provider
15012 * @return {Provider} The state provider
15014 getProvider : function(){
15021 * Ext JS Library 1.1.1
15022 * Copyright(c) 2006-2007, Ext JS, LLC.
15024 * Originally Released Under LGPL - original licence link has changed is not relivant.
15027 * <script type="text/javascript">
15030 * @class Roo.state.CookieProvider
15031 * @extends Roo.state.Provider
15032 * The default Provider implementation which saves state via cookies.
15035 var cp = new Roo.state.CookieProvider({
15037 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
15038 domain: "roojs.com"
15040 Roo.state.Manager.setProvider(cp);
15042 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
15043 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
15044 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
15045 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
15046 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
15047 * domain the page is running on including the 'www' like 'www.roojs.com')
15048 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
15050 * Create a new CookieProvider
15051 * @param {Object} config The configuration object
15053 Roo.state.CookieProvider = function(config){
15054 Roo.state.CookieProvider.superclass.constructor.call(this);
15056 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
15057 this.domain = null;
15058 this.secure = false;
15059 Roo.apply(this, config);
15060 this.state = this.readCookies();
15063 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
15065 set : function(name, value){
15066 if(typeof value == "undefined" || value === null){
15070 this.setCookie(name, value);
15071 Roo.state.CookieProvider.superclass.set.call(this, name, value);
15075 clear : function(name){
15076 this.clearCookie(name);
15077 Roo.state.CookieProvider.superclass.clear.call(this, name);
15081 readCookies : function(){
15083 var c = document.cookie + ";";
15084 var re = /\s?(.*?)=(.*?);/g;
15086 while((matches = re.exec(c)) != null){
15087 var name = matches[1];
15088 var value = matches[2];
15089 if(name && name.substring(0,3) == "ys-"){
15090 cookies[name.substr(3)] = this.decodeValue(value);
15097 setCookie : function(name, value){
15098 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15099 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15100 ((this.path == null) ? "" : ("; path=" + this.path)) +
15101 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15102 ((this.secure == true) ? "; secure" : "");
15106 clearCookie : function(name){
15107 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15108 ((this.path == null) ? "" : ("; path=" + this.path)) +
15109 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15110 ((this.secure == true) ? "; secure" : "");
15114 * Ext JS Library 1.1.1
15115 * Copyright(c) 2006-2007, Ext JS, LLC.
15117 * Originally Released Under LGPL - original licence link has changed is not relivant.
15120 * <script type="text/javascript">
15125 * @class Roo.ComponentMgr
15126 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15129 Roo.ComponentMgr = function(){
15130 var all = new Roo.util.MixedCollection();
15134 * Registers a component.
15135 * @param {Roo.Component} c The component
15137 register : function(c){
15142 * Unregisters a component.
15143 * @param {Roo.Component} c The component
15145 unregister : function(c){
15150 * Returns a component by id
15151 * @param {String} id The component id
15153 get : function(id){
15154 return all.get(id);
15158 * Registers a function that will be called when a specified component is added to ComponentMgr
15159 * @param {String} id The component id
15160 * @param {Funtction} fn The callback function
15161 * @param {Object} scope The scope of the callback
15163 onAvailable : function(id, fn, scope){
15164 all.on("add", function(index, o){
15166 fn.call(scope || o, o);
15167 all.un("add", fn, scope);
15174 * Ext JS Library 1.1.1
15175 * Copyright(c) 2006-2007, Ext JS, LLC.
15177 * Originally Released Under LGPL - original licence link has changed is not relivant.
15180 * <script type="text/javascript">
15184 * @class Roo.Component
15185 * @extends Roo.util.Observable
15186 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15187 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15188 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15189 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15190 * All visual components (widgets) that require rendering into a layout should subclass Component.
15192 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15193 * 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
15194 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15196 Roo.Component = function(config){
15197 config = config || {};
15198 if(config.tagName || config.dom || typeof config == "string"){ // element object
15199 config = {el: config, id: config.id || config};
15201 this.initialConfig = config;
15203 Roo.apply(this, config);
15207 * Fires after the component is disabled.
15208 * @param {Roo.Component} this
15213 * Fires after the component is enabled.
15214 * @param {Roo.Component} this
15218 * @event beforeshow
15219 * Fires before the component is shown. Return false to stop the show.
15220 * @param {Roo.Component} this
15225 * Fires after the component is shown.
15226 * @param {Roo.Component} this
15230 * @event beforehide
15231 * Fires before the component is hidden. Return false to stop the hide.
15232 * @param {Roo.Component} this
15237 * Fires after the component is hidden.
15238 * @param {Roo.Component} this
15242 * @event beforerender
15243 * Fires before the component is rendered. Return false to stop the render.
15244 * @param {Roo.Component} this
15246 beforerender : true,
15249 * Fires after the component is rendered.
15250 * @param {Roo.Component} this
15254 * @event beforedestroy
15255 * Fires before the component is destroyed. Return false to stop the destroy.
15256 * @param {Roo.Component} this
15258 beforedestroy : true,
15261 * Fires after the component is destroyed.
15262 * @param {Roo.Component} this
15267 this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
15269 Roo.ComponentMgr.register(this);
15270 Roo.Component.superclass.constructor.call(this);
15271 this.initComponent();
15272 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15273 this.render(this.renderTo);
15274 delete this.renderTo;
15279 Roo.Component.AUTO_ID = 1000;
15281 Roo.extend(Roo.Component, Roo.util.Observable, {
15283 * @scope Roo.Component.prototype
15285 * true if this component is hidden. Read-only.
15290 * true if this component is disabled. Read-only.
15295 * true if this component has been rendered. Read-only.
15299 /** @cfg {String} disableClass
15300 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15302 disabledClass : "x-item-disabled",
15303 /** @cfg {Boolean} allowDomMove
15304 * Whether the component can move the Dom node when rendering (defaults to true).
15306 allowDomMove : true,
15307 /** @cfg {String} hideMode (display|visibility)
15308 * How this component should hidden. Supported values are
15309 * "visibility" (css visibility), "offsets" (negative offset position) and
15310 * "display" (css display) - defaults to "display".
15312 hideMode: 'display',
15315 ctype : "Roo.Component",
15318 * @cfg {String} actionMode
15319 * which property holds the element that used for hide() / show() / disable() / enable()
15325 getActionEl : function(){
15326 return this[this.actionMode];
15329 initComponent : Roo.emptyFn,
15331 * If this is a lazy rendering component, render it to its container element.
15332 * @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.
15334 render : function(container, position){
15335 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15336 if(!container && this.el){
15337 this.el = Roo.get(this.el);
15338 container = this.el.dom.parentNode;
15339 this.allowDomMove = false;
15341 this.container = Roo.get(container);
15342 this.rendered = true;
15343 if(position !== undefined){
15344 if(typeof position == 'number'){
15345 position = this.container.dom.childNodes[position];
15347 position = Roo.getDom(position);
15350 this.onRender(this.container, position || null);
15352 this.el.addClass(this.cls);
15356 this.el.applyStyles(this.style);
15359 this.fireEvent("render", this);
15360 this.afterRender(this.container);
15372 // default function is not really useful
15373 onRender : function(ct, position){
15375 this.el = Roo.get(this.el);
15376 if(this.allowDomMove !== false){
15377 ct.dom.insertBefore(this.el.dom, position);
15383 getAutoCreate : function(){
15384 var cfg = typeof this.autoCreate == "object" ?
15385 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15386 if(this.id && !cfg.id){
15393 afterRender : Roo.emptyFn,
15396 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15397 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15399 destroy : function(){
15400 if(this.fireEvent("beforedestroy", this) !== false){
15401 this.purgeListeners();
15402 this.beforeDestroy();
15404 this.el.removeAllListeners();
15406 if(this.actionMode == "container"){
15407 this.container.remove();
15411 Roo.ComponentMgr.unregister(this);
15412 this.fireEvent("destroy", this);
15417 beforeDestroy : function(){
15422 onDestroy : function(){
15427 * Returns the underlying {@link Roo.Element}.
15428 * @return {Roo.Element} The element
15430 getEl : function(){
15435 * Returns the id of this component.
15438 getId : function(){
15443 * Try to focus this component.
15444 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15445 * @return {Roo.Component} this
15447 focus : function(selectText){
15450 if(selectText === true){
15451 this.el.dom.select();
15466 * Disable this component.
15467 * @return {Roo.Component} this
15469 disable : function(){
15473 this.disabled = true;
15474 this.fireEvent("disable", this);
15479 onDisable : function(){
15480 this.getActionEl().addClass(this.disabledClass);
15481 this.el.dom.disabled = true;
15485 * Enable this component.
15486 * @return {Roo.Component} this
15488 enable : function(){
15492 this.disabled = false;
15493 this.fireEvent("enable", this);
15498 onEnable : function(){
15499 this.getActionEl().removeClass(this.disabledClass);
15500 this.el.dom.disabled = false;
15504 * Convenience function for setting disabled/enabled by boolean.
15505 * @param {Boolean} disabled
15507 setDisabled : function(disabled){
15508 this[disabled ? "disable" : "enable"]();
15512 * Show this component.
15513 * @return {Roo.Component} this
15516 if(this.fireEvent("beforeshow", this) !== false){
15517 this.hidden = false;
15521 this.fireEvent("show", this);
15527 onShow : function(){
15528 var ae = this.getActionEl();
15529 if(this.hideMode == 'visibility'){
15530 ae.dom.style.visibility = "visible";
15531 }else if(this.hideMode == 'offsets'){
15532 ae.removeClass('x-hidden');
15534 ae.dom.style.display = "";
15539 * Hide this component.
15540 * @return {Roo.Component} this
15543 if(this.fireEvent("beforehide", this) !== false){
15544 this.hidden = true;
15548 this.fireEvent("hide", this);
15554 onHide : function(){
15555 var ae = this.getActionEl();
15556 if(this.hideMode == 'visibility'){
15557 ae.dom.style.visibility = "hidden";
15558 }else if(this.hideMode == 'offsets'){
15559 ae.addClass('x-hidden');
15561 ae.dom.style.display = "none";
15566 * Convenience function to hide or show this component by boolean.
15567 * @param {Boolean} visible True to show, false to hide
15568 * @return {Roo.Component} this
15570 setVisible: function(visible){
15580 * Returns true if this component is visible.
15582 isVisible : function(){
15583 return this.getActionEl().isVisible();
15586 cloneConfig : function(overrides){
15587 overrides = overrides || {};
15588 var id = overrides.id || Roo.id();
15589 var cfg = Roo.applyIf(overrides, this.initialConfig);
15590 cfg.id = id; // prevent dup id
15591 return new this.constructor(cfg);
15595 * Ext JS Library 1.1.1
15596 * Copyright(c) 2006-2007, Ext JS, LLC.
15598 * Originally Released Under LGPL - original licence link has changed is not relivant.
15601 * <script type="text/javascript">
15605 * @class Roo.BoxComponent
15606 * @extends Roo.Component
15607 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15608 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15609 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15610 * layout containers.
15612 * @param {Roo.Element/String/Object} config The configuration options.
15614 Roo.BoxComponent = function(config){
15615 Roo.Component.call(this, config);
15619 * Fires after the component is resized.
15620 * @param {Roo.Component} this
15621 * @param {Number} adjWidth The box-adjusted width that was set
15622 * @param {Number} adjHeight The box-adjusted height that was set
15623 * @param {Number} rawWidth The width that was originally specified
15624 * @param {Number} rawHeight The height that was originally specified
15629 * Fires after the component is moved.
15630 * @param {Roo.Component} this
15631 * @param {Number} x The new x position
15632 * @param {Number} y The new y position
15638 Roo.extend(Roo.BoxComponent, Roo.Component, {
15639 // private, set in afterRender to signify that the component has been rendered
15641 // private, used to defer height settings to subclasses
15642 deferHeight: false,
15643 /** @cfg {Number} width
15644 * width (optional) size of component
15646 /** @cfg {Number} height
15647 * height (optional) size of component
15651 * Sets the width and height of the component. This method fires the resize event. This method can accept
15652 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15653 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15654 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15655 * @return {Roo.BoxComponent} this
15657 setSize : function(w, h){
15658 // support for standard size objects
15659 if(typeof w == 'object'){
15664 if(!this.boxReady){
15670 // prevent recalcs when not needed
15671 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15674 this.lastSize = {width: w, height: h};
15676 var adj = this.adjustSize(w, h);
15677 var aw = adj.width, ah = adj.height;
15678 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15679 var rz = this.getResizeEl();
15680 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15681 rz.setSize(aw, ah);
15682 }else if(!this.deferHeight && ah !== undefined){
15684 }else if(aw !== undefined){
15687 this.onResize(aw, ah, w, h);
15688 this.fireEvent('resize', this, aw, ah, w, h);
15694 * Gets the current size of the component's underlying element.
15695 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15697 getSize : function(){
15698 return this.el.getSize();
15702 * Gets the current XY position of the component's underlying element.
15703 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15704 * @return {Array} The XY position of the element (e.g., [100, 200])
15706 getPosition : function(local){
15707 if(local === true){
15708 return [this.el.getLeft(true), this.el.getTop(true)];
15710 return this.xy || this.el.getXY();
15714 * Gets the current box measurements of the component's underlying element.
15715 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15716 * @returns {Object} box An object in the format {x, y, width, height}
15718 getBox : function(local){
15719 var s = this.el.getSize();
15721 s.x = this.el.getLeft(true);
15722 s.y = this.el.getTop(true);
15724 var xy = this.xy || this.el.getXY();
15732 * Sets the current box measurements of the component's underlying element.
15733 * @param {Object} box An object in the format {x, y, width, height}
15734 * @returns {Roo.BoxComponent} this
15736 updateBox : function(box){
15737 this.setSize(box.width, box.height);
15738 this.setPagePosition(box.x, box.y);
15743 getResizeEl : function(){
15744 return this.resizeEl || this.el;
15748 getPositionEl : function(){
15749 return this.positionEl || this.el;
15753 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15754 * This method fires the move event.
15755 * @param {Number} left The new left
15756 * @param {Number} top The new top
15757 * @returns {Roo.BoxComponent} this
15759 setPosition : function(x, y){
15762 if(!this.boxReady){
15765 var adj = this.adjustPosition(x, y);
15766 var ax = adj.x, ay = adj.y;
15768 var el = this.getPositionEl();
15769 if(ax !== undefined || ay !== undefined){
15770 if(ax !== undefined && ay !== undefined){
15771 el.setLeftTop(ax, ay);
15772 }else if(ax !== undefined){
15774 }else if(ay !== undefined){
15777 this.onPosition(ax, ay);
15778 this.fireEvent('move', this, ax, ay);
15784 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15785 * This method fires the move event.
15786 * @param {Number} x The new x position
15787 * @param {Number} y The new y position
15788 * @returns {Roo.BoxComponent} this
15790 setPagePosition : function(x, y){
15793 if(!this.boxReady){
15796 if(x === undefined || y === undefined){ // cannot translate undefined points
15799 var p = this.el.translatePoints(x, y);
15800 this.setPosition(p.left, p.top);
15805 onRender : function(ct, position){
15806 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15808 this.resizeEl = Roo.get(this.resizeEl);
15810 if(this.positionEl){
15811 this.positionEl = Roo.get(this.positionEl);
15816 afterRender : function(){
15817 Roo.BoxComponent.superclass.afterRender.call(this);
15818 this.boxReady = true;
15819 this.setSize(this.width, this.height);
15820 if(this.x || this.y){
15821 this.setPosition(this.x, this.y);
15823 if(this.pageX || this.pageY){
15824 this.setPagePosition(this.pageX, this.pageY);
15829 * Force the component's size to recalculate based on the underlying element's current height and width.
15830 * @returns {Roo.BoxComponent} this
15832 syncSize : function(){
15833 delete this.lastSize;
15834 this.setSize(this.el.getWidth(), this.el.getHeight());
15839 * Called after the component is resized, this method is empty by default but can be implemented by any
15840 * subclass that needs to perform custom logic after a resize occurs.
15841 * @param {Number} adjWidth The box-adjusted width that was set
15842 * @param {Number} adjHeight The box-adjusted height that was set
15843 * @param {Number} rawWidth The width that was originally specified
15844 * @param {Number} rawHeight The height that was originally specified
15846 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15851 * Called after the component is moved, this method is empty by default but can be implemented by any
15852 * subclass that needs to perform custom logic after a move occurs.
15853 * @param {Number} x The new x position
15854 * @param {Number} y The new y position
15856 onPosition : function(x, y){
15861 adjustSize : function(w, h){
15862 if(this.autoWidth){
15865 if(this.autoHeight){
15868 return {width : w, height: h};
15872 adjustPosition : function(x, y){
15873 return {x : x, y: y};
15876 * Original code for Roojs - LGPL
15877 * <script type="text/javascript">
15881 * @class Roo.XComponent
15882 * A delayed Element creator...
15883 * Or a way to group chunks of interface together.
15884 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15885 * used in conjunction with XComponent.build() it will create an instance of each element,
15886 * then call addxtype() to build the User interface.
15888 * Mypart.xyx = new Roo.XComponent({
15890 parent : 'Mypart.xyz', // empty == document.element.!!
15894 disabled : function() {}
15896 tree : function() { // return an tree of xtype declared components
15900 xtype : 'NestedLayoutPanel',
15907 * It can be used to build a big heiracy, with parent etc.
15908 * or you can just use this to render a single compoent to a dom element
15909 * MYPART.render(Roo.Element | String(id) | dom_element )
15916 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15917 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15919 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15921 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15922 * - if mulitple topModules exist, the last one is defined as the top module.
15926 * When the top level or multiple modules are to embedded into a existing HTML page,
15927 * the parent element can container '#id' of the element where the module will be drawn.
15931 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15932 * it relies more on a include mechanism, where sub modules are included into an outer page.
15933 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15935 * Bootstrap Roo Included elements
15937 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15938 * hence confusing the component builder as it thinks there are multiple top level elements.
15942 * @extends Roo.util.Observable
15944 * @param cfg {Object} configuration of component
15947 Roo.XComponent = function(cfg) {
15948 Roo.apply(this, cfg);
15952 * Fires when this the componnt is built
15953 * @param {Roo.XComponent} c the component
15958 this.region = this.region || 'center'; // default..
15959 Roo.XComponent.register(this);
15960 this.modules = false;
15961 this.el = false; // where the layout goes..
15965 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15968 * The created element (with Roo.factory())
15969 * @type {Roo.Layout}
15975 * for BC - use el in new code
15976 * @type {Roo.Layout}
15982 * for BC - use el in new code
15983 * @type {Roo.Layout}
15988 * @cfg {Function|boolean} disabled
15989 * If this module is disabled by some rule, return true from the funtion
15994 * @cfg {String} parent
15995 * Name of parent element which it get xtype added to..
16000 * @cfg {String} order
16001 * Used to set the order in which elements are created (usefull for multiple tabs)
16006 * @cfg {String} name
16007 * String to display while loading.
16011 * @cfg {String} region
16012 * Region to render component to (defaults to center)
16017 * @cfg {Array} items
16018 * A single item array - the first element is the root of the tree..
16019 * It's done this way to stay compatible with the Xtype system...
16025 * The method that retuns the tree of parts that make up this compoennt
16032 * render element to dom or tree
16033 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
16036 render : function(el)
16040 var hp = this.parent ? 1 : 0;
16041 Roo.debug && Roo.log(this);
16043 var tree = this._tree ? this._tree() : this.tree();
16046 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
16047 // if parent is a '#.....' string, then let's use that..
16048 var ename = this.parent.substr(1);
16049 this.parent = false;
16050 Roo.debug && Roo.log(ename);
16052 case 'bootstrap-body':
16053 if (typeof(tree.el) != 'undefined' && tree.el == document.body) {
16054 // this is the BorderLayout standard?
16055 this.parent = { el : true };
16058 if (["Nest", "Content", "Grid", "Tree"].indexOf(tree.xtype) > -1) {
16059 // need to insert stuff...
16061 el : new Roo.bootstrap.layout.Border({
16062 el : document.body,
16068 tabPosition: 'top',
16069 //resizeTabs: true,
16070 alwaysShowTabs: true,
16080 if (typeof(Roo.bootstrap.Body) != 'undefined' ) {
16081 this.parent = { el : new Roo.bootstrap.Body() };
16082 Roo.debug && Roo.log("setting el to doc body");
16085 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
16089 this.parent = { el : true};
16092 el = Roo.get(ename);
16093 if (typeof(Roo.bootstrap) != 'undefined' && tree['|xns'] == 'Roo.bootstrap') {
16094 this.parent = { el : true};
16101 if (!el && !this.parent) {
16102 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
16107 Roo.debug && Roo.log("EL:");
16108 Roo.debug && Roo.log(el);
16109 Roo.debug && Roo.log("this.parent.el:");
16110 Roo.debug && Roo.log(this.parent.el);
16113 // altertive root elements ??? - we need a better way to indicate these.
16114 var is_alt = Roo.XComponent.is_alt ||
16115 (typeof(tree.el) != 'undefined' && tree.el == document.body) ||
16116 (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
16117 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
16121 if (!this.parent && is_alt) {
16122 //el = Roo.get(document.body);
16123 this.parent = { el : true };
16128 if (!this.parent) {
16130 Roo.debug && Roo.log("no parent - creating one");
16132 el = el ? Roo.get(el) : false;
16134 if (typeof(Roo.BorderLayout) == 'undefined' ) {
16137 el : new Roo.bootstrap.layout.Border({
16138 el: el || document.body,
16144 tabPosition: 'top',
16145 //resizeTabs: true,
16146 alwaysShowTabs: false,
16149 overflow: 'visible'
16155 // it's a top level one..
16157 el : new Roo.BorderLayout(el || document.body, {
16162 tabPosition: 'top',
16163 //resizeTabs: true,
16164 alwaysShowTabs: el && hp? false : true,
16165 hideTabs: el || !hp ? true : false,
16173 if (!this.parent.el) {
16174 // probably an old style ctor, which has been disabled.
16178 // The 'tree' method is '_tree now'
16180 tree.region = tree.region || this.region;
16181 var is_body = false;
16182 if (this.parent.el === true) {
16183 // bootstrap... - body..
16187 this.parent.el = Roo.factory(tree);
16191 this.el = this.parent.el.addxtype(tree, undefined, is_body);
16192 this.fireEvent('built', this);
16194 this.panel = this.el;
16195 this.layout = this.panel.layout;
16196 this.parentLayout = this.parent.layout || false;
16202 Roo.apply(Roo.XComponent, {
16204 * @property hideProgress
16205 * true to disable the building progress bar.. usefull on single page renders.
16208 hideProgress : false,
16210 * @property buildCompleted
16211 * True when the builder has completed building the interface.
16214 buildCompleted : false,
16217 * @property topModule
16218 * the upper most module - uses document.element as it's constructor.
16225 * @property modules
16226 * array of modules to be created by registration system.
16227 * @type {Array} of Roo.XComponent
16232 * @property elmodules
16233 * array of modules to be created by which use #ID
16234 * @type {Array} of Roo.XComponent
16241 * Is an alternative Root - normally used by bootstrap or other systems,
16242 * where the top element in the tree can wrap 'body'
16243 * @type {boolean} (default false)
16248 * @property build_from_html
16249 * Build elements from html - used by bootstrap HTML stuff
16250 * - this is cleared after build is completed
16251 * @type {boolean} (default false)
16254 build_from_html : false,
16256 * Register components to be built later.
16258 * This solves the following issues
16259 * - Building is not done on page load, but after an authentication process has occured.
16260 * - Interface elements are registered on page load
16261 * - Parent Interface elements may not be loaded before child, so this handles that..
16268 module : 'Pman.Tab.projectMgr',
16270 parent : 'Pman.layout',
16271 disabled : false, // or use a function..
16274 * * @param {Object} details about module
16276 register : function(obj) {
16278 Roo.XComponent.event.fireEvent('register', obj);
16279 switch(typeof(obj.disabled) ) {
16285 if ( obj.disabled() ) {
16291 if (obj.disabled) {
16297 this.modules.push(obj);
16301 * convert a string to an object..
16302 * eg. 'AAA.BBB' -> finds AAA.BBB
16306 toObject : function(str)
16308 if (!str || typeof(str) == 'object') {
16311 if (str.substring(0,1) == '#') {
16315 var ar = str.split('.');
16320 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16322 throw "Module not found : " + str;
16326 throw "Module not found : " + str;
16328 Roo.each(ar, function(e) {
16329 if (typeof(o[e]) == 'undefined') {
16330 throw "Module not found : " + str;
16341 * move modules into their correct place in the tree..
16344 preBuild : function ()
16347 Roo.each(this.modules , function (obj)
16349 Roo.XComponent.event.fireEvent('beforebuild', obj);
16351 var opar = obj.parent;
16353 obj.parent = this.toObject(opar);
16355 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16360 Roo.debug && Roo.log("GOT top level module");
16361 Roo.debug && Roo.log(obj);
16362 obj.modules = new Roo.util.MixedCollection(false,
16363 function(o) { return o.order + '' }
16365 this.topModule = obj;
16368 // parent is a string (usually a dom element name..)
16369 if (typeof(obj.parent) == 'string') {
16370 this.elmodules.push(obj);
16373 if (obj.parent.constructor != Roo.XComponent) {
16374 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16376 if (!obj.parent.modules) {
16377 obj.parent.modules = new Roo.util.MixedCollection(false,
16378 function(o) { return o.order + '' }
16381 if (obj.parent.disabled) {
16382 obj.disabled = true;
16384 obj.parent.modules.add(obj);
16389 * make a list of modules to build.
16390 * @return {Array} list of modules.
16393 buildOrder : function()
16396 var cmp = function(a,b) {
16397 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16399 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16400 throw "No top level modules to build";
16403 // make a flat list in order of modules to build.
16404 var mods = this.topModule ? [ this.topModule ] : [];
16407 // elmodules (is a list of DOM based modules )
16408 Roo.each(this.elmodules, function(e) {
16410 if (!this.topModule &&
16411 typeof(e.parent) == 'string' &&
16412 e.parent.substring(0,1) == '#' &&
16413 Roo.get(e.parent.substr(1))
16416 _this.topModule = e;
16422 // add modules to their parents..
16423 var addMod = function(m) {
16424 Roo.debug && Roo.log("build Order: add: " + m.name);
16427 if (m.modules && !m.disabled) {
16428 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16429 m.modules.keySort('ASC', cmp );
16430 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16432 m.modules.each(addMod);
16434 Roo.debug && Roo.log("build Order: no child modules");
16436 // not sure if this is used any more..
16438 m.finalize.name = m.name + " (clean up) ";
16439 mods.push(m.finalize);
16443 if (this.topModule && this.topModule.modules) {
16444 this.topModule.modules.keySort('ASC', cmp );
16445 this.topModule.modules.each(addMod);
16451 * Build the registered modules.
16452 * @param {Object} parent element.
16453 * @param {Function} optional method to call after module has been added.
16457 build : function(opts)
16460 if (typeof(opts) != 'undefined') {
16461 Roo.apply(this,opts);
16465 var mods = this.buildOrder();
16467 //this.allmods = mods;
16468 //Roo.debug && Roo.log(mods);
16470 if (!mods.length) { // should not happen
16471 throw "NO modules!!!";
16475 var msg = "Building Interface...";
16476 // flash it up as modal - so we store the mask!?
16477 if (!this.hideProgress && Roo.MessageBox) {
16478 Roo.MessageBox.show({ title: 'loading' });
16479 Roo.MessageBox.show({
16480 title: "Please wait...",
16489 var total = mods.length;
16492 var progressRun = function() {
16493 if (!mods.length) {
16494 Roo.debug && Roo.log('hide?');
16495 if (!this.hideProgress && Roo.MessageBox) {
16496 Roo.MessageBox.hide();
16498 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16500 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16506 var m = mods.shift();
16509 Roo.debug && Roo.log(m);
16510 // not sure if this is supported any more.. - modules that are are just function
16511 if (typeof(m) == 'function') {
16513 return progressRun.defer(10, _this);
16517 msg = "Building Interface " + (total - mods.length) +
16519 (m.name ? (' - ' + m.name) : '');
16520 Roo.debug && Roo.log(msg);
16521 if (!this.hideProgress && Roo.MessageBox) {
16522 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16526 // is the module disabled?
16527 var disabled = (typeof(m.disabled) == 'function') ?
16528 m.disabled.call(m.module.disabled) : m.disabled;
16532 return progressRun(); // we do not update the display!
16540 // it's 10 on top level, and 1 on others??? why...
16541 return progressRun.defer(10, _this);
16544 progressRun.defer(1, _this);
16558 * wrapper for event.on - aliased later..
16559 * Typically use to register a event handler for register:
16561 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16570 Roo.XComponent.event = new Roo.util.Observable({
16574 * Fires when an Component is registered,
16575 * set the disable property on the Component to stop registration.
16576 * @param {Roo.XComponent} c the component being registerd.
16581 * @event beforebuild
16582 * Fires before each Component is built
16583 * can be used to apply permissions.
16584 * @param {Roo.XComponent} c the component being registerd.
16587 'beforebuild' : true,
16589 * @event buildcomplete
16590 * Fires on the top level element when all elements have been built
16591 * @param {Roo.XComponent} the top level component.
16593 'buildcomplete' : true
16598 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);
16601 * marked - a markdown parser
16602 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
16603 * https://github.com/chjj/marked
16609 * Roo.Markdown - is a very crude wrapper around marked..
16613 * alert( Roo.Markdown.toHtml("Markdown *rocks*.") );
16615 * Note: move the sample code to the bottom of this
16616 * file before uncommenting it.
16621 Roo.Markdown.toHtml = function(text) {
16623 var c = new Roo.Markdown.marked.setOptions({
16624 renderer: new Roo.Markdown.marked.Renderer(),
16635 text = text.replace(/\\\n/g,' ');
16636 return Roo.Markdown.marked(text);
16641 // Wraps all "globals" so that the only thing
16642 // exposed is makeHtml().
16647 * Block-Level Grammar
16652 code: /^( {4}[^\n]+\n*)+/,
16654 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
16655 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
16657 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
16658 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
16659 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
16660 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
16661 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
16663 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
16667 block.bullet = /(?:[*+-]|\d+\.)/;
16668 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
16669 block.item = replace(block.item, 'gm')
16670 (/bull/g, block.bullet)
16673 block.list = replace(block.list)
16674 (/bull/g, block.bullet)
16675 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
16676 ('def', '\\n+(?=' + block.def.source + ')')
16679 block.blockquote = replace(block.blockquote)
16683 block._tag = '(?!(?:'
16684 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
16685 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
16686 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
16688 block.html = replace(block.html)
16689 ('comment', /<!--[\s\S]*?-->/)
16690 ('closed', /<(tag)[\s\S]+?<\/\1>/)
16691 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
16692 (/tag/g, block._tag)
16695 block.paragraph = replace(block.paragraph)
16697 ('heading', block.heading)
16698 ('lheading', block.lheading)
16699 ('blockquote', block.blockquote)
16700 ('tag', '<' + block._tag)
16705 * Normal Block Grammar
16708 block.normal = merge({}, block);
16711 * GFM Block Grammar
16714 block.gfm = merge({}, block.normal, {
16715 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
16717 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
16720 block.gfm.paragraph = replace(block.paragraph)
16722 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
16723 + block.list.source.replace('\\1', '\\3') + '|')
16727 * GFM + Tables Block Grammar
16730 block.tables = merge({}, block.gfm, {
16731 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
16732 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
16739 function Lexer(options) {
16741 this.tokens.links = {};
16742 this.options = options || marked.defaults;
16743 this.rules = block.normal;
16745 if (this.options.gfm) {
16746 if (this.options.tables) {
16747 this.rules = block.tables;
16749 this.rules = block.gfm;
16755 * Expose Block Rules
16758 Lexer.rules = block;
16761 * Static Lex Method
16764 Lexer.lex = function(src, options) {
16765 var lexer = new Lexer(options);
16766 return lexer.lex(src);
16773 Lexer.prototype.lex = function(src) {
16775 .replace(/\r\n|\r/g, '\n')
16776 .replace(/\t/g, ' ')
16777 .replace(/\u00a0/g, ' ')
16778 .replace(/\u2424/g, '\n');
16780 return this.token(src, true);
16787 Lexer.prototype.token = function(src, top, bq) {
16788 var src = src.replace(/^ +$/gm, '')
16801 if (cap = this.rules.newline.exec(src)) {
16802 src = src.substring(cap[0].length);
16803 if (cap[0].length > 1) {
16811 if (cap = this.rules.code.exec(src)) {
16812 src = src.substring(cap[0].length);
16813 cap = cap[0].replace(/^ {4}/gm, '');
16816 text: !this.options.pedantic
16817 ? cap.replace(/\n+$/, '')
16824 if (cap = this.rules.fences.exec(src)) {
16825 src = src.substring(cap[0].length);
16835 if (cap = this.rules.heading.exec(src)) {
16836 src = src.substring(cap[0].length);
16839 depth: cap[1].length,
16845 // table no leading pipe (gfm)
16846 if (top && (cap = this.rules.nptable.exec(src))) {
16847 src = src.substring(cap[0].length);
16851 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
16852 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
16853 cells: cap[3].replace(/\n$/, '').split('\n')
16856 for (i = 0; i < item.align.length; i++) {
16857 if (/^ *-+: *$/.test(item.align[i])) {
16858 item.align[i] = 'right';
16859 } else if (/^ *:-+: *$/.test(item.align[i])) {
16860 item.align[i] = 'center';
16861 } else if (/^ *:-+ *$/.test(item.align[i])) {
16862 item.align[i] = 'left';
16864 item.align[i] = null;
16868 for (i = 0; i < item.cells.length; i++) {
16869 item.cells[i] = item.cells[i].split(/ *\| */);
16872 this.tokens.push(item);
16878 if (cap = this.rules.lheading.exec(src)) {
16879 src = src.substring(cap[0].length);
16882 depth: cap[2] === '=' ? 1 : 2,
16889 if (cap = this.rules.hr.exec(src)) {
16890 src = src.substring(cap[0].length);
16898 if (cap = this.rules.blockquote.exec(src)) {
16899 src = src.substring(cap[0].length);
16902 type: 'blockquote_start'
16905 cap = cap[0].replace(/^ *> ?/gm, '');
16907 // Pass `top` to keep the current
16908 // "toplevel" state. This is exactly
16909 // how markdown.pl works.
16910 this.token(cap, top, true);
16913 type: 'blockquote_end'
16920 if (cap = this.rules.list.exec(src)) {
16921 src = src.substring(cap[0].length);
16925 type: 'list_start',
16926 ordered: bull.length > 1
16929 // Get each top-level item.
16930 cap = cap[0].match(this.rules.item);
16936 for (; i < l; i++) {
16939 // Remove the list item's bullet
16940 // so it is seen as the next token.
16941 space = item.length;
16942 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
16944 // Outdent whatever the
16945 // list item contains. Hacky.
16946 if (~item.indexOf('\n ')) {
16947 space -= item.length;
16948 item = !this.options.pedantic
16949 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
16950 : item.replace(/^ {1,4}/gm, '');
16953 // Determine whether the next list item belongs here.
16954 // Backpedal if it does not belong in this list.
16955 if (this.options.smartLists && i !== l - 1) {
16956 b = block.bullet.exec(cap[i + 1])[0];
16957 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
16958 src = cap.slice(i + 1).join('\n') + src;
16963 // Determine whether item is loose or not.
16964 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
16965 // for discount behavior.
16966 loose = next || /\n\n(?!\s*$)/.test(item);
16968 next = item.charAt(item.length - 1) === '\n';
16969 if (!loose) { loose = next; }
16974 ? 'loose_item_start'
16975 : 'list_item_start'
16979 this.token(item, false, bq);
16982 type: 'list_item_end'
16994 if (cap = this.rules.html.exec(src)) {
16995 src = src.substring(cap[0].length);
16997 type: this.options.sanitize
17000 pre: !this.options.sanitizer
17001 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
17008 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
17009 src = src.substring(cap[0].length);
17010 this.tokens.links[cap[1].toLowerCase()] = {
17018 if (top && (cap = this.rules.table.exec(src))) {
17019 src = src.substring(cap[0].length);
17023 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
17024 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
17025 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
17028 for (i = 0; i < item.align.length; i++) {
17029 if (/^ *-+: *$/.test(item.align[i])) {
17030 item.align[i] = 'right';
17031 } else if (/^ *:-+: *$/.test(item.align[i])) {
17032 item.align[i] = 'center';
17033 } else if (/^ *:-+ *$/.test(item.align[i])) {
17034 item.align[i] = 'left';
17036 item.align[i] = null;
17040 for (i = 0; i < item.cells.length; i++) {
17041 item.cells[i] = item.cells[i]
17042 .replace(/^ *\| *| *\| *$/g, '')
17046 this.tokens.push(item);
17051 // top-level paragraph
17052 if (top && (cap = this.rules.paragraph.exec(src))) {
17053 src = src.substring(cap[0].length);
17056 text: cap[1].charAt(cap[1].length - 1) === '\n'
17057 ? cap[1].slice(0, -1)
17064 if (cap = this.rules.text.exec(src)) {
17065 // Top-level should never reach here.
17066 src = src.substring(cap[0].length);
17076 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17080 return this.tokens;
17084 * Inline-Level Grammar
17088 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
17089 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
17091 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
17092 link: /^!?\[(inside)\]\(href\)/,
17093 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
17094 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
17095 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
17096 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
17097 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
17098 br: /^ {2,}\n(?!\s*$)/,
17100 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
17103 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
17104 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
17106 inline.link = replace(inline.link)
17107 ('inside', inline._inside)
17108 ('href', inline._href)
17111 inline.reflink = replace(inline.reflink)
17112 ('inside', inline._inside)
17116 * Normal Inline Grammar
17119 inline.normal = merge({}, inline);
17122 * Pedantic Inline Grammar
17125 inline.pedantic = merge({}, inline.normal, {
17126 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
17127 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
17131 * GFM Inline Grammar
17134 inline.gfm = merge({}, inline.normal, {
17135 escape: replace(inline.escape)('])', '~|])')(),
17136 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
17137 del: /^~~(?=\S)([\s\S]*?\S)~~/,
17138 text: replace(inline.text)
17140 ('|', '|https?://|')
17145 * GFM + Line Breaks Inline Grammar
17148 inline.breaks = merge({}, inline.gfm, {
17149 br: replace(inline.br)('{2,}', '*')(),
17150 text: replace(inline.gfm.text)('{2,}', '*')()
17154 * Inline Lexer & Compiler
17157 function InlineLexer(links, options) {
17158 this.options = options || marked.defaults;
17159 this.links = links;
17160 this.rules = inline.normal;
17161 this.renderer = this.options.renderer || new Renderer;
17162 this.renderer.options = this.options;
17166 Error('Tokens array requires a `links` property.');
17169 if (this.options.gfm) {
17170 if (this.options.breaks) {
17171 this.rules = inline.breaks;
17173 this.rules = inline.gfm;
17175 } else if (this.options.pedantic) {
17176 this.rules = inline.pedantic;
17181 * Expose Inline Rules
17184 InlineLexer.rules = inline;
17187 * Static Lexing/Compiling Method
17190 InlineLexer.output = function(src, links, options) {
17191 var inline = new InlineLexer(links, options);
17192 return inline.output(src);
17199 InlineLexer.prototype.output = function(src) {
17208 if (cap = this.rules.escape.exec(src)) {
17209 src = src.substring(cap[0].length);
17215 if (cap = this.rules.autolink.exec(src)) {
17216 src = src.substring(cap[0].length);
17217 if (cap[2] === '@') {
17218 text = cap[1].charAt(6) === ':'
17219 ? this.mangle(cap[1].substring(7))
17220 : this.mangle(cap[1]);
17221 href = this.mangle('mailto:') + text;
17223 text = escape(cap[1]);
17226 out += this.renderer.link(href, null, text);
17231 if (!this.inLink && (cap = this.rules.url.exec(src))) {
17232 src = src.substring(cap[0].length);
17233 text = escape(cap[1]);
17235 out += this.renderer.link(href, null, text);
17240 if (cap = this.rules.tag.exec(src)) {
17241 if (!this.inLink && /^<a /i.test(cap[0])) {
17242 this.inLink = true;
17243 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
17244 this.inLink = false;
17246 src = src.substring(cap[0].length);
17247 out += this.options.sanitize
17248 ? this.options.sanitizer
17249 ? this.options.sanitizer(cap[0])
17256 if (cap = this.rules.link.exec(src)) {
17257 src = src.substring(cap[0].length);
17258 this.inLink = true;
17259 out += this.outputLink(cap, {
17263 this.inLink = false;
17268 if ((cap = this.rules.reflink.exec(src))
17269 || (cap = this.rules.nolink.exec(src))) {
17270 src = src.substring(cap[0].length);
17271 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
17272 link = this.links[link.toLowerCase()];
17273 if (!link || !link.href) {
17274 out += cap[0].charAt(0);
17275 src = cap[0].substring(1) + src;
17278 this.inLink = true;
17279 out += this.outputLink(cap, link);
17280 this.inLink = false;
17285 if (cap = this.rules.strong.exec(src)) {
17286 src = src.substring(cap[0].length);
17287 out += this.renderer.strong(this.output(cap[2] || cap[1]));
17292 if (cap = this.rules.em.exec(src)) {
17293 src = src.substring(cap[0].length);
17294 out += this.renderer.em(this.output(cap[2] || cap[1]));
17299 if (cap = this.rules.code.exec(src)) {
17300 src = src.substring(cap[0].length);
17301 out += this.renderer.codespan(escape(cap[2], true));
17306 if (cap = this.rules.br.exec(src)) {
17307 src = src.substring(cap[0].length);
17308 out += this.renderer.br();
17313 if (cap = this.rules.del.exec(src)) {
17314 src = src.substring(cap[0].length);
17315 out += this.renderer.del(this.output(cap[1]));
17320 if (cap = this.rules.text.exec(src)) {
17321 src = src.substring(cap[0].length);
17322 out += this.renderer.text(escape(this.smartypants(cap[0])));
17328 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17339 InlineLexer.prototype.outputLink = function(cap, link) {
17340 var href = escape(link.href)
17341 , title = link.title ? escape(link.title) : null;
17343 return cap[0].charAt(0) !== '!'
17344 ? this.renderer.link(href, title, this.output(cap[1]))
17345 : this.renderer.image(href, title, escape(cap[1]));
17349 * Smartypants Transformations
17352 InlineLexer.prototype.smartypants = function(text) {
17353 if (!this.options.smartypants) { return text; }
17356 .replace(/---/g, '\u2014')
17358 .replace(/--/g, '\u2013')
17360 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
17361 // closing singles & apostrophes
17362 .replace(/'/g, '\u2019')
17364 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
17366 .replace(/"/g, '\u201d')
17368 .replace(/\.{3}/g, '\u2026');
17375 InlineLexer.prototype.mangle = function(text) {
17376 if (!this.options.mangle) { return text; }
17382 for (; i < l; i++) {
17383 ch = text.charCodeAt(i);
17384 if (Math.random() > 0.5) {
17385 ch = 'x' + ch.toString(16);
17387 out += '&#' + ch + ';';
17397 function Renderer(options) {
17398 this.options = options || {};
17401 Renderer.prototype.code = function(code, lang, escaped) {
17402 if (this.options.highlight) {
17403 var out = this.options.highlight(code, lang);
17404 if (out != null && out !== code) {
17409 // hack!!! - it's already escapeD?
17414 return '<pre><code>'
17415 + (escaped ? code : escape(code, true))
17416 + '\n</code></pre>';
17419 return '<pre><code class="'
17420 + this.options.langPrefix
17421 + escape(lang, true)
17423 + (escaped ? code : escape(code, true))
17424 + '\n</code></pre>\n';
17427 Renderer.prototype.blockquote = function(quote) {
17428 return '<blockquote>\n' + quote + '</blockquote>\n';
17431 Renderer.prototype.html = function(html) {
17435 Renderer.prototype.heading = function(text, level, raw) {
17439 + this.options.headerPrefix
17440 + raw.toLowerCase().replace(/[^\w]+/g, '-')
17448 Renderer.prototype.hr = function() {
17449 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
17452 Renderer.prototype.list = function(body, ordered) {
17453 var type = ordered ? 'ol' : 'ul';
17454 return '<' + type + '>\n' + body + '</' + type + '>\n';
17457 Renderer.prototype.listitem = function(text) {
17458 return '<li>' + text + '</li>\n';
17461 Renderer.prototype.paragraph = function(text) {
17462 return '<p>' + text + '</p>\n';
17465 Renderer.prototype.table = function(header, body) {
17466 return '<table class="table table-striped">\n'
17476 Renderer.prototype.tablerow = function(content) {
17477 return '<tr>\n' + content + '</tr>\n';
17480 Renderer.prototype.tablecell = function(content, flags) {
17481 var type = flags.header ? 'th' : 'td';
17482 var tag = flags.align
17483 ? '<' + type + ' style="text-align:' + flags.align + '">'
17484 : '<' + type + '>';
17485 return tag + content + '</' + type + '>\n';
17488 // span level renderer
17489 Renderer.prototype.strong = function(text) {
17490 return '<strong>' + text + '</strong>';
17493 Renderer.prototype.em = function(text) {
17494 return '<em>' + text + '</em>';
17497 Renderer.prototype.codespan = function(text) {
17498 return '<code>' + text + '</code>';
17501 Renderer.prototype.br = function() {
17502 return this.options.xhtml ? '<br/>' : '<br>';
17505 Renderer.prototype.del = function(text) {
17506 return '<del>' + text + '</del>';
17509 Renderer.prototype.link = function(href, title, text) {
17510 if (this.options.sanitize) {
17512 var prot = decodeURIComponent(unescape(href))
17513 .replace(/[^\w:]/g, '')
17518 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
17522 var out = '<a href="' + href + '"';
17524 out += ' title="' + title + '"';
17526 out += '>' + text + '</a>';
17530 Renderer.prototype.image = function(href, title, text) {
17531 var out = '<img src="' + href + '" alt="' + text + '"';
17533 out += ' title="' + title + '"';
17535 out += this.options.xhtml ? '/>' : '>';
17539 Renderer.prototype.text = function(text) {
17544 * Parsing & Compiling
17547 function Parser(options) {
17550 this.options = options || marked.defaults;
17551 this.options.renderer = this.options.renderer || new Renderer;
17552 this.renderer = this.options.renderer;
17553 this.renderer.options = this.options;
17557 * Static Parse Method
17560 Parser.parse = function(src, options, renderer) {
17561 var parser = new Parser(options, renderer);
17562 return parser.parse(src);
17569 Parser.prototype.parse = function(src) {
17570 this.inline = new InlineLexer(src.links, this.options, this.renderer);
17571 this.tokens = src.reverse();
17574 while (this.next()) {
17585 Parser.prototype.next = function() {
17586 return this.token = this.tokens.pop();
17590 * Preview Next Token
17593 Parser.prototype.peek = function() {
17594 return this.tokens[this.tokens.length - 1] || 0;
17598 * Parse Text Tokens
17601 Parser.prototype.parseText = function() {
17602 var body = this.token.text;
17604 while (this.peek().type === 'text') {
17605 body += '\n' + this.next().text;
17608 return this.inline.output(body);
17612 * Parse Current Token
17615 Parser.prototype.tok = function() {
17616 switch (this.token.type) {
17621 return this.renderer.hr();
17624 return this.renderer.heading(
17625 this.inline.output(this.token.text),
17630 return this.renderer.code(this.token.text,
17632 this.token.escaped);
17645 for (i = 0; i < this.token.header.length; i++) {
17646 flags = { header: true, align: this.token.align[i] };
17647 cell += this.renderer.tablecell(
17648 this.inline.output(this.token.header[i]),
17649 { header: true, align: this.token.align[i] }
17652 header += this.renderer.tablerow(cell);
17654 for (i = 0; i < this.token.cells.length; i++) {
17655 row = this.token.cells[i];
17658 for (j = 0; j < row.length; j++) {
17659 cell += this.renderer.tablecell(
17660 this.inline.output(row[j]),
17661 { header: false, align: this.token.align[j] }
17665 body += this.renderer.tablerow(cell);
17667 return this.renderer.table(header, body);
17669 case 'blockquote_start': {
17672 while (this.next().type !== 'blockquote_end') {
17673 body += this.tok();
17676 return this.renderer.blockquote(body);
17678 case 'list_start': {
17680 , ordered = this.token.ordered;
17682 while (this.next().type !== 'list_end') {
17683 body += this.tok();
17686 return this.renderer.list(body, ordered);
17688 case 'list_item_start': {
17691 while (this.next().type !== 'list_item_end') {
17692 body += this.token.type === 'text'
17697 return this.renderer.listitem(body);
17699 case 'loose_item_start': {
17702 while (this.next().type !== 'list_item_end') {
17703 body += this.tok();
17706 return this.renderer.listitem(body);
17709 var html = !this.token.pre && !this.options.pedantic
17710 ? this.inline.output(this.token.text)
17712 return this.renderer.html(html);
17714 case 'paragraph': {
17715 return this.renderer.paragraph(this.inline.output(this.token.text));
17718 return this.renderer.paragraph(this.parseText());
17727 function escape(html, encode) {
17729 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
17730 .replace(/</g, '<')
17731 .replace(/>/g, '>')
17732 .replace(/"/g, '"')
17733 .replace(/'/g, ''');
17736 function unescape(html) {
17737 // explicitly match decimal, hex, and named HTML entities
17738 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
17739 n = n.toLowerCase();
17740 if (n === 'colon') { return ':'; }
17741 if (n.charAt(0) === '#') {
17742 return n.charAt(1) === 'x'
17743 ? String.fromCharCode(parseInt(n.substring(2), 16))
17744 : String.fromCharCode(+n.substring(1));
17750 function replace(regex, opt) {
17751 regex = regex.source;
17753 return function self(name, val) {
17754 if (!name) { return new RegExp(regex, opt); }
17755 val = val.source || val;
17756 val = val.replace(/(^|[^\[])\^/g, '$1');
17757 regex = regex.replace(name, val);
17765 function merge(obj) {
17770 for (; i < arguments.length; i++) {
17771 target = arguments[i];
17772 for (key in target) {
17773 if (Object.prototype.hasOwnProperty.call(target, key)) {
17774 obj[key] = target[key];
17787 function marked(src, opt, callback) {
17788 if (callback || typeof opt === 'function') {
17794 opt = merge({}, marked.defaults, opt || {});
17796 var highlight = opt.highlight
17802 tokens = Lexer.lex(src, opt)
17804 return callback(e);
17807 pending = tokens.length;
17809 var done = function(err) {
17811 opt.highlight = highlight;
17812 return callback(err);
17818 out = Parser.parse(tokens, opt);
17823 opt.highlight = highlight;
17827 : callback(null, out);
17830 if (!highlight || highlight.length < 3) {
17834 delete opt.highlight;
17836 if (!pending) { return done(); }
17838 for (; i < tokens.length; i++) {
17840 if (token.type !== 'code') {
17841 return --pending || done();
17843 return highlight(token.text, token.lang, function(err, code) {
17844 if (err) { return done(err); }
17845 if (code == null || code === token.text) {
17846 return --pending || done();
17849 token.escaped = true;
17850 --pending || done();
17858 if (opt) { opt = merge({}, marked.defaults, opt); }
17859 return Parser.parse(Lexer.lex(src, opt), opt);
17861 e.message += '\nPlease report this to https://github.com/chjj/marked.';
17862 if ((opt || marked.defaults).silent) {
17863 return '<p>An error occured:</p><pre>'
17864 + escape(e.message + '', true)
17876 marked.setOptions = function(opt) {
17877 merge(marked.defaults, opt);
17881 marked.defaults = {
17892 langPrefix: 'lang-',
17893 smartypants: false,
17895 renderer: new Renderer,
17903 marked.Parser = Parser;
17904 marked.parser = Parser.parse;
17906 marked.Renderer = Renderer;
17908 marked.Lexer = Lexer;
17909 marked.lexer = Lexer.lex;
17911 marked.InlineLexer = InlineLexer;
17912 marked.inlineLexer = InlineLexer.output;
17914 marked.parse = marked;
17916 Roo.Markdown.marked = marked;
17920 * Ext JS Library 1.1.1
17921 * Copyright(c) 2006-2007, Ext JS, LLC.
17923 * Originally Released Under LGPL - original licence link has changed is not relivant.
17926 * <script type="text/javascript">
17932 * These classes are derivatives of the similarly named classes in the YUI Library.
17933 * The original license:
17934 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
17935 * Code licensed under the BSD License:
17936 * http://developer.yahoo.net/yui/license.txt
17941 var Event=Roo.EventManager;
17942 var Dom=Roo.lib.Dom;
17945 * @class Roo.dd.DragDrop
17946 * @extends Roo.util.Observable
17947 * Defines the interface and base operation of items that that can be
17948 * dragged or can be drop targets. It was designed to be extended, overriding
17949 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
17950 * Up to three html elements can be associated with a DragDrop instance:
17952 * <li>linked element: the element that is passed into the constructor.
17953 * This is the element which defines the boundaries for interaction with
17954 * other DragDrop objects.</li>
17955 * <li>handle element(s): The drag operation only occurs if the element that
17956 * was clicked matches a handle element. By default this is the linked
17957 * element, but there are times that you will want only a portion of the
17958 * linked element to initiate the drag operation, and the setHandleElId()
17959 * method provides a way to define this.</li>
17960 * <li>drag element: this represents the element that would be moved along
17961 * with the cursor during a drag operation. By default, this is the linked
17962 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
17963 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
17966 * This class should not be instantiated until the onload event to ensure that
17967 * the associated elements are available.
17968 * The following would define a DragDrop obj that would interact with any
17969 * other DragDrop obj in the "group1" group:
17971 * dd = new Roo.dd.DragDrop("div1", "group1");
17973 * Since none of the event handlers have been implemented, nothing would
17974 * actually happen if you were to run the code above. Normally you would
17975 * override this class or one of the default implementations, but you can
17976 * also override the methods you want on an instance of the class...
17978 * dd.onDragDrop = function(e, id) {
17979 * alert("dd was dropped on " + id);
17983 * @param {String} id of the element that is linked to this instance
17984 * @param {String} sGroup the group of related DragDrop objects
17985 * @param {object} config an object containing configurable attributes
17986 * Valid properties for DragDrop:
17987 * padding, isTarget, maintainOffset, primaryButtonOnly
17989 Roo.dd.DragDrop = function(id, sGroup, config) {
17991 this.init(id, sGroup, config);
17996 Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
17999 * The id of the element associated with this object. This is what we
18000 * refer to as the "linked element" because the size and position of
18001 * this element is used to determine when the drag and drop objects have
18009 * Configuration attributes passed into the constructor
18016 * The id of the element that will be dragged. By default this is same
18017 * as the linked element , but could be changed to another element. Ex:
18019 * @property dragElId
18026 * the id of the element that initiates the drag operation. By default
18027 * this is the linked element, but could be changed to be a child of this
18028 * element. This lets us do things like only starting the drag when the
18029 * header element within the linked html element is clicked.
18030 * @property handleElId
18037 * An associative array of HTML tags that will be ignored if clicked.
18038 * @property invalidHandleTypes
18039 * @type {string: string}
18041 invalidHandleTypes: null,
18044 * An associative array of ids for elements that will be ignored if clicked
18045 * @property invalidHandleIds
18046 * @type {string: string}
18048 invalidHandleIds: null,
18051 * An indexted array of css class names for elements that will be ignored
18053 * @property invalidHandleClasses
18056 invalidHandleClasses: null,
18059 * The linked element's absolute X position at the time the drag was
18061 * @property startPageX
18068 * The linked element's absolute X position at the time the drag was
18070 * @property startPageY
18077 * The group defines a logical collection of DragDrop objects that are
18078 * related. Instances only get events when interacting with other
18079 * DragDrop object in the same group. This lets us define multiple
18080 * groups using a single DragDrop subclass if we want.
18082 * @type {string: string}
18087 * Individual drag/drop instances can be locked. This will prevent
18088 * onmousedown start drag.
18096 * Lock this instance
18099 lock: function() { this.locked = true; },
18102 * Unlock this instace
18105 unlock: function() { this.locked = false; },
18108 * By default, all insances can be a drop target. This can be disabled by
18109 * setting isTarget to false.
18116 * The padding configured for this drag and drop object for calculating
18117 * the drop zone intersection with this object.
18124 * Cached reference to the linked element
18125 * @property _domRef
18131 * Internal typeof flag
18132 * @property __ygDragDrop
18135 __ygDragDrop: true,
18138 * Set to true when horizontal contraints are applied
18139 * @property constrainX
18146 * Set to true when vertical contraints are applied
18147 * @property constrainY
18154 * The left constraint
18162 * The right constraint
18170 * The up constraint
18179 * The down constraint
18187 * Maintain offsets when we resetconstraints. Set to true when you want
18188 * the position of the element relative to its parent to stay the same
18189 * when the page changes
18191 * @property maintainOffset
18194 maintainOffset: false,
18197 * Array of pixel locations the element will snap to if we specified a
18198 * horizontal graduation/interval. This array is generated automatically
18199 * when you define a tick interval.
18206 * Array of pixel locations the element will snap to if we specified a
18207 * vertical graduation/interval. This array is generated automatically
18208 * when you define a tick interval.
18215 * By default the drag and drop instance will only respond to the primary
18216 * button click (left button for a right-handed mouse). Set to true to
18217 * allow drag and drop to start with any mouse click that is propogated
18219 * @property primaryButtonOnly
18222 primaryButtonOnly: true,
18225 * The availabe property is false until the linked dom element is accessible.
18226 * @property available
18232 * By default, drags can only be initiated if the mousedown occurs in the
18233 * region the linked element is. This is done in part to work around a
18234 * bug in some browsers that mis-report the mousedown if the previous
18235 * mouseup happened outside of the window. This property is set to true
18236 * if outer handles are defined.
18238 * @property hasOuterHandles
18242 hasOuterHandles: false,
18245 * Code that executes immediately before the startDrag event
18246 * @method b4StartDrag
18249 b4StartDrag: function(x, y) { },
18252 * Abstract method called after a drag/drop object is clicked
18253 * and the drag or mousedown time thresholds have beeen met.
18254 * @method startDrag
18255 * @param {int} X click location
18256 * @param {int} Y click location
18258 startDrag: function(x, y) { /* override this */ },
18261 * Code that executes immediately before the onDrag event
18265 b4Drag: function(e) { },
18268 * Abstract method called during the onMouseMove event while dragging an
18271 * @param {Event} e the mousemove event
18273 onDrag: function(e) { /* override this */ },
18276 * Abstract method called when this element fist begins hovering over
18277 * another DragDrop obj
18278 * @method onDragEnter
18279 * @param {Event} e the mousemove event
18280 * @param {String|DragDrop[]} id In POINT mode, the element
18281 * id this is hovering over. In INTERSECT mode, an array of one or more
18282 * dragdrop items being hovered over.
18284 onDragEnter: function(e, id) { /* override this */ },
18287 * Code that executes immediately before the onDragOver event
18288 * @method b4DragOver
18291 b4DragOver: function(e) { },
18294 * Abstract method called when this element is hovering over another
18296 * @method onDragOver
18297 * @param {Event} e the mousemove event
18298 * @param {String|DragDrop[]} id In POINT mode, the element
18299 * id this is hovering over. In INTERSECT mode, an array of dd items
18300 * being hovered over.
18302 onDragOver: function(e, id) { /* override this */ },
18305 * Code that executes immediately before the onDragOut event
18306 * @method b4DragOut
18309 b4DragOut: function(e) { },
18312 * Abstract method called when we are no longer hovering over an element
18313 * @method onDragOut
18314 * @param {Event} e the mousemove event
18315 * @param {String|DragDrop[]} id In POINT mode, the element
18316 * id this was hovering over. In INTERSECT mode, an array of dd items
18317 * that the mouse is no longer over.
18319 onDragOut: function(e, id) { /* override this */ },
18322 * Code that executes immediately before the onDragDrop event
18323 * @method b4DragDrop
18326 b4DragDrop: function(e) { },
18329 * Abstract method called when this item is dropped on another DragDrop
18331 * @method onDragDrop
18332 * @param {Event} e the mouseup event
18333 * @param {String|DragDrop[]} id In POINT mode, the element
18334 * id this was dropped on. In INTERSECT mode, an array of dd items this
18337 onDragDrop: function(e, id) { /* override this */ },
18340 * Abstract method called when this item is dropped on an area with no
18342 * @method onInvalidDrop
18343 * @param {Event} e the mouseup event
18345 onInvalidDrop: function(e) { /* override this */ },
18348 * Code that executes immediately before the endDrag event
18349 * @method b4EndDrag
18352 b4EndDrag: function(e) { },
18355 * Fired when we are done dragging the object
18357 * @param {Event} e the mouseup event
18359 endDrag: function(e) { /* override this */ },
18362 * Code executed immediately before the onMouseDown event
18363 * @method b4MouseDown
18364 * @param {Event} e the mousedown event
18367 b4MouseDown: function(e) { },
18370 * Event handler that fires when a drag/drop obj gets a mousedown
18371 * @method onMouseDown
18372 * @param {Event} e the mousedown event
18374 onMouseDown: function(e) { /* override this */ },
18377 * Event handler that fires when a drag/drop obj gets a mouseup
18378 * @method onMouseUp
18379 * @param {Event} e the mouseup event
18381 onMouseUp: function(e) { /* override this */ },
18384 * Override the onAvailable method to do what is needed after the initial
18385 * position was determined.
18386 * @method onAvailable
18388 onAvailable: function () {
18392 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
18395 defaultPadding : {left:0, right:0, top:0, bottom:0},
18398 * Initializes the drag drop object's constraints to restrict movement to a certain element.
18402 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
18403 { dragElId: "existingProxyDiv" });
18404 dd.startDrag = function(){
18405 this.constrainTo("parent-id");
18408 * Or you can initalize it using the {@link Roo.Element} object:
18410 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
18411 startDrag : function(){
18412 this.constrainTo("parent-id");
18416 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
18417 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
18418 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
18419 * an object containing the sides to pad. For example: {right:10, bottom:10}
18420 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
18422 constrainTo : function(constrainTo, pad, inContent){
18423 if(typeof pad == "number"){
18424 pad = {left: pad, right:pad, top:pad, bottom:pad};
18426 pad = pad || this.defaultPadding;
18427 var b = Roo.get(this.getEl()).getBox();
18428 var ce = Roo.get(constrainTo);
18429 var s = ce.getScroll();
18430 var c, cd = ce.dom;
18431 if(cd == document.body){
18432 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
18435 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
18439 var topSpace = b.y - c.y;
18440 var leftSpace = b.x - c.x;
18442 this.resetConstraints();
18443 this.setXConstraint(leftSpace - (pad.left||0), // left
18444 c.width - leftSpace - b.width - (pad.right||0) //right
18446 this.setYConstraint(topSpace - (pad.top||0), //top
18447 c.height - topSpace - b.height - (pad.bottom||0) //bottom
18452 * Returns a reference to the linked element
18454 * @return {HTMLElement} the html element
18456 getEl: function() {
18457 if (!this._domRef) {
18458 this._domRef = Roo.getDom(this.id);
18461 return this._domRef;
18465 * Returns a reference to the actual element to drag. By default this is
18466 * the same as the html element, but it can be assigned to another
18467 * element. An example of this can be found in Roo.dd.DDProxy
18468 * @method getDragEl
18469 * @return {HTMLElement} the html element
18471 getDragEl: function() {
18472 return Roo.getDom(this.dragElId);
18476 * Sets up the DragDrop object. Must be called in the constructor of any
18477 * Roo.dd.DragDrop subclass
18479 * @param id the id of the linked element
18480 * @param {String} sGroup the group of related items
18481 * @param {object} config configuration attributes
18483 init: function(id, sGroup, config) {
18484 this.initTarget(id, sGroup, config);
18485 if (!Roo.isTouch) {
18486 Event.on(this.id, "mousedown", this.handleMouseDown, this);
18488 Event.on(this.id, "touchstart", this.handleMouseDown, this);
18489 // Event.on(this.id, "selectstart", Event.preventDefault);
18493 * Initializes Targeting functionality only... the object does not
18494 * get a mousedown handler.
18495 * @method initTarget
18496 * @param id the id of the linked element
18497 * @param {String} sGroup the group of related items
18498 * @param {object} config configuration attributes
18500 initTarget: function(id, sGroup, config) {
18502 // configuration attributes
18503 this.config = config || {};
18505 // create a local reference to the drag and drop manager
18506 this.DDM = Roo.dd.DDM;
18507 // initialize the groups array
18510 // assume that we have an element reference instead of an id if the
18511 // parameter is not a string
18512 if (typeof id !== "string") {
18519 // add to an interaction group
18520 this.addToGroup((sGroup) ? sGroup : "default");
18522 // We don't want to register this as the handle with the manager
18523 // so we just set the id rather than calling the setter.
18524 this.handleElId = id;
18526 // the linked element is the element that gets dragged by default
18527 this.setDragElId(id);
18529 // by default, clicked anchors will not start drag operations.
18530 this.invalidHandleTypes = { A: "A" };
18531 this.invalidHandleIds = {};
18532 this.invalidHandleClasses = [];
18534 this.applyConfig();
18536 this.handleOnAvailable();
18540 * Applies the configuration parameters that were passed into the constructor.
18541 * This is supposed to happen at each level through the inheritance chain. So
18542 * a DDProxy implentation will execute apply config on DDProxy, DD, and
18543 * DragDrop in order to get all of the parameters that are available in
18545 * @method applyConfig
18547 applyConfig: function() {
18549 // configurable properties:
18550 // padding, isTarget, maintainOffset, primaryButtonOnly
18551 this.padding = this.config.padding || [0, 0, 0, 0];
18552 this.isTarget = (this.config.isTarget !== false);
18553 this.maintainOffset = (this.config.maintainOffset);
18554 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
18559 * Executed when the linked element is available
18560 * @method handleOnAvailable
18563 handleOnAvailable: function() {
18564 this.available = true;
18565 this.resetConstraints();
18566 this.onAvailable();
18570 * Configures the padding for the target zone in px. Effectively expands
18571 * (or reduces) the virtual object size for targeting calculations.
18572 * Supports css-style shorthand; if only one parameter is passed, all sides
18573 * will have that padding, and if only two are passed, the top and bottom
18574 * will have the first param, the left and right the second.
18575 * @method setPadding
18576 * @param {int} iTop Top pad
18577 * @param {int} iRight Right pad
18578 * @param {int} iBot Bot pad
18579 * @param {int} iLeft Left pad
18581 setPadding: function(iTop, iRight, iBot, iLeft) {
18582 // this.padding = [iLeft, iRight, iTop, iBot];
18583 if (!iRight && 0 !== iRight) {
18584 this.padding = [iTop, iTop, iTop, iTop];
18585 } else if (!iBot && 0 !== iBot) {
18586 this.padding = [iTop, iRight, iTop, iRight];
18588 this.padding = [iTop, iRight, iBot, iLeft];
18593 * Stores the initial placement of the linked element.
18594 * @method setInitialPosition
18595 * @param {int} diffX the X offset, default 0
18596 * @param {int} diffY the Y offset, default 0
18598 setInitPosition: function(diffX, diffY) {
18599 var el = this.getEl();
18601 if (!this.DDM.verifyEl(el)) {
18605 var dx = diffX || 0;
18606 var dy = diffY || 0;
18608 var p = Dom.getXY( el );
18610 this.initPageX = p[0] - dx;
18611 this.initPageY = p[1] - dy;
18613 this.lastPageX = p[0];
18614 this.lastPageY = p[1];
18617 this.setStartPosition(p);
18621 * Sets the start position of the element. This is set when the obj
18622 * is initialized, the reset when a drag is started.
18623 * @method setStartPosition
18624 * @param pos current position (from previous lookup)
18627 setStartPosition: function(pos) {
18628 var p = pos || Dom.getXY( this.getEl() );
18629 this.deltaSetXY = null;
18631 this.startPageX = p[0];
18632 this.startPageY = p[1];
18636 * Add this instance to a group of related drag/drop objects. All
18637 * instances belong to at least one group, and can belong to as many
18638 * groups as needed.
18639 * @method addToGroup
18640 * @param sGroup {string} the name of the group
18642 addToGroup: function(sGroup) {
18643 this.groups[sGroup] = true;
18644 this.DDM.regDragDrop(this, sGroup);
18648 * Remove's this instance from the supplied interaction group
18649 * @method removeFromGroup
18650 * @param {string} sGroup The group to drop
18652 removeFromGroup: function(sGroup) {
18653 if (this.groups[sGroup]) {
18654 delete this.groups[sGroup];
18657 this.DDM.removeDDFromGroup(this, sGroup);
18661 * Allows you to specify that an element other than the linked element
18662 * will be moved with the cursor during a drag
18663 * @method setDragElId
18664 * @param id {string} the id of the element that will be used to initiate the drag
18666 setDragElId: function(id) {
18667 this.dragElId = id;
18671 * Allows you to specify a child of the linked element that should be
18672 * used to initiate the drag operation. An example of this would be if
18673 * you have a content div with text and links. Clicking anywhere in the
18674 * content area would normally start the drag operation. Use this method
18675 * to specify that an element inside of the content div is the element
18676 * that starts the drag operation.
18677 * @method setHandleElId
18678 * @param id {string} the id of the element that will be used to
18679 * initiate the drag.
18681 setHandleElId: function(id) {
18682 if (typeof id !== "string") {
18685 this.handleElId = id;
18686 this.DDM.regHandle(this.id, id);
18690 * Allows you to set an element outside of the linked element as a drag
18692 * @method setOuterHandleElId
18693 * @param id the id of the element that will be used to initiate the drag
18695 setOuterHandleElId: function(id) {
18696 if (typeof id !== "string") {
18699 Event.on(id, "mousedown",
18700 this.handleMouseDown, this);
18701 this.setHandleElId(id);
18703 this.hasOuterHandles = true;
18707 * Remove all drag and drop hooks for this element
18710 unreg: function() {
18711 Event.un(this.id, "mousedown",
18712 this.handleMouseDown);
18713 Event.un(this.id, "touchstart",
18714 this.handleMouseDown);
18715 this._domRef = null;
18716 this.DDM._remove(this);
18719 destroy : function(){
18724 * Returns true if this instance is locked, or the drag drop mgr is locked
18725 * (meaning that all drag/drop is disabled on the page.)
18727 * @return {boolean} true if this obj or all drag/drop is locked, else
18730 isLocked: function() {
18731 return (this.DDM.isLocked() || this.locked);
18735 * Fired when this object is clicked
18736 * @method handleMouseDown
18738 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
18741 handleMouseDown: function(e, oDD){
18743 if (!Roo.isTouch && this.primaryButtonOnly && e.button != 0) {
18744 //Roo.log('not touch/ button !=0');
18747 if (e.browserEvent.touches && e.browserEvent.touches.length != 1) {
18748 return; // double touch..
18752 if (this.isLocked()) {
18753 //Roo.log('locked');
18757 this.DDM.refreshCache(this.groups);
18758 // Roo.log([Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e)]);
18759 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
18760 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
18761 //Roo.log('no outer handes or not over target');
18764 // Roo.log('check validator');
18765 if (this.clickValidator(e)) {
18766 // Roo.log('validate success');
18767 // set the initial element position
18768 this.setStartPosition();
18771 this.b4MouseDown(e);
18772 this.onMouseDown(e);
18774 this.DDM.handleMouseDown(e, this);
18776 this.DDM.stopEvent(e);
18784 clickValidator: function(e) {
18785 var target = e.getTarget();
18786 return ( this.isValidHandleChild(target) &&
18787 (this.id == this.handleElId ||
18788 this.DDM.handleWasClicked(target, this.id)) );
18792 * Allows you to specify a tag name that should not start a drag operation
18793 * when clicked. This is designed to facilitate embedding links within a
18794 * drag handle that do something other than start the drag.
18795 * @method addInvalidHandleType
18796 * @param {string} tagName the type of element to exclude
18798 addInvalidHandleType: function(tagName) {
18799 var type = tagName.toUpperCase();
18800 this.invalidHandleTypes[type] = type;
18804 * Lets you to specify an element id for a child of a drag handle
18805 * that should not initiate a drag
18806 * @method addInvalidHandleId
18807 * @param {string} id the element id of the element you wish to ignore
18809 addInvalidHandleId: function(id) {
18810 if (typeof id !== "string") {
18813 this.invalidHandleIds[id] = id;
18817 * Lets you specify a css class of elements that will not initiate a drag
18818 * @method addInvalidHandleClass
18819 * @param {string} cssClass the class of the elements you wish to ignore
18821 addInvalidHandleClass: function(cssClass) {
18822 this.invalidHandleClasses.push(cssClass);
18826 * Unsets an excluded tag name set by addInvalidHandleType
18827 * @method removeInvalidHandleType
18828 * @param {string} tagName the type of element to unexclude
18830 removeInvalidHandleType: function(tagName) {
18831 var type = tagName.toUpperCase();
18832 // this.invalidHandleTypes[type] = null;
18833 delete this.invalidHandleTypes[type];
18837 * Unsets an invalid handle id
18838 * @method removeInvalidHandleId
18839 * @param {string} id the id of the element to re-enable
18841 removeInvalidHandleId: function(id) {
18842 if (typeof id !== "string") {
18845 delete this.invalidHandleIds[id];
18849 * Unsets an invalid css class
18850 * @method removeInvalidHandleClass
18851 * @param {string} cssClass the class of the element(s) you wish to
18854 removeInvalidHandleClass: function(cssClass) {
18855 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
18856 if (this.invalidHandleClasses[i] == cssClass) {
18857 delete this.invalidHandleClasses[i];
18863 * Checks the tag exclusion list to see if this click should be ignored
18864 * @method isValidHandleChild
18865 * @param {HTMLElement} node the HTMLElement to evaluate
18866 * @return {boolean} true if this is a valid tag type, false if not
18868 isValidHandleChild: function(node) {
18871 // var n = (node.nodeName == "#text") ? node.parentNode : node;
18874 nodeName = node.nodeName.toUpperCase();
18876 nodeName = node.nodeName;
18878 valid = valid && !this.invalidHandleTypes[nodeName];
18879 valid = valid && !this.invalidHandleIds[node.id];
18881 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
18882 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
18891 * Create the array of horizontal tick marks if an interval was specified
18892 * in setXConstraint().
18893 * @method setXTicks
18896 setXTicks: function(iStartX, iTickSize) {
18898 this.xTickSize = iTickSize;
18902 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
18904 this.xTicks[this.xTicks.length] = i;
18909 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
18911 this.xTicks[this.xTicks.length] = i;
18916 this.xTicks.sort(this.DDM.numericSort) ;
18920 * Create the array of vertical tick marks if an interval was specified in
18921 * setYConstraint().
18922 * @method setYTicks
18925 setYTicks: function(iStartY, iTickSize) {
18927 this.yTickSize = iTickSize;
18931 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
18933 this.yTicks[this.yTicks.length] = i;
18938 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
18940 this.yTicks[this.yTicks.length] = i;
18945 this.yTicks.sort(this.DDM.numericSort) ;
18949 * By default, the element can be dragged any place on the screen. Use
18950 * this method to limit the horizontal travel of the element. Pass in
18951 * 0,0 for the parameters if you want to lock the drag to the y axis.
18952 * @method setXConstraint
18953 * @param {int} iLeft the number of pixels the element can move to the left
18954 * @param {int} iRight the number of pixels the element can move to the
18956 * @param {int} iTickSize optional parameter for specifying that the
18958 * should move iTickSize pixels at a time.
18960 setXConstraint: function(iLeft, iRight, iTickSize) {
18961 this.leftConstraint = iLeft;
18962 this.rightConstraint = iRight;
18964 this.minX = this.initPageX - iLeft;
18965 this.maxX = this.initPageX + iRight;
18966 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
18968 this.constrainX = true;
18972 * Clears any constraints applied to this instance. Also clears ticks
18973 * since they can't exist independent of a constraint at this time.
18974 * @method clearConstraints
18976 clearConstraints: function() {
18977 this.constrainX = false;
18978 this.constrainY = false;
18983 * Clears any tick interval defined for this instance
18984 * @method clearTicks
18986 clearTicks: function() {
18987 this.xTicks = null;
18988 this.yTicks = null;
18989 this.xTickSize = 0;
18990 this.yTickSize = 0;
18994 * By default, the element can be dragged any place on the screen. Set
18995 * this to limit the vertical travel of the element. Pass in 0,0 for the
18996 * parameters if you want to lock the drag to the x axis.
18997 * @method setYConstraint
18998 * @param {int} iUp the number of pixels the element can move up
18999 * @param {int} iDown the number of pixels the element can move down
19000 * @param {int} iTickSize optional parameter for specifying that the
19001 * element should move iTickSize pixels at a time.
19003 setYConstraint: function(iUp, iDown, iTickSize) {
19004 this.topConstraint = iUp;
19005 this.bottomConstraint = iDown;
19007 this.minY = this.initPageY - iUp;
19008 this.maxY = this.initPageY + iDown;
19009 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
19011 this.constrainY = true;
19016 * resetConstraints must be called if you manually reposition a dd element.
19017 * @method resetConstraints
19018 * @param {boolean} maintainOffset
19020 resetConstraints: function() {
19023 // Maintain offsets if necessary
19024 if (this.initPageX || this.initPageX === 0) {
19025 // figure out how much this thing has moved
19026 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
19027 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
19029 this.setInitPosition(dx, dy);
19031 // This is the first time we have detected the element's position
19033 this.setInitPosition();
19036 if (this.constrainX) {
19037 this.setXConstraint( this.leftConstraint,
19038 this.rightConstraint,
19042 if (this.constrainY) {
19043 this.setYConstraint( this.topConstraint,
19044 this.bottomConstraint,
19050 * Normally the drag element is moved pixel by pixel, but we can specify
19051 * that it move a number of pixels at a time. This method resolves the
19052 * location when we have it set up like this.
19054 * @param {int} val where we want to place the object
19055 * @param {int[]} tickArray sorted array of valid points
19056 * @return {int} the closest tick
19059 getTick: function(val, tickArray) {
19062 // If tick interval is not defined, it is effectively 1 pixel,
19063 // so we return the value passed to us.
19065 } else if (tickArray[0] >= val) {
19066 // The value is lower than the first tick, so we return the first
19068 return tickArray[0];
19070 for (var i=0, len=tickArray.length; i<len; ++i) {
19072 if (tickArray[next] && tickArray[next] >= val) {
19073 var diff1 = val - tickArray[i];
19074 var diff2 = tickArray[next] - val;
19075 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
19079 // The value is larger than the last tick, so we return the last
19081 return tickArray[tickArray.length - 1];
19088 * @return {string} string representation of the dd obj
19090 toString: function() {
19091 return ("DragDrop " + this.id);
19099 * Ext JS Library 1.1.1
19100 * Copyright(c) 2006-2007, Ext JS, LLC.
19102 * Originally Released Under LGPL - original licence link has changed is not relivant.
19105 * <script type="text/javascript">
19110 * The drag and drop utility provides a framework for building drag and drop
19111 * applications. In addition to enabling drag and drop for specific elements,
19112 * the drag and drop elements are tracked by the manager class, and the
19113 * interactions between the various elements are tracked during the drag and
19114 * the implementing code is notified about these important moments.
19117 // Only load the library once. Rewriting the manager class would orphan
19118 // existing drag and drop instances.
19119 if (!Roo.dd.DragDropMgr) {
19122 * @class Roo.dd.DragDropMgr
19123 * DragDropMgr is a singleton that tracks the element interaction for
19124 * all DragDrop items in the window. Generally, you will not call
19125 * this class directly, but it does have helper methods that could
19126 * be useful in your DragDrop implementations.
19129 Roo.dd.DragDropMgr = function() {
19131 var Event = Roo.EventManager;
19136 * Two dimensional Array of registered DragDrop objects. The first
19137 * dimension is the DragDrop item group, the second the DragDrop
19140 * @type {string: string}
19147 * Array of element ids defined as drag handles. Used to determine
19148 * if the element that generated the mousedown event is actually the
19149 * handle and not the html element itself.
19150 * @property handleIds
19151 * @type {string: string}
19158 * the DragDrop object that is currently being dragged
19159 * @property dragCurrent
19167 * the DragDrop object(s) that are being hovered over
19168 * @property dragOvers
19176 * the X distance between the cursor and the object being dragged
19185 * the Y distance between the cursor and the object being dragged
19194 * Flag to determine if we should prevent the default behavior of the
19195 * events we define. By default this is true, but this can be set to
19196 * false if you need the default behavior (not recommended)
19197 * @property preventDefault
19201 preventDefault: true,
19204 * Flag to determine if we should stop the propagation of the events
19205 * we generate. This is true by default but you may want to set it to
19206 * false if the html element contains other features that require the
19208 * @property stopPropagation
19212 stopPropagation: true,
19215 * Internal flag that is set to true when drag and drop has been
19217 * @property initialized
19224 * All drag and drop can be disabled.
19232 * Called the first time an element is registered.
19238 this.initialized = true;
19242 * In point mode, drag and drop interaction is defined by the
19243 * location of the cursor during the drag/drop
19251 * In intersect mode, drag and drop interactio nis defined by the
19252 * overlap of two or more drag and drop objects.
19253 * @property INTERSECT
19260 * The current drag and drop mode. Default: POINT
19268 * Runs method on all drag and drop objects
19269 * @method _execOnAll
19273 _execOnAll: function(sMethod, args) {
19274 for (var i in this.ids) {
19275 for (var j in this.ids[i]) {
19276 var oDD = this.ids[i][j];
19277 if (! this.isTypeOfDD(oDD)) {
19280 oDD[sMethod].apply(oDD, args);
19286 * Drag and drop initialization. Sets up the global event handlers
19291 _onLoad: function() {
19295 if (!Roo.isTouch) {
19296 Event.on(document, "mouseup", this.handleMouseUp, this, true);
19297 Event.on(document, "mousemove", this.handleMouseMove, this, true);
19299 Event.on(document, "touchend", this.handleMouseUp, this, true);
19300 Event.on(document, "touchmove", this.handleMouseMove, this, true);
19302 Event.on(window, "unload", this._onUnload, this, true);
19303 Event.on(window, "resize", this._onResize, this, true);
19304 // Event.on(window, "mouseout", this._test);
19309 * Reset constraints on all drag and drop objs
19310 * @method _onResize
19314 _onResize: function(e) {
19315 this._execOnAll("resetConstraints", []);
19319 * Lock all drag and drop functionality
19323 lock: function() { this.locked = true; },
19326 * Unlock all drag and drop functionality
19330 unlock: function() { this.locked = false; },
19333 * Is drag and drop locked?
19335 * @return {boolean} True if drag and drop is locked, false otherwise.
19338 isLocked: function() { return this.locked; },
19341 * Location cache that is set for all drag drop objects when a drag is
19342 * initiated, cleared when the drag is finished.
19343 * @property locationCache
19350 * Set useCache to false if you want to force object the lookup of each
19351 * drag and drop linked element constantly during a drag.
19352 * @property useCache
19359 * The number of pixels that the mouse needs to move after the
19360 * mousedown before the drag is initiated. Default=3;
19361 * @property clickPixelThresh
19365 clickPixelThresh: 3,
19368 * The number of milliseconds after the mousedown event to initiate the
19369 * drag if we don't get a mouseup event. Default=1000
19370 * @property clickTimeThresh
19374 clickTimeThresh: 350,
19377 * Flag that indicates that either the drag pixel threshold or the
19378 * mousdown time threshold has been met
19379 * @property dragThreshMet
19384 dragThreshMet: false,
19387 * Timeout used for the click time threshold
19388 * @property clickTimeout
19393 clickTimeout: null,
19396 * The X position of the mousedown event stored for later use when a
19397 * drag threshold is met.
19406 * The Y position of the mousedown event stored for later use when a
19407 * drag threshold is met.
19416 * Each DragDrop instance must be registered with the DragDropMgr.
19417 * This is executed in DragDrop.init()
19418 * @method regDragDrop
19419 * @param {DragDrop} oDD the DragDrop object to register
19420 * @param {String} sGroup the name of the group this element belongs to
19423 regDragDrop: function(oDD, sGroup) {
19424 if (!this.initialized) { this.init(); }
19426 if (!this.ids[sGroup]) {
19427 this.ids[sGroup] = {};
19429 this.ids[sGroup][oDD.id] = oDD;
19433 * Removes the supplied dd instance from the supplied group. Executed
19434 * by DragDrop.removeFromGroup, so don't call this function directly.
19435 * @method removeDDFromGroup
19439 removeDDFromGroup: function(oDD, sGroup) {
19440 if (!this.ids[sGroup]) {
19441 this.ids[sGroup] = {};
19444 var obj = this.ids[sGroup];
19445 if (obj && obj[oDD.id]) {
19446 delete obj[oDD.id];
19451 * Unregisters a drag and drop item. This is executed in
19452 * DragDrop.unreg, use that method instead of calling this directly.
19457 _remove: function(oDD) {
19458 for (var g in oDD.groups) {
19459 if (g && this.ids[g][oDD.id]) {
19460 delete this.ids[g][oDD.id];
19463 delete this.handleIds[oDD.id];
19467 * Each DragDrop handle element must be registered. This is done
19468 * automatically when executing DragDrop.setHandleElId()
19469 * @method regHandle
19470 * @param {String} sDDId the DragDrop id this element is a handle for
19471 * @param {String} sHandleId the id of the element that is the drag
19475 regHandle: function(sDDId, sHandleId) {
19476 if (!this.handleIds[sDDId]) {
19477 this.handleIds[sDDId] = {};
19479 this.handleIds[sDDId][sHandleId] = sHandleId;
19483 * Utility function to determine if a given element has been
19484 * registered as a drag drop item.
19485 * @method isDragDrop
19486 * @param {String} id the element id to check
19487 * @return {boolean} true if this element is a DragDrop item,
19491 isDragDrop: function(id) {
19492 return ( this.getDDById(id) ) ? true : false;
19496 * Returns the drag and drop instances that are in all groups the
19497 * passed in instance belongs to.
19498 * @method getRelated
19499 * @param {DragDrop} p_oDD the obj to get related data for
19500 * @param {boolean} bTargetsOnly if true, only return targetable objs
19501 * @return {DragDrop[]} the related instances
19504 getRelated: function(p_oDD, bTargetsOnly) {
19506 for (var i in p_oDD.groups) {
19507 for (j in this.ids[i]) {
19508 var dd = this.ids[i][j];
19509 if (! this.isTypeOfDD(dd)) {
19512 if (!bTargetsOnly || dd.isTarget) {
19513 oDDs[oDDs.length] = dd;
19522 * Returns true if the specified dd target is a legal target for
19523 * the specifice drag obj
19524 * @method isLegalTarget
19525 * @param {DragDrop} the drag obj
19526 * @param {DragDrop} the target
19527 * @return {boolean} true if the target is a legal target for the
19531 isLegalTarget: function (oDD, oTargetDD) {
19532 var targets = this.getRelated(oDD, true);
19533 for (var i=0, len=targets.length;i<len;++i) {
19534 if (targets[i].id == oTargetDD.id) {
19543 * My goal is to be able to transparently determine if an object is
19544 * typeof DragDrop, and the exact subclass of DragDrop. typeof
19545 * returns "object", oDD.constructor.toString() always returns
19546 * "DragDrop" and not the name of the subclass. So for now it just
19547 * evaluates a well-known variable in DragDrop.
19548 * @method isTypeOfDD
19549 * @param {Object} the object to evaluate
19550 * @return {boolean} true if typeof oDD = DragDrop
19553 isTypeOfDD: function (oDD) {
19554 return (oDD && oDD.__ygDragDrop);
19558 * Utility function to determine if a given element has been
19559 * registered as a drag drop handle for the given Drag Drop object.
19561 * @param {String} id the element id to check
19562 * @return {boolean} true if this element is a DragDrop handle, false
19566 isHandle: function(sDDId, sHandleId) {
19567 return ( this.handleIds[sDDId] &&
19568 this.handleIds[sDDId][sHandleId] );
19572 * Returns the DragDrop instance for a given id
19573 * @method getDDById
19574 * @param {String} id the id of the DragDrop object
19575 * @return {DragDrop} the drag drop object, null if it is not found
19578 getDDById: function(id) {
19579 for (var i in this.ids) {
19580 if (this.ids[i][id]) {
19581 return this.ids[i][id];
19588 * Fired after a registered DragDrop object gets the mousedown event.
19589 * Sets up the events required to track the object being dragged
19590 * @method handleMouseDown
19591 * @param {Event} e the event
19592 * @param oDD the DragDrop object being dragged
19596 handleMouseDown: function(e, oDD) {
19598 Roo.QuickTips.disable();
19600 this.currentTarget = e.getTarget();
19602 this.dragCurrent = oDD;
19604 var el = oDD.getEl();
19606 // track start position
19607 this.startX = e.getPageX();
19608 this.startY = e.getPageY();
19610 this.deltaX = this.startX - el.offsetLeft;
19611 this.deltaY = this.startY - el.offsetTop;
19613 this.dragThreshMet = false;
19615 this.clickTimeout = setTimeout(
19617 var DDM = Roo.dd.DDM;
19618 DDM.startDrag(DDM.startX, DDM.startY);
19620 this.clickTimeThresh );
19624 * Fired when either the drag pixel threshol or the mousedown hold
19625 * time threshold has been met.
19626 * @method startDrag
19627 * @param x {int} the X position of the original mousedown
19628 * @param y {int} the Y position of the original mousedown
19631 startDrag: function(x, y) {
19632 clearTimeout(this.clickTimeout);
19633 if (this.dragCurrent) {
19634 this.dragCurrent.b4StartDrag(x, y);
19635 this.dragCurrent.startDrag(x, y);
19637 this.dragThreshMet = true;
19641 * Internal function to handle the mouseup event. Will be invoked
19642 * from the context of the document.
19643 * @method handleMouseUp
19644 * @param {Event} e the event
19648 handleMouseUp: function(e) {
19651 Roo.QuickTips.enable();
19653 if (! this.dragCurrent) {
19657 clearTimeout(this.clickTimeout);
19659 if (this.dragThreshMet) {
19660 this.fireEvents(e, true);
19670 * Utility to stop event propagation and event default, if these
19671 * features are turned on.
19672 * @method stopEvent
19673 * @param {Event} e the event as returned by this.getEvent()
19676 stopEvent: function(e){
19677 if(this.stopPropagation) {
19678 e.stopPropagation();
19681 if (this.preventDefault) {
19682 e.preventDefault();
19687 * Internal function to clean up event handlers after the drag
19688 * operation is complete
19690 * @param {Event} e the event
19694 stopDrag: function(e) {
19695 // Fire the drag end event for the item that was dragged
19696 if (this.dragCurrent) {
19697 if (this.dragThreshMet) {
19698 this.dragCurrent.b4EndDrag(e);
19699 this.dragCurrent.endDrag(e);
19702 this.dragCurrent.onMouseUp(e);
19705 this.dragCurrent = null;
19706 this.dragOvers = {};
19710 * Internal function to handle the mousemove event. Will be invoked
19711 * from the context of the html element.
19713 * @TODO figure out what we can do about mouse events lost when the
19714 * user drags objects beyond the window boundary. Currently we can
19715 * detect this in internet explorer by verifying that the mouse is
19716 * down during the mousemove event. Firefox doesn't give us the
19717 * button state on the mousemove event.
19718 * @method handleMouseMove
19719 * @param {Event} e the event
19723 handleMouseMove: function(e) {
19724 if (! this.dragCurrent) {
19728 // var button = e.which || e.button;
19730 // check for IE mouseup outside of page boundary
19731 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
19733 return this.handleMouseUp(e);
19736 if (!this.dragThreshMet) {
19737 var diffX = Math.abs(this.startX - e.getPageX());
19738 var diffY = Math.abs(this.startY - e.getPageY());
19739 if (diffX > this.clickPixelThresh ||
19740 diffY > this.clickPixelThresh) {
19741 this.startDrag(this.startX, this.startY);
19745 if (this.dragThreshMet) {
19746 this.dragCurrent.b4Drag(e);
19747 this.dragCurrent.onDrag(e);
19748 if(!this.dragCurrent.moveOnly){
19749 this.fireEvents(e, false);
19759 * Iterates over all of the DragDrop elements to find ones we are
19760 * hovering over or dropping on
19761 * @method fireEvents
19762 * @param {Event} e the event
19763 * @param {boolean} isDrop is this a drop op or a mouseover op?
19767 fireEvents: function(e, isDrop) {
19768 var dc = this.dragCurrent;
19770 // If the user did the mouse up outside of the window, we could
19771 // get here even though we have ended the drag.
19772 if (!dc || dc.isLocked()) {
19776 var pt = e.getPoint();
19778 // cache the previous dragOver array
19784 var enterEvts = [];
19786 // Check to see if the object(s) we were hovering over is no longer
19787 // being hovered over so we can fire the onDragOut event
19788 for (var i in this.dragOvers) {
19790 var ddo = this.dragOvers[i];
19792 if (! this.isTypeOfDD(ddo)) {
19796 if (! this.isOverTarget(pt, ddo, this.mode)) {
19797 outEvts.push( ddo );
19800 oldOvers[i] = true;
19801 delete this.dragOvers[i];
19804 for (var sGroup in dc.groups) {
19806 if ("string" != typeof sGroup) {
19810 for (i in this.ids[sGroup]) {
19811 var oDD = this.ids[sGroup][i];
19812 if (! this.isTypeOfDD(oDD)) {
19816 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
19817 if (this.isOverTarget(pt, oDD, this.mode)) {
19818 // look for drop interactions
19820 dropEvts.push( oDD );
19821 // look for drag enter and drag over interactions
19824 // initial drag over: dragEnter fires
19825 if (!oldOvers[oDD.id]) {
19826 enterEvts.push( oDD );
19827 // subsequent drag overs: dragOver fires
19829 overEvts.push( oDD );
19832 this.dragOvers[oDD.id] = oDD;
19840 if (outEvts.length) {
19841 dc.b4DragOut(e, outEvts);
19842 dc.onDragOut(e, outEvts);
19845 if (enterEvts.length) {
19846 dc.onDragEnter(e, enterEvts);
19849 if (overEvts.length) {
19850 dc.b4DragOver(e, overEvts);
19851 dc.onDragOver(e, overEvts);
19854 if (dropEvts.length) {
19855 dc.b4DragDrop(e, dropEvts);
19856 dc.onDragDrop(e, dropEvts);
19860 // fire dragout events
19862 for (i=0, len=outEvts.length; i<len; ++i) {
19863 dc.b4DragOut(e, outEvts[i].id);
19864 dc.onDragOut(e, outEvts[i].id);
19867 // fire enter events
19868 for (i=0,len=enterEvts.length; i<len; ++i) {
19869 // dc.b4DragEnter(e, oDD.id);
19870 dc.onDragEnter(e, enterEvts[i].id);
19873 // fire over events
19874 for (i=0,len=overEvts.length; i<len; ++i) {
19875 dc.b4DragOver(e, overEvts[i].id);
19876 dc.onDragOver(e, overEvts[i].id);
19879 // fire drop events
19880 for (i=0, len=dropEvts.length; i<len; ++i) {
19881 dc.b4DragDrop(e, dropEvts[i].id);
19882 dc.onDragDrop(e, dropEvts[i].id);
19887 // notify about a drop that did not find a target
19888 if (isDrop && !dropEvts.length) {
19889 dc.onInvalidDrop(e);
19895 * Helper function for getting the best match from the list of drag
19896 * and drop objects returned by the drag and drop events when we are
19897 * in INTERSECT mode. It returns either the first object that the
19898 * cursor is over, or the object that has the greatest overlap with
19899 * the dragged element.
19900 * @method getBestMatch
19901 * @param {DragDrop[]} dds The array of drag and drop objects
19903 * @return {DragDrop} The best single match
19906 getBestMatch: function(dds) {
19908 // Return null if the input is not what we expect
19909 //if (!dds || !dds.length || dds.length == 0) {
19911 // If there is only one item, it wins
19912 //} else if (dds.length == 1) {
19914 var len = dds.length;
19919 // Loop through the targeted items
19920 for (var i=0; i<len; ++i) {
19922 // If the cursor is over the object, it wins. If the
19923 // cursor is over multiple matches, the first one we come
19925 if (dd.cursorIsOver) {
19928 // Otherwise the object with the most overlap wins
19931 winner.overlap.getArea() < dd.overlap.getArea()) {
19942 * Refreshes the cache of the top-left and bottom-right points of the
19943 * drag and drop objects in the specified group(s). This is in the
19944 * format that is stored in the drag and drop instance, so typical
19947 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
19951 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
19953 * @TODO this really should be an indexed array. Alternatively this
19954 * method could accept both.
19955 * @method refreshCache
19956 * @param {Object} groups an associative array of groups to refresh
19959 refreshCache: function(groups) {
19960 for (var sGroup in groups) {
19961 if ("string" != typeof sGroup) {
19964 for (var i in this.ids[sGroup]) {
19965 var oDD = this.ids[sGroup][i];
19967 if (this.isTypeOfDD(oDD)) {
19968 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
19969 var loc = this.getLocation(oDD);
19971 this.locationCache[oDD.id] = loc;
19973 delete this.locationCache[oDD.id];
19974 // this will unregister the drag and drop object if
19975 // the element is not in a usable state
19984 * This checks to make sure an element exists and is in the DOM. The
19985 * main purpose is to handle cases where innerHTML is used to remove
19986 * drag and drop objects from the DOM. IE provides an 'unspecified
19987 * error' when trying to access the offsetParent of such an element
19989 * @param {HTMLElement} el the element to check
19990 * @return {boolean} true if the element looks usable
19993 verifyEl: function(el) {
19998 parent = el.offsetParent;
20001 parent = el.offsetParent;
20012 * Returns a Region object containing the drag and drop element's position
20013 * and size, including the padding configured for it
20014 * @method getLocation
20015 * @param {DragDrop} oDD the drag and drop object to get the
20017 * @return {Roo.lib.Region} a Region object representing the total area
20018 * the element occupies, including any padding
20019 * the instance is configured for.
20022 getLocation: function(oDD) {
20023 if (! this.isTypeOfDD(oDD)) {
20027 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
20030 pos= Roo.lib.Dom.getXY(el);
20038 x2 = x1 + el.offsetWidth;
20040 y2 = y1 + el.offsetHeight;
20042 t = y1 - oDD.padding[0];
20043 r = x2 + oDD.padding[1];
20044 b = y2 + oDD.padding[2];
20045 l = x1 - oDD.padding[3];
20047 return new Roo.lib.Region( t, r, b, l );
20051 * Checks the cursor location to see if it over the target
20052 * @method isOverTarget
20053 * @param {Roo.lib.Point} pt The point to evaluate
20054 * @param {DragDrop} oTarget the DragDrop object we are inspecting
20055 * @return {boolean} true if the mouse is over the target
20059 isOverTarget: function(pt, oTarget, intersect) {
20060 // use cache if available
20061 var loc = this.locationCache[oTarget.id];
20062 if (!loc || !this.useCache) {
20063 loc = this.getLocation(oTarget);
20064 this.locationCache[oTarget.id] = loc;
20072 oTarget.cursorIsOver = loc.contains( pt );
20074 // DragDrop is using this as a sanity check for the initial mousedown
20075 // in this case we are done. In POINT mode, if the drag obj has no
20076 // contraints, we are also done. Otherwise we need to evaluate the
20077 // location of the target as related to the actual location of the
20078 // dragged element.
20079 var dc = this.dragCurrent;
20080 if (!dc || !dc.getTargetCoord ||
20081 (!intersect && !dc.constrainX && !dc.constrainY)) {
20082 return oTarget.cursorIsOver;
20085 oTarget.overlap = null;
20087 // Get the current location of the drag element, this is the
20088 // location of the mouse event less the delta that represents
20089 // where the original mousedown happened on the element. We
20090 // need to consider constraints and ticks as well.
20091 var pos = dc.getTargetCoord(pt.x, pt.y);
20093 var el = dc.getDragEl();
20094 var curRegion = new Roo.lib.Region( pos.y,
20095 pos.x + el.offsetWidth,
20096 pos.y + el.offsetHeight,
20099 var overlap = curRegion.intersect(loc);
20102 oTarget.overlap = overlap;
20103 return (intersect) ? true : oTarget.cursorIsOver;
20110 * unload event handler
20111 * @method _onUnload
20115 _onUnload: function(e, me) {
20116 Roo.dd.DragDropMgr.unregAll();
20120 * Cleans up the drag and drop events and objects.
20125 unregAll: function() {
20127 if (this.dragCurrent) {
20129 this.dragCurrent = null;
20132 this._execOnAll("unreg", []);
20134 for (i in this.elementCache) {
20135 delete this.elementCache[i];
20138 this.elementCache = {};
20143 * A cache of DOM elements
20144 * @property elementCache
20151 * Get the wrapper for the DOM element specified
20152 * @method getElWrapper
20153 * @param {String} id the id of the element to get
20154 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
20156 * @deprecated This wrapper isn't that useful
20159 getElWrapper: function(id) {
20160 var oWrapper = this.elementCache[id];
20161 if (!oWrapper || !oWrapper.el) {
20162 oWrapper = this.elementCache[id] =
20163 new this.ElementWrapper(Roo.getDom(id));
20169 * Returns the actual DOM element
20170 * @method getElement
20171 * @param {String} id the id of the elment to get
20172 * @return {Object} The element
20173 * @deprecated use Roo.getDom instead
20176 getElement: function(id) {
20177 return Roo.getDom(id);
20181 * Returns the style property for the DOM element (i.e.,
20182 * document.getElById(id).style)
20184 * @param {String} id the id of the elment to get
20185 * @return {Object} The style property of the element
20186 * @deprecated use Roo.getDom instead
20189 getCss: function(id) {
20190 var el = Roo.getDom(id);
20191 return (el) ? el.style : null;
20195 * Inner class for cached elements
20196 * @class DragDropMgr.ElementWrapper
20201 ElementWrapper: function(el) {
20206 this.el = el || null;
20211 this.id = this.el && el.id;
20213 * A reference to the style property
20216 this.css = this.el && el.style;
20220 * Returns the X position of an html element
20222 * @param el the element for which to get the position
20223 * @return {int} the X coordinate
20225 * @deprecated use Roo.lib.Dom.getX instead
20228 getPosX: function(el) {
20229 return Roo.lib.Dom.getX(el);
20233 * Returns the Y position of an html element
20235 * @param el the element for which to get the position
20236 * @return {int} the Y coordinate
20237 * @deprecated use Roo.lib.Dom.getY instead
20240 getPosY: function(el) {
20241 return Roo.lib.Dom.getY(el);
20245 * Swap two nodes. In IE, we use the native method, for others we
20246 * emulate the IE behavior
20248 * @param n1 the first node to swap
20249 * @param n2 the other node to swap
20252 swapNode: function(n1, n2) {
20256 var p = n2.parentNode;
20257 var s = n2.nextSibling;
20260 p.insertBefore(n1, n2);
20261 } else if (n2 == n1.nextSibling) {
20262 p.insertBefore(n2, n1);
20264 n1.parentNode.replaceChild(n2, n1);
20265 p.insertBefore(n1, s);
20271 * Returns the current scroll position
20272 * @method getScroll
20276 getScroll: function () {
20277 var t, l, dde=document.documentElement, db=document.body;
20278 if (dde && (dde.scrollTop || dde.scrollLeft)) {
20280 l = dde.scrollLeft;
20287 return { top: t, left: l };
20291 * Returns the specified element style property
20293 * @param {HTMLElement} el the element
20294 * @param {string} styleProp the style property
20295 * @return {string} The value of the style property
20296 * @deprecated use Roo.lib.Dom.getStyle
20299 getStyle: function(el, styleProp) {
20300 return Roo.fly(el).getStyle(styleProp);
20304 * Gets the scrollTop
20305 * @method getScrollTop
20306 * @return {int} the document's scrollTop
20309 getScrollTop: function () { return this.getScroll().top; },
20312 * Gets the scrollLeft
20313 * @method getScrollLeft
20314 * @return {int} the document's scrollTop
20317 getScrollLeft: function () { return this.getScroll().left; },
20320 * Sets the x/y position of an element to the location of the
20323 * @param {HTMLElement} moveEl The element to move
20324 * @param {HTMLElement} targetEl The position reference element
20327 moveToEl: function (moveEl, targetEl) {
20328 var aCoord = Roo.lib.Dom.getXY(targetEl);
20329 Roo.lib.Dom.setXY(moveEl, aCoord);
20333 * Numeric array sort function
20334 * @method numericSort
20337 numericSort: function(a, b) { return (a - b); },
20341 * @property _timeoutCount
20348 * Trying to make the load order less important. Without this we get
20349 * an error if this file is loaded before the Event Utility.
20350 * @method _addListeners
20354 _addListeners: function() {
20355 var DDM = Roo.dd.DDM;
20356 if ( Roo.lib.Event && document ) {
20359 if (DDM._timeoutCount > 2000) {
20361 setTimeout(DDM._addListeners, 10);
20362 if (document && document.body) {
20363 DDM._timeoutCount += 1;
20370 * Recursively searches the immediate parent and all child nodes for
20371 * the handle element in order to determine wheter or not it was
20373 * @method handleWasClicked
20374 * @param node the html element to inspect
20377 handleWasClicked: function(node, id) {
20378 if (this.isHandle(id, node.id)) {
20381 // check to see if this is a text node child of the one we want
20382 var p = node.parentNode;
20385 if (this.isHandle(id, p.id)) {
20400 // shorter alias, save a few bytes
20401 Roo.dd.DDM = Roo.dd.DragDropMgr;
20402 Roo.dd.DDM._addListeners();
20406 * Ext JS Library 1.1.1
20407 * Copyright(c) 2006-2007, Ext JS, LLC.
20409 * Originally Released Under LGPL - original licence link has changed is not relivant.
20412 * <script type="text/javascript">
20417 * A DragDrop implementation where the linked element follows the
20418 * mouse cursor during a drag.
20419 * @extends Roo.dd.DragDrop
20421 * @param {String} id the id of the linked element
20422 * @param {String} sGroup the group of related DragDrop items
20423 * @param {object} config an object containing configurable attributes
20424 * Valid properties for DD:
20427 Roo.dd.DD = function(id, sGroup, config) {
20429 this.init(id, sGroup, config);
20433 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
20436 * When set to true, the utility automatically tries to scroll the browser
20437 * window wehn a drag and drop element is dragged near the viewport boundary.
20438 * Defaults to true.
20445 * Sets the pointer offset to the distance between the linked element's top
20446 * left corner and the location the element was clicked
20447 * @method autoOffset
20448 * @param {int} iPageX the X coordinate of the click
20449 * @param {int} iPageY the Y coordinate of the click
20451 autoOffset: function(iPageX, iPageY) {
20452 var x = iPageX - this.startPageX;
20453 var y = iPageY - this.startPageY;
20454 this.setDelta(x, y);
20458 * Sets the pointer offset. You can call this directly to force the
20459 * offset to be in a particular location (e.g., pass in 0,0 to set it
20460 * to the center of the object)
20462 * @param {int} iDeltaX the distance from the left
20463 * @param {int} iDeltaY the distance from the top
20465 setDelta: function(iDeltaX, iDeltaY) {
20466 this.deltaX = iDeltaX;
20467 this.deltaY = iDeltaY;
20471 * Sets the drag element to the location of the mousedown or click event,
20472 * maintaining the cursor location relative to the location on the element
20473 * that was clicked. Override this if you want to place the element in a
20474 * location other than where the cursor is.
20475 * @method setDragElPos
20476 * @param {int} iPageX the X coordinate of the mousedown or drag event
20477 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20479 setDragElPos: function(iPageX, iPageY) {
20480 // the first time we do this, we are going to check to make sure
20481 // the element has css positioning
20483 var el = this.getDragEl();
20484 this.alignElWithMouse(el, iPageX, iPageY);
20488 * Sets the element to the location of the mousedown or click event,
20489 * maintaining the cursor location relative to the location on the element
20490 * that was clicked. Override this if you want to place the element in a
20491 * location other than where the cursor is.
20492 * @method alignElWithMouse
20493 * @param {HTMLElement} el the element to move
20494 * @param {int} iPageX the X coordinate of the mousedown or drag event
20495 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20497 alignElWithMouse: function(el, iPageX, iPageY) {
20498 var oCoord = this.getTargetCoord(iPageX, iPageY);
20499 var fly = el.dom ? el : Roo.fly(el);
20500 if (!this.deltaSetXY) {
20501 var aCoord = [oCoord.x, oCoord.y];
20503 var newLeft = fly.getLeft(true);
20504 var newTop = fly.getTop(true);
20505 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
20507 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
20510 this.cachePosition(oCoord.x, oCoord.y);
20511 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
20516 * Saves the most recent position so that we can reset the constraints and
20517 * tick marks on-demand. We need to know this so that we can calculate the
20518 * number of pixels the element is offset from its original position.
20519 * @method cachePosition
20520 * @param iPageX the current x position (optional, this just makes it so we
20521 * don't have to look it up again)
20522 * @param iPageY the current y position (optional, this just makes it so we
20523 * don't have to look it up again)
20525 cachePosition: function(iPageX, iPageY) {
20527 this.lastPageX = iPageX;
20528 this.lastPageY = iPageY;
20530 var aCoord = Roo.lib.Dom.getXY(this.getEl());
20531 this.lastPageX = aCoord[0];
20532 this.lastPageY = aCoord[1];
20537 * Auto-scroll the window if the dragged object has been moved beyond the
20538 * visible window boundary.
20539 * @method autoScroll
20540 * @param {int} x the drag element's x position
20541 * @param {int} y the drag element's y position
20542 * @param {int} h the height of the drag element
20543 * @param {int} w the width of the drag element
20546 autoScroll: function(x, y, h, w) {
20549 // The client height
20550 var clientH = Roo.lib.Dom.getViewWidth();
20552 // The client width
20553 var clientW = Roo.lib.Dom.getViewHeight();
20555 // The amt scrolled down
20556 var st = this.DDM.getScrollTop();
20558 // The amt scrolled right
20559 var sl = this.DDM.getScrollLeft();
20561 // Location of the bottom of the element
20564 // Location of the right of the element
20567 // The distance from the cursor to the bottom of the visible area,
20568 // adjusted so that we don't scroll if the cursor is beyond the
20569 // element drag constraints
20570 var toBot = (clientH + st - y - this.deltaY);
20572 // The distance from the cursor to the right of the visible area
20573 var toRight = (clientW + sl - x - this.deltaX);
20576 // How close to the edge the cursor must be before we scroll
20577 // var thresh = (document.all) ? 100 : 40;
20580 // How many pixels to scroll per autoscroll op. This helps to reduce
20581 // clunky scrolling. IE is more sensitive about this ... it needs this
20582 // value to be higher.
20583 var scrAmt = (document.all) ? 80 : 30;
20585 // Scroll down if we are near the bottom of the visible page and the
20586 // obj extends below the crease
20587 if ( bot > clientH && toBot < thresh ) {
20588 window.scrollTo(sl, st + scrAmt);
20591 // Scroll up if the window is scrolled down and the top of the object
20592 // goes above the top border
20593 if ( y < st && st > 0 && y - st < thresh ) {
20594 window.scrollTo(sl, st - scrAmt);
20597 // Scroll right if the obj is beyond the right border and the cursor is
20598 // near the border.
20599 if ( right > clientW && toRight < thresh ) {
20600 window.scrollTo(sl + scrAmt, st);
20603 // Scroll left if the window has been scrolled to the right and the obj
20604 // extends past the left border
20605 if ( x < sl && sl > 0 && x - sl < thresh ) {
20606 window.scrollTo(sl - scrAmt, st);
20612 * Finds the location the element should be placed if we want to move
20613 * it to where the mouse location less the click offset would place us.
20614 * @method getTargetCoord
20615 * @param {int} iPageX the X coordinate of the click
20616 * @param {int} iPageY the Y coordinate of the click
20617 * @return an object that contains the coordinates (Object.x and Object.y)
20620 getTargetCoord: function(iPageX, iPageY) {
20623 var x = iPageX - this.deltaX;
20624 var y = iPageY - this.deltaY;
20626 if (this.constrainX) {
20627 if (x < this.minX) { x = this.minX; }
20628 if (x > this.maxX) { x = this.maxX; }
20631 if (this.constrainY) {
20632 if (y < this.minY) { y = this.minY; }
20633 if (y > this.maxY) { y = this.maxY; }
20636 x = this.getTick(x, this.xTicks);
20637 y = this.getTick(y, this.yTicks);
20644 * Sets up config options specific to this class. Overrides
20645 * Roo.dd.DragDrop, but all versions of this method through the
20646 * inheritance chain are called
20648 applyConfig: function() {
20649 Roo.dd.DD.superclass.applyConfig.call(this);
20650 this.scroll = (this.config.scroll !== false);
20654 * Event that fires prior to the onMouseDown event. Overrides
20657 b4MouseDown: function(e) {
20658 // this.resetConstraints();
20659 this.autoOffset(e.getPageX(),
20664 * Event that fires prior to the onDrag event. Overrides
20667 b4Drag: function(e) {
20668 this.setDragElPos(e.getPageX(),
20672 toString: function() {
20673 return ("DD " + this.id);
20676 //////////////////////////////////////////////////////////////////////////
20677 // Debugging ygDragDrop events that can be overridden
20678 //////////////////////////////////////////////////////////////////////////
20680 startDrag: function(x, y) {
20683 onDrag: function(e) {
20686 onDragEnter: function(e, id) {
20689 onDragOver: function(e, id) {
20692 onDragOut: function(e, id) {
20695 onDragDrop: function(e, id) {
20698 endDrag: function(e) {
20705 * Ext JS Library 1.1.1
20706 * Copyright(c) 2006-2007, Ext JS, LLC.
20708 * Originally Released Under LGPL - original licence link has changed is not relivant.
20711 * <script type="text/javascript">
20715 * @class Roo.dd.DDProxy
20716 * A DragDrop implementation that inserts an empty, bordered div into
20717 * the document that follows the cursor during drag operations. At the time of
20718 * the click, the frame div is resized to the dimensions of the linked html
20719 * element, and moved to the exact location of the linked element.
20721 * References to the "frame" element refer to the single proxy element that
20722 * was created to be dragged in place of all DDProxy elements on the
20725 * @extends Roo.dd.DD
20727 * @param {String} id the id of the linked html element
20728 * @param {String} sGroup the group of related DragDrop objects
20729 * @param {object} config an object containing configurable attributes
20730 * Valid properties for DDProxy in addition to those in DragDrop:
20731 * resizeFrame, centerFrame, dragElId
20733 Roo.dd.DDProxy = function(id, sGroup, config) {
20735 this.init(id, sGroup, config);
20741 * The default drag frame div id
20742 * @property Roo.dd.DDProxy.dragElId
20746 Roo.dd.DDProxy.dragElId = "ygddfdiv";
20748 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
20751 * By default we resize the drag frame to be the same size as the element
20752 * we want to drag (this is to get the frame effect). We can turn it off
20753 * if we want a different behavior.
20754 * @property resizeFrame
20760 * By default the frame is positioned exactly where the drag element is, so
20761 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
20762 * you do not have constraints on the obj is to have the drag frame centered
20763 * around the cursor. Set centerFrame to true for this effect.
20764 * @property centerFrame
20767 centerFrame: false,
20770 * Creates the proxy element if it does not yet exist
20771 * @method createFrame
20773 createFrame: function() {
20775 var body = document.body;
20777 if (!body || !body.firstChild) {
20778 setTimeout( function() { self.createFrame(); }, 50 );
20782 var div = this.getDragEl();
20785 div = document.createElement("div");
20786 div.id = this.dragElId;
20789 s.position = "absolute";
20790 s.visibility = "hidden";
20792 s.border = "2px solid #aaa";
20795 // appendChild can blow up IE if invoked prior to the window load event
20796 // while rendering a table. It is possible there are other scenarios
20797 // that would cause this to happen as well.
20798 body.insertBefore(div, body.firstChild);
20803 * Initialization for the drag frame element. Must be called in the
20804 * constructor of all subclasses
20805 * @method initFrame
20807 initFrame: function() {
20808 this.createFrame();
20811 applyConfig: function() {
20812 Roo.dd.DDProxy.superclass.applyConfig.call(this);
20814 this.resizeFrame = (this.config.resizeFrame !== false);
20815 this.centerFrame = (this.config.centerFrame);
20816 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
20820 * Resizes the drag frame to the dimensions of the clicked object, positions
20821 * it over the object, and finally displays it
20822 * @method showFrame
20823 * @param {int} iPageX X click position
20824 * @param {int} iPageY Y click position
20827 showFrame: function(iPageX, iPageY) {
20828 var el = this.getEl();
20829 var dragEl = this.getDragEl();
20830 var s = dragEl.style;
20832 this._resizeProxy();
20834 if (this.centerFrame) {
20835 this.setDelta( Math.round(parseInt(s.width, 10)/2),
20836 Math.round(parseInt(s.height, 10)/2) );
20839 this.setDragElPos(iPageX, iPageY);
20841 Roo.fly(dragEl).show();
20845 * The proxy is automatically resized to the dimensions of the linked
20846 * element when a drag is initiated, unless resizeFrame is set to false
20847 * @method _resizeProxy
20850 _resizeProxy: function() {
20851 if (this.resizeFrame) {
20852 var el = this.getEl();
20853 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
20857 // overrides Roo.dd.DragDrop
20858 b4MouseDown: function(e) {
20859 var x = e.getPageX();
20860 var y = e.getPageY();
20861 this.autoOffset(x, y);
20862 this.setDragElPos(x, y);
20865 // overrides Roo.dd.DragDrop
20866 b4StartDrag: function(x, y) {
20867 // show the drag frame
20868 this.showFrame(x, y);
20871 // overrides Roo.dd.DragDrop
20872 b4EndDrag: function(e) {
20873 Roo.fly(this.getDragEl()).hide();
20876 // overrides Roo.dd.DragDrop
20877 // By default we try to move the element to the last location of the frame.
20878 // This is so that the default behavior mirrors that of Roo.dd.DD.
20879 endDrag: function(e) {
20881 var lel = this.getEl();
20882 var del = this.getDragEl();
20884 // Show the drag frame briefly so we can get its position
20885 del.style.visibility = "";
20888 // Hide the linked element before the move to get around a Safari
20890 lel.style.visibility = "hidden";
20891 Roo.dd.DDM.moveToEl(lel, del);
20892 del.style.visibility = "hidden";
20893 lel.style.visibility = "";
20898 beforeMove : function(){
20902 afterDrag : function(){
20906 toString: function() {
20907 return ("DDProxy " + this.id);
20913 * Ext JS Library 1.1.1
20914 * Copyright(c) 2006-2007, Ext JS, LLC.
20916 * Originally Released Under LGPL - original licence link has changed is not relivant.
20919 * <script type="text/javascript">
20923 * @class Roo.dd.DDTarget
20924 * A DragDrop implementation that does not move, but can be a drop
20925 * target. You would get the same result by simply omitting implementation
20926 * for the event callbacks, but this way we reduce the processing cost of the
20927 * event listener and the callbacks.
20928 * @extends Roo.dd.DragDrop
20930 * @param {String} id the id of the element that is a drop target
20931 * @param {String} sGroup the group of related DragDrop objects
20932 * @param {object} config an object containing configurable attributes
20933 * Valid properties for DDTarget in addition to those in
20937 Roo.dd.DDTarget = function(id, sGroup, config) {
20939 this.initTarget(id, sGroup, config);
20941 if (config.listeners || config.events) {
20942 Roo.dd.DragDrop.superclass.constructor.call(this, {
20943 listeners : config.listeners || {},
20944 events : config.events || {}
20949 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
20950 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
20951 toString: function() {
20952 return ("DDTarget " + this.id);
20957 * Ext JS Library 1.1.1
20958 * Copyright(c) 2006-2007, Ext JS, LLC.
20960 * Originally Released Under LGPL - original licence link has changed is not relivant.
20963 * <script type="text/javascript">
20968 * @class Roo.dd.ScrollManager
20969 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
20970 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
20973 Roo.dd.ScrollManager = function(){
20974 var ddm = Roo.dd.DragDropMgr;
20981 var onStop = function(e){
20986 var triggerRefresh = function(){
20987 if(ddm.dragCurrent){
20988 ddm.refreshCache(ddm.dragCurrent.groups);
20992 var doScroll = function(){
20993 if(ddm.dragCurrent){
20994 var dds = Roo.dd.ScrollManager;
20996 if(proc.el.scroll(proc.dir, dds.increment)){
21000 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
21005 var clearProc = function(){
21007 clearInterval(proc.id);
21014 var startProc = function(el, dir){
21015 Roo.log('scroll startproc');
21019 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
21022 var onFire = function(e, isDrop){
21024 if(isDrop || !ddm.dragCurrent){ return; }
21025 var dds = Roo.dd.ScrollManager;
21026 if(!dragEl || dragEl != ddm.dragCurrent){
21027 dragEl = ddm.dragCurrent;
21028 // refresh regions on drag start
21029 dds.refreshCache();
21032 var xy = Roo.lib.Event.getXY(e);
21033 var pt = new Roo.lib.Point(xy[0], xy[1]);
21034 for(var id in els){
21035 var el = els[id], r = el._region;
21036 if(r && r.contains(pt) && el.isScrollable()){
21037 if(r.bottom - pt.y <= dds.thresh){
21039 startProc(el, "down");
21042 }else if(r.right - pt.x <= dds.thresh){
21044 startProc(el, "left");
21047 }else if(pt.y - r.top <= dds.thresh){
21049 startProc(el, "up");
21052 }else if(pt.x - r.left <= dds.thresh){
21054 startProc(el, "right");
21063 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
21064 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
21068 * Registers new overflow element(s) to auto scroll
21069 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
21071 register : function(el){
21072 if(el instanceof Array){
21073 for(var i = 0, len = el.length; i < len; i++) {
21074 this.register(el[i]);
21080 Roo.dd.ScrollManager.els = els;
21084 * Unregisters overflow element(s) so they are no longer scrolled
21085 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
21087 unregister : function(el){
21088 if(el instanceof Array){
21089 for(var i = 0, len = el.length; i < len; i++) {
21090 this.unregister(el[i]);
21099 * The number of pixels from the edge of a container the pointer needs to be to
21100 * trigger scrolling (defaults to 25)
21106 * The number of pixels to scroll in each scroll increment (defaults to 50)
21112 * The frequency of scrolls in milliseconds (defaults to 500)
21118 * True to animate the scroll (defaults to true)
21124 * The animation duration in seconds -
21125 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
21131 * Manually trigger a cache refresh.
21133 refreshCache : function(){
21134 for(var id in els){
21135 if(typeof els[id] == 'object'){ // for people extending the object prototype
21136 els[id]._region = els[id].getRegion();
21143 * Ext JS Library 1.1.1
21144 * Copyright(c) 2006-2007, Ext JS, LLC.
21146 * Originally Released Under LGPL - original licence link has changed is not relivant.
21149 * <script type="text/javascript">
21154 * @class Roo.dd.Registry
21155 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
21156 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
21159 Roo.dd.Registry = function(){
21162 var autoIdSeed = 0;
21164 var getId = function(el, autogen){
21165 if(typeof el == "string"){
21169 if(!id && autogen !== false){
21170 id = "roodd-" + (++autoIdSeed);
21178 * Register a drag drop element
21179 * @param {String|HTMLElement} element The id or DOM node to register
21180 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
21181 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
21182 * knows how to interpret, plus there are some specific properties known to the Registry that should be
21183 * populated in the data object (if applicable):
21185 Value Description<br />
21186 --------- ------------------------------------------<br />
21187 handles Array of DOM nodes that trigger dragging<br />
21188 for the element being registered<br />
21189 isHandle True if the element passed in triggers<br />
21190 dragging itself, else false
21193 register : function(el, data){
21195 if(typeof el == "string"){
21196 el = document.getElementById(el);
21199 elements[getId(el)] = data;
21200 if(data.isHandle !== false){
21201 handles[data.ddel.id] = data;
21204 var hs = data.handles;
21205 for(var i = 0, len = hs.length; i < len; i++){
21206 handles[getId(hs[i])] = data;
21212 * Unregister a drag drop element
21213 * @param {String|HTMLElement} element The id or DOM node to unregister
21215 unregister : function(el){
21216 var id = getId(el, false);
21217 var data = elements[id];
21219 delete elements[id];
21221 var hs = data.handles;
21222 for(var i = 0, len = hs.length; i < len; i++){
21223 delete handles[getId(hs[i], false)];
21230 * Returns the handle registered for a DOM Node by id
21231 * @param {String|HTMLElement} id The DOM node or id to look up
21232 * @return {Object} handle The custom handle data
21234 getHandle : function(id){
21235 if(typeof id != "string"){ // must be element?
21238 return handles[id];
21242 * Returns the handle that is registered for the DOM node that is the target of the event
21243 * @param {Event} e The event
21244 * @return {Object} handle The custom handle data
21246 getHandleFromEvent : function(e){
21247 var t = Roo.lib.Event.getTarget(e);
21248 return t ? handles[t.id] : null;
21252 * Returns a custom data object that is registered for a DOM node by id
21253 * @param {String|HTMLElement} id The DOM node or id to look up
21254 * @return {Object} data The custom data
21256 getTarget : function(id){
21257 if(typeof id != "string"){ // must be element?
21260 return elements[id];
21264 * Returns a custom data object that is registered for the DOM node that is the target of the event
21265 * @param {Event} e The event
21266 * @return {Object} data The custom data
21268 getTargetFromEvent : function(e){
21269 var t = Roo.lib.Event.getTarget(e);
21270 return t ? elements[t.id] || handles[t.id] : null;
21275 * Ext JS Library 1.1.1
21276 * Copyright(c) 2006-2007, Ext JS, LLC.
21278 * Originally Released Under LGPL - original licence link has changed is not relivant.
21281 * <script type="text/javascript">
21286 * @class Roo.dd.StatusProxy
21287 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
21288 * default drag proxy used by all Roo.dd components.
21290 * @param {Object} config
21292 Roo.dd.StatusProxy = function(config){
21293 Roo.apply(this, config);
21294 this.id = this.id || Roo.id();
21295 this.el = new Roo.Layer({
21297 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
21298 {tag: "div", cls: "x-dd-drop-icon"},
21299 {tag: "div", cls: "x-dd-drag-ghost"}
21302 shadow: !config || config.shadow !== false
21304 this.ghost = Roo.get(this.el.dom.childNodes[1]);
21305 this.dropStatus = this.dropNotAllowed;
21308 Roo.dd.StatusProxy.prototype = {
21310 * @cfg {String} dropAllowed
21311 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
21313 dropAllowed : "x-dd-drop-ok",
21315 * @cfg {String} dropNotAllowed
21316 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
21318 dropNotAllowed : "x-dd-drop-nodrop",
21321 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
21322 * over the current target element.
21323 * @param {String} cssClass The css class for the new drop status indicator image
21325 setStatus : function(cssClass){
21326 cssClass = cssClass || this.dropNotAllowed;
21327 if(this.dropStatus != cssClass){
21328 this.el.replaceClass(this.dropStatus, cssClass);
21329 this.dropStatus = cssClass;
21334 * Resets the status indicator to the default dropNotAllowed value
21335 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
21337 reset : function(clearGhost){
21338 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
21339 this.dropStatus = this.dropNotAllowed;
21341 this.ghost.update("");
21346 * Updates the contents of the ghost element
21347 * @param {String} html The html that will replace the current innerHTML of the ghost element
21349 update : function(html){
21350 if(typeof html == "string"){
21351 this.ghost.update(html);
21353 this.ghost.update("");
21354 html.style.margin = "0";
21355 this.ghost.dom.appendChild(html);
21357 // ensure float = none set?? cant remember why though.
21358 var el = this.ghost.dom.firstChild;
21360 Roo.fly(el).setStyle('float', 'none');
21365 * Returns the underlying proxy {@link Roo.Layer}
21366 * @return {Roo.Layer} el
21368 getEl : function(){
21373 * Returns the ghost element
21374 * @return {Roo.Element} el
21376 getGhost : function(){
21382 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
21384 hide : function(clear){
21392 * Stops the repair animation if it's currently running
21395 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
21401 * Displays this proxy
21408 * Force the Layer to sync its shadow and shim positions to the element
21415 * Causes the proxy to return to its position of origin via an animation. Should be called after an
21416 * invalid drop operation by the item being dragged.
21417 * @param {Array} xy The XY position of the element ([x, y])
21418 * @param {Function} callback The function to call after the repair is complete
21419 * @param {Object} scope The scope in which to execute the callback
21421 repair : function(xy, callback, scope){
21422 this.callback = callback;
21423 this.scope = scope;
21424 if(xy && this.animRepair !== false){
21425 this.el.addClass("x-dd-drag-repair");
21426 this.el.hideUnders(true);
21427 this.anim = this.el.shift({
21428 duration: this.repairDuration || .5,
21432 callback: this.afterRepair,
21436 this.afterRepair();
21441 afterRepair : function(){
21443 if(typeof this.callback == "function"){
21444 this.callback.call(this.scope || this);
21446 this.callback = null;
21451 * Ext JS Library 1.1.1
21452 * Copyright(c) 2006-2007, Ext JS, LLC.
21454 * Originally Released Under LGPL - original licence link has changed is not relivant.
21457 * <script type="text/javascript">
21461 * @class Roo.dd.DragSource
21462 * @extends Roo.dd.DDProxy
21463 * A simple class that provides the basic implementation needed to make any element draggable.
21465 * @param {String/HTMLElement/Element} el The container element
21466 * @param {Object} config
21468 Roo.dd.DragSource = function(el, config){
21469 this.el = Roo.get(el);
21470 this.dragData = {};
21472 Roo.apply(this, config);
21475 this.proxy = new Roo.dd.StatusProxy();
21478 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
21479 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
21481 this.dragging = false;
21484 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
21486 * @cfg {String} dropAllowed
21487 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21489 dropAllowed : "x-dd-drop-ok",
21491 * @cfg {String} dropNotAllowed
21492 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21494 dropNotAllowed : "x-dd-drop-nodrop",
21497 * Returns the data object associated with this drag source
21498 * @return {Object} data An object containing arbitrary data
21500 getDragData : function(e){
21501 return this.dragData;
21505 onDragEnter : function(e, id){
21506 var target = Roo.dd.DragDropMgr.getDDById(id);
21507 this.cachedTarget = target;
21508 if(this.beforeDragEnter(target, e, id) !== false){
21509 if(target.isNotifyTarget){
21510 var status = target.notifyEnter(this, e, this.dragData);
21511 this.proxy.setStatus(status);
21513 this.proxy.setStatus(this.dropAllowed);
21516 if(this.afterDragEnter){
21518 * An empty function by default, but provided so that you can perform a custom action
21519 * when the dragged item enters the drop target by providing an implementation.
21520 * @param {Roo.dd.DragDrop} target The drop target
21521 * @param {Event} e The event object
21522 * @param {String} id The id of the dragged element
21523 * @method afterDragEnter
21525 this.afterDragEnter(target, e, id);
21531 * An empty function by default, but provided so that you can perform a custom action
21532 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
21533 * @param {Roo.dd.DragDrop} target The drop target
21534 * @param {Event} e The event object
21535 * @param {String} id The id of the dragged element
21536 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21538 beforeDragEnter : function(target, e, id){
21543 alignElWithMouse: function() {
21544 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
21549 onDragOver : function(e, id){
21550 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21551 if(this.beforeDragOver(target, e, id) !== false){
21552 if(target.isNotifyTarget){
21553 var status = target.notifyOver(this, e, this.dragData);
21554 this.proxy.setStatus(status);
21557 if(this.afterDragOver){
21559 * An empty function by default, but provided so that you can perform a custom action
21560 * while the dragged item is over the drop target by providing an implementation.
21561 * @param {Roo.dd.DragDrop} target The drop target
21562 * @param {Event} e The event object
21563 * @param {String} id The id of the dragged element
21564 * @method afterDragOver
21566 this.afterDragOver(target, e, id);
21572 * An empty function by default, but provided so that you can perform a custom action
21573 * while the dragged item is over the drop target and optionally cancel the onDragOver.
21574 * @param {Roo.dd.DragDrop} target The drop target
21575 * @param {Event} e The event object
21576 * @param {String} id The id of the dragged element
21577 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21579 beforeDragOver : function(target, e, id){
21584 onDragOut : function(e, id){
21585 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21586 if(this.beforeDragOut(target, e, id) !== false){
21587 if(target.isNotifyTarget){
21588 target.notifyOut(this, e, this.dragData);
21590 this.proxy.reset();
21591 if(this.afterDragOut){
21593 * An empty function by default, but provided so that you can perform a custom action
21594 * after the dragged item is dragged out of the target without dropping.
21595 * @param {Roo.dd.DragDrop} target The drop target
21596 * @param {Event} e The event object
21597 * @param {String} id The id of the dragged element
21598 * @method afterDragOut
21600 this.afterDragOut(target, e, id);
21603 this.cachedTarget = null;
21607 * An empty function by default, but provided so that you can perform a custom action before the dragged
21608 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
21609 * @param {Roo.dd.DragDrop} target The drop target
21610 * @param {Event} e The event object
21611 * @param {String} id The id of the dragged element
21612 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21614 beforeDragOut : function(target, e, id){
21619 onDragDrop : function(e, id){
21620 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21621 if(this.beforeDragDrop(target, e, id) !== false){
21622 if(target.isNotifyTarget){
21623 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
21624 this.onValidDrop(target, e, id);
21626 this.onInvalidDrop(target, e, id);
21629 this.onValidDrop(target, e, id);
21632 if(this.afterDragDrop){
21634 * An empty function by default, but provided so that you can perform a custom action
21635 * after a valid drag drop has occurred by providing an implementation.
21636 * @param {Roo.dd.DragDrop} target The drop target
21637 * @param {Event} e The event object
21638 * @param {String} id The id of the dropped element
21639 * @method afterDragDrop
21641 this.afterDragDrop(target, e, id);
21644 delete this.cachedTarget;
21648 * An empty function by default, but provided so that you can perform a custom action before the dragged
21649 * item is dropped onto the target and optionally cancel the onDragDrop.
21650 * @param {Roo.dd.DragDrop} target The drop target
21651 * @param {Event} e The event object
21652 * @param {String} id The id of the dragged element
21653 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
21655 beforeDragDrop : function(target, e, id){
21660 onValidDrop : function(target, e, id){
21662 if(this.afterValidDrop){
21664 * An empty function by default, but provided so that you can perform a custom action
21665 * after a valid drop has occurred by providing an implementation.
21666 * @param {Object} target The target DD
21667 * @param {Event} e The event object
21668 * @param {String} id The id of the dropped element
21669 * @method afterInvalidDrop
21671 this.afterValidDrop(target, e, id);
21676 getRepairXY : function(e, data){
21677 return this.el.getXY();
21681 onInvalidDrop : function(target, e, id){
21682 this.beforeInvalidDrop(target, e, id);
21683 if(this.cachedTarget){
21684 if(this.cachedTarget.isNotifyTarget){
21685 this.cachedTarget.notifyOut(this, e, this.dragData);
21687 this.cacheTarget = null;
21689 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
21691 if(this.afterInvalidDrop){
21693 * An empty function by default, but provided so that you can perform a custom action
21694 * after an invalid drop has occurred by providing an implementation.
21695 * @param {Event} e The event object
21696 * @param {String} id The id of the dropped element
21697 * @method afterInvalidDrop
21699 this.afterInvalidDrop(e, id);
21704 afterRepair : function(){
21706 this.el.highlight(this.hlColor || "c3daf9");
21708 this.dragging = false;
21712 * An empty function by default, but provided so that you can perform a custom action after an invalid
21713 * drop has occurred.
21714 * @param {Roo.dd.DragDrop} target The drop target
21715 * @param {Event} e The event object
21716 * @param {String} id The id of the dragged element
21717 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
21719 beforeInvalidDrop : function(target, e, id){
21724 handleMouseDown : function(e){
21725 if(this.dragging) {
21728 var data = this.getDragData(e);
21729 if(data && this.onBeforeDrag(data, e) !== false){
21730 this.dragData = data;
21732 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
21737 * An empty function by default, but provided so that you can perform a custom action before the initial
21738 * drag event begins and optionally cancel it.
21739 * @param {Object} data An object containing arbitrary data to be shared with drop targets
21740 * @param {Event} e The event object
21741 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21743 onBeforeDrag : function(data, e){
21748 * An empty function by default, but provided so that you can perform a custom action once the initial
21749 * drag event has begun. The drag cannot be canceled from this function.
21750 * @param {Number} x The x position of the click on the dragged object
21751 * @param {Number} y The y position of the click on the dragged object
21753 onStartDrag : Roo.emptyFn,
21755 // private - YUI override
21756 startDrag : function(x, y){
21757 this.proxy.reset();
21758 this.dragging = true;
21759 this.proxy.update("");
21760 this.onInitDrag(x, y);
21765 onInitDrag : function(x, y){
21766 var clone = this.el.dom.cloneNode(true);
21767 clone.id = Roo.id(); // prevent duplicate ids
21768 this.proxy.update(clone);
21769 this.onStartDrag(x, y);
21774 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
21775 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
21777 getProxy : function(){
21782 * Hides the drag source's {@link Roo.dd.StatusProxy}
21784 hideProxy : function(){
21786 this.proxy.reset(true);
21787 this.dragging = false;
21791 triggerCacheRefresh : function(){
21792 Roo.dd.DDM.refreshCache(this.groups);
21795 // private - override to prevent hiding
21796 b4EndDrag: function(e) {
21799 // private - override to prevent moving
21800 endDrag : function(e){
21801 this.onEndDrag(this.dragData, e);
21805 onEndDrag : function(data, e){
21808 // private - pin to cursor
21809 autoOffset : function(x, y) {
21810 this.setDelta(-12, -20);
21814 * Ext JS Library 1.1.1
21815 * Copyright(c) 2006-2007, Ext JS, LLC.
21817 * Originally Released Under LGPL - original licence link has changed is not relivant.
21820 * <script type="text/javascript">
21825 * @class Roo.dd.DropTarget
21826 * @extends Roo.dd.DDTarget
21827 * A simple class that provides the basic implementation needed to make any element a drop target that can have
21828 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
21830 * @param {String/HTMLElement/Element} el The container element
21831 * @param {Object} config
21833 Roo.dd.DropTarget = function(el, config){
21834 this.el = Roo.get(el);
21836 var listeners = false; ;
21837 if (config && config.listeners) {
21838 listeners= config.listeners;
21839 delete config.listeners;
21841 Roo.apply(this, config);
21843 if(this.containerScroll){
21844 Roo.dd.ScrollManager.register(this.el);
21848 * @scope Roo.dd.DropTarget
21853 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
21854 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
21855 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
21857 * IMPORTANT : it should set this.overClass and this.dropAllowed
21859 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21860 * @param {Event} e The event
21861 * @param {Object} data An object containing arbitrary data supplied by the drag source
21867 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
21868 * This method will be called on every mouse movement while the drag source is over the drop target.
21869 * This default implementation simply returns the dropAllowed config value.
21871 * IMPORTANT : it should set this.dropAllowed
21873 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21874 * @param {Event} e The event
21875 * @param {Object} data An object containing arbitrary data supplied by the drag source
21881 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
21882 * out of the target without dropping. This default implementation simply removes the CSS class specified by
21883 * overClass (if any) from the drop element.
21885 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21886 * @param {Event} e The event
21887 * @param {Object} data An object containing arbitrary data supplied by the drag source
21893 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
21894 * been dropped on it. This method has no default implementation and returns false, so you must provide an
21895 * implementation that does something to process the drop event and returns true so that the drag source's
21896 * repair action does not run.
21898 * IMPORTANT : it should set this.success
21900 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21901 * @param {Event} e The event
21902 * @param {Object} data An object containing arbitrary data supplied by the drag source
21908 Roo.dd.DropTarget.superclass.constructor.call( this,
21910 this.ddGroup || this.group,
21913 listeners : listeners || {}
21921 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
21923 * @cfg {String} overClass
21924 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
21927 * @cfg {String} ddGroup
21928 * The drag drop group to handle drop events for
21932 * @cfg {String} dropAllowed
21933 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21935 dropAllowed : "x-dd-drop-ok",
21937 * @cfg {String} dropNotAllowed
21938 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21940 dropNotAllowed : "x-dd-drop-nodrop",
21942 * @cfg {boolean} success
21943 * set this after drop listener..
21947 * @cfg {boolean|String} valid true/false or string (ok-add/ok-sub/ok/nodrop)
21948 * if the drop point is valid for over/enter..
21955 isNotifyTarget : true,
21960 notifyEnter : function(dd, e, data)
21963 this.fireEvent('enter', dd, e, data);
21964 if(this.overClass){
21965 this.el.addClass(this.overClass);
21967 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
21968 this.valid ? this.dropAllowed : this.dropNotAllowed
21975 notifyOver : function(dd, e, data)
21978 this.fireEvent('over', dd, e, data);
21979 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
21980 this.valid ? this.dropAllowed : this.dropNotAllowed
21987 notifyOut : function(dd, e, data)
21989 this.fireEvent('out', dd, e, data);
21990 if(this.overClass){
21991 this.el.removeClass(this.overClass);
21998 notifyDrop : function(dd, e, data)
22000 this.success = false;
22001 this.fireEvent('drop', dd, e, data);
22002 return this.success;
22006 * Ext JS Library 1.1.1
22007 * Copyright(c) 2006-2007, Ext JS, LLC.
22009 * Originally Released Under LGPL - original licence link has changed is not relivant.
22012 * <script type="text/javascript">
22017 * @class Roo.dd.DragZone
22018 * @extends Roo.dd.DragSource
22019 * This class provides a container DD instance that proxies for multiple child node sources.<br />
22020 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
22022 * @param {String/HTMLElement/Element} el The container element
22023 * @param {Object} config
22025 Roo.dd.DragZone = function(el, config){
22026 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
22027 if(this.containerScroll){
22028 Roo.dd.ScrollManager.register(this.el);
22032 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
22034 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
22035 * for auto scrolling during drag operations.
22038 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
22039 * method after a failed drop (defaults to "c3daf9" - light blue)
22043 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
22044 * for a valid target to drag based on the mouse down. Override this method
22045 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
22046 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
22047 * @param {EventObject} e The mouse down event
22048 * @return {Object} The dragData
22050 getDragData : function(e){
22051 return Roo.dd.Registry.getHandleFromEvent(e);
22055 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
22056 * this.dragData.ddel
22057 * @param {Number} x The x position of the click on the dragged object
22058 * @param {Number} y The y position of the click on the dragged object
22059 * @return {Boolean} true to continue the drag, false to cancel
22061 onInitDrag : function(x, y){
22062 this.proxy.update(this.dragData.ddel.cloneNode(true));
22063 this.onStartDrag(x, y);
22068 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
22070 afterRepair : function(){
22072 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
22074 this.dragging = false;
22078 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
22079 * the XY of this.dragData.ddel
22080 * @param {EventObject} e The mouse up event
22081 * @return {Array} The xy location (e.g. [100, 200])
22083 getRepairXY : function(e){
22084 return Roo.Element.fly(this.dragData.ddel).getXY();
22088 * Ext JS Library 1.1.1
22089 * Copyright(c) 2006-2007, Ext JS, LLC.
22091 * Originally Released Under LGPL - original licence link has changed is not relivant.
22094 * <script type="text/javascript">
22097 * @class Roo.dd.DropZone
22098 * @extends Roo.dd.DropTarget
22099 * This class provides a container DD instance that proxies for multiple child node targets.<br />
22100 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
22102 * @param {String/HTMLElement/Element} el The container element
22103 * @param {Object} config
22105 Roo.dd.DropZone = function(el, config){
22106 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
22109 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
22111 * Returns a custom data object associated with the DOM node that is the target of the event. By default
22112 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
22113 * provide your own custom lookup.
22114 * @param {Event} e The event
22115 * @return {Object} data The custom data
22117 getTargetFromEvent : function(e){
22118 return Roo.dd.Registry.getTargetFromEvent(e);
22122 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
22123 * that it has registered. This method has no default implementation and should be overridden to provide
22124 * node-specific processing if necessary.
22125 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22126 * {@link #getTargetFromEvent} for this node)
22127 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22128 * @param {Event} e The event
22129 * @param {Object} data An object containing arbitrary data supplied by the drag source
22131 onNodeEnter : function(n, dd, e, data){
22136 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
22137 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
22138 * overridden to provide the proper feedback.
22139 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22140 * {@link #getTargetFromEvent} for this node)
22141 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22142 * @param {Event} e The event
22143 * @param {Object} data An object containing arbitrary data supplied by the drag source
22144 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22145 * underlying {@link Roo.dd.StatusProxy} can be updated
22147 onNodeOver : function(n, dd, e, data){
22148 return this.dropAllowed;
22152 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
22153 * the drop node without dropping. This method has no default implementation and should be overridden to provide
22154 * node-specific processing if necessary.
22155 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22156 * {@link #getTargetFromEvent} for this node)
22157 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22158 * @param {Event} e The event
22159 * @param {Object} data An object containing arbitrary data supplied by the drag source
22161 onNodeOut : function(n, dd, e, data){
22166 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
22167 * the drop node. The default implementation returns false, so it should be overridden to provide the
22168 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
22169 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22170 * {@link #getTargetFromEvent} for this node)
22171 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22172 * @param {Event} e The event
22173 * @param {Object} data An object containing arbitrary data supplied by the drag source
22174 * @return {Boolean} True if the drop was valid, else false
22176 onNodeDrop : function(n, dd, e, data){
22181 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
22182 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
22183 * it should be overridden to provide the proper feedback if necessary.
22184 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22185 * @param {Event} e The event
22186 * @param {Object} data An object containing arbitrary data supplied by the drag source
22187 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22188 * underlying {@link Roo.dd.StatusProxy} can be updated
22190 onContainerOver : function(dd, e, data){
22191 return this.dropNotAllowed;
22195 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
22196 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
22197 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
22198 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
22199 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22200 * @param {Event} e The event
22201 * @param {Object} data An object containing arbitrary data supplied by the drag source
22202 * @return {Boolean} True if the drop was valid, else false
22204 onContainerDrop : function(dd, e, data){
22209 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
22210 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
22211 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
22212 * you should override this method and provide a custom implementation.
22213 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22214 * @param {Event} e The event
22215 * @param {Object} data An object containing arbitrary data supplied by the drag source
22216 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22217 * underlying {@link Roo.dd.StatusProxy} can be updated
22219 notifyEnter : function(dd, e, data){
22220 return this.dropNotAllowed;
22224 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
22225 * This method will be called on every mouse movement while the drag source is over the drop zone.
22226 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
22227 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
22228 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
22229 * registered node, it will call {@link #onContainerOver}.
22230 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22231 * @param {Event} e The event
22232 * @param {Object} data An object containing arbitrary data supplied by the drag source
22233 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22234 * underlying {@link Roo.dd.StatusProxy} can be updated
22236 notifyOver : function(dd, e, data){
22237 var n = this.getTargetFromEvent(e);
22238 if(!n){ // not over valid drop target
22239 if(this.lastOverNode){
22240 this.onNodeOut(this.lastOverNode, dd, e, data);
22241 this.lastOverNode = null;
22243 return this.onContainerOver(dd, e, data);
22245 if(this.lastOverNode != n){
22246 if(this.lastOverNode){
22247 this.onNodeOut(this.lastOverNode, dd, e, data);
22249 this.onNodeEnter(n, dd, e, data);
22250 this.lastOverNode = n;
22252 return this.onNodeOver(n, dd, e, data);
22256 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
22257 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
22258 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
22259 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
22260 * @param {Event} e The event
22261 * @param {Object} data An object containing arbitrary data supplied by the drag zone
22263 notifyOut : function(dd, e, data){
22264 if(this.lastOverNode){
22265 this.onNodeOut(this.lastOverNode, dd, e, data);
22266 this.lastOverNode = null;
22271 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
22272 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
22273 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
22274 * otherwise it will call {@link #onContainerDrop}.
22275 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22276 * @param {Event} e The event
22277 * @param {Object} data An object containing arbitrary data supplied by the drag source
22278 * @return {Boolean} True if the drop was valid, else false
22280 notifyDrop : function(dd, e, data){
22281 if(this.lastOverNode){
22282 this.onNodeOut(this.lastOverNode, dd, e, data);
22283 this.lastOverNode = null;
22285 var n = this.getTargetFromEvent(e);
22287 this.onNodeDrop(n, dd, e, data) :
22288 this.onContainerDrop(dd, e, data);
22292 triggerCacheRefresh : function(){
22293 Roo.dd.DDM.refreshCache(this.groups);