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 */
6777 setEvent : function(e){
6778 if(e == this || (e && e.browserEvent)){ // already wrapped
6781 this.browserEvent = e;
6783 // normalize buttons
6784 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6785 if(e.type == 'click' && this.button == -1){
6789 this.shiftKey = e.shiftKey;
6790 // mac metaKey behaves like ctrlKey
6791 this.ctrlKey = e.ctrlKey || e.metaKey;
6792 this.altKey = e.altKey;
6793 // in getKey these will be normalized for the mac
6794 this.keyCode = e.keyCode;
6795 // keyup warnings on firefox.
6796 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6797 // cache the target for the delayed and or buffered events
6798 this.target = E.getTarget(e);
6800 this.xy = E.getXY(e);
6803 this.shiftKey = false;
6804 this.ctrlKey = false;
6805 this.altKey = false;
6815 * Stop the event (preventDefault and stopPropagation)
6817 stopEvent : function(){
6818 if(this.browserEvent){
6819 if(this.browserEvent.type == 'mousedown'){
6820 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6822 E.stopEvent(this.browserEvent);
6827 * Prevents the browsers default handling of the event.
6829 preventDefault : function(){
6830 if(this.browserEvent){
6831 E.preventDefault(this.browserEvent);
6836 isNavKeyPress : function(){
6837 var k = this.keyCode;
6838 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6839 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6842 isSpecialKey : function(){
6843 var k = this.keyCode;
6844 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6845 (k == 16) || (k == 17) ||
6846 (k >= 18 && k <= 20) ||
6847 (k >= 33 && k <= 35) ||
6848 (k >= 36 && k <= 39) ||
6849 (k >= 44 && k <= 45);
6852 * Cancels bubbling of the event.
6854 stopPropagation : function(){
6855 if(this.browserEvent){
6856 if(this.type == 'mousedown'){
6857 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6859 E.stopPropagation(this.browserEvent);
6864 * Gets the key code for the event.
6867 getCharCode : function(){
6868 return this.charCode || this.keyCode;
6872 * Returns a normalized keyCode for the event.
6873 * @return {Number} The key code
6875 getKey : function(){
6876 var k = this.keyCode || this.charCode;
6877 return Roo.isSafari ? (safariKeys[k] || k) : k;
6881 * Gets the x coordinate of the event.
6884 getPageX : function(){
6889 * Gets the y coordinate of the event.
6892 getPageY : function(){
6897 * Gets the time of the event.
6900 getTime : function(){
6901 if(this.browserEvent){
6902 return E.getTime(this.browserEvent);
6908 * Gets the page coordinates of the event.
6909 * @return {Array} The xy values like [x, y]
6916 * Gets the target for the event.
6917 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6918 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6919 search as a number or element (defaults to 10 || document.body)
6920 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6921 * @return {HTMLelement}
6923 getTarget : function(selector, maxDepth, returnEl){
6924 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6927 * Gets the related target.
6928 * @return {HTMLElement}
6930 getRelatedTarget : function(){
6931 if(this.browserEvent){
6932 return E.getRelatedTarget(this.browserEvent);
6938 * Normalizes mouse wheel delta across browsers
6939 * @return {Number} The delta
6941 getWheelDelta : function(){
6942 var e = this.browserEvent;
6944 if(e.wheelDelta){ /* IE/Opera. */
6945 delta = e.wheelDelta/120;
6946 }else if(e.detail){ /* Mozilla case. */
6947 delta = -e.detail/3;
6953 * Returns true if the control, meta, shift or alt key was pressed during this event.
6956 hasModifier : function(){
6957 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6961 * Returns true if the target of this event equals el or is a child of el
6962 * @param {String/HTMLElement/Element} el
6963 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6966 within : function(el, related){
6967 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6968 return t && Roo.fly(el).contains(t);
6971 getPoint : function(){
6972 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6976 return new Roo.EventObjectImpl();
6981 * Ext JS Library 1.1.1
6982 * Copyright(c) 2006-2007, Ext JS, LLC.
6984 * Originally Released Under LGPL - original licence link has changed is not relivant.
6987 * <script type="text/javascript">
6991 // was in Composite Element!??!?!
6994 var D = Roo.lib.Dom;
6995 var E = Roo.lib.Event;
6996 var A = Roo.lib.Anim;
6998 // local style camelizing for speed
7000 var camelRe = /(-[a-z])/gi;
7001 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
7002 var view = document.defaultView;
7005 * @class Roo.Element
7006 * Represents an Element in the DOM.<br><br>
7009 var el = Roo.get("my-div");
7012 var el = getEl("my-div");
7014 // or with a DOM element
7015 var el = Roo.get(myDivElement);
7017 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
7018 * each call instead of constructing a new one.<br><br>
7019 * <b>Animations</b><br />
7020 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
7021 * should either be a boolean (true) or an object literal with animation options. The animation options are:
7023 Option Default Description
7024 --------- -------- ---------------------------------------------
7025 duration .35 The duration of the animation in seconds
7026 easing easeOut The YUI easing method
7027 callback none A function to execute when the anim completes
7028 scope this The scope (this) of the callback function
7030 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
7031 * manipulate the animation. Here's an example:
7033 var el = Roo.get("my-div");
7038 // default animation
7039 el.setWidth(100, true);
7041 // animation with some options set
7048 // using the "anim" property to get the Anim object
7054 el.setWidth(100, opt);
7056 if(opt.anim.isAnimated()){
7060 * <b> Composite (Collections of) Elements</b><br />
7061 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
7062 * @constructor Create a new Element directly.
7063 * @param {String/HTMLElement} element
7064 * @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).
7066 Roo.Element = function(element, forceNew){
7067 var dom = typeof element == "string" ?
7068 document.getElementById(element) : element;
7069 if(!dom){ // invalid id/element
7073 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7074 return Roo.Element.cache[id];
7084 * The DOM element ID
7087 this.id = id || Roo.id(dom);
7090 var El = Roo.Element;
7094 * The element's default display mode (defaults to "")
7097 originalDisplay : "",
7101 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7107 * Sets the element's visibility mode. When setVisible() is called it
7108 * will use this to determine whether to set the visibility or the display property.
7109 * @param visMode Element.VISIBILITY or Element.DISPLAY
7110 * @return {Roo.Element} this
7112 setVisibilityMode : function(visMode){
7113 this.visibilityMode = visMode;
7117 * Convenience method for setVisibilityMode(Element.DISPLAY)
7118 * @param {String} display (optional) What to set display to when visible
7119 * @return {Roo.Element} this
7121 enableDisplayMode : function(display){
7122 this.setVisibilityMode(El.DISPLAY);
7123 if(typeof display != "undefined") { this.originalDisplay = display; }
7128 * 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)
7129 * @param {String} selector The simple selector to test
7130 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7131 search as a number or element (defaults to 10 || document.body)
7132 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7133 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7135 findParent : function(simpleSelector, maxDepth, returnEl){
7136 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7137 maxDepth = maxDepth || 50;
7138 if(typeof maxDepth != "number"){
7139 stopEl = Roo.getDom(maxDepth);
7142 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7143 if(dq.is(p, simpleSelector)){
7144 return returnEl ? Roo.get(p) : p;
7154 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7155 * @param {String} selector The simple selector to test
7156 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7157 search as a number or element (defaults to 10 || document.body)
7158 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7159 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7161 findParentNode : function(simpleSelector, maxDepth, returnEl){
7162 var p = Roo.fly(this.dom.parentNode, '_internal');
7163 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7167 * Looks at the scrollable parent element
7169 findScrollableParent : function(){
7171 var overflowRegex = /(auto|scroll)/;
7173 if(this.getStyle('position') === 'fixed'){
7174 return Roo.get(document.body);
7177 var excludeStaticParent = this.getStyle('position') === "absolute";
7179 for (var parent = this; (parent = Roo.get(parent.dom.parentNode));){
7181 if (excludeStaticParent && parent.getStyle('position') === "static") {
7186 parent.dom.nodeName.toLowerCase() == 'body' ||
7187 overflowRegex.test(parent.getStyle('overflow') + parent.getStyle('overflow-x') + parent.getStyle('overflow-y'))
7193 return Roo.get(document.body);
7197 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7198 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7199 * @param {String} selector The simple selector to test
7200 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7201 search as a number or element (defaults to 10 || document.body)
7202 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7204 up : function(simpleSelector, maxDepth){
7205 return this.findParentNode(simpleSelector, maxDepth, true);
7211 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7212 * @param {String} selector The simple selector to test
7213 * @return {Boolean} True if this element matches the selector, else false
7215 is : function(simpleSelector){
7216 return Roo.DomQuery.is(this.dom, simpleSelector);
7220 * Perform animation on this element.
7221 * @param {Object} args The YUI animation control args
7222 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7223 * @param {Function} onComplete (optional) Function to call when animation completes
7224 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7225 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7226 * @return {Roo.Element} this
7228 animate : function(args, duration, onComplete, easing, animType){
7229 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7234 * @private Internal animation call
7236 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7237 animType = animType || 'run';
7239 var anim = Roo.lib.Anim[animType](
7241 (opt.duration || defaultDur) || .35,
7242 (opt.easing || defaultEase) || 'easeOut',
7244 Roo.callback(cb, this);
7245 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7253 // private legacy anim prep
7254 preanim : function(a, i){
7255 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7259 * Removes worthless text nodes
7260 * @param {Boolean} forceReclean (optional) By default the element
7261 * keeps track if it has been cleaned already so
7262 * you can call this over and over. However, if you update the element and
7263 * need to force a reclean, you can pass true.
7265 clean : function(forceReclean){
7266 if(this.isCleaned && forceReclean !== true){
7270 var d = this.dom, n = d.firstChild, ni = -1;
7272 var nx = n.nextSibling;
7273 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7280 this.isCleaned = true;
7285 calcOffsetsTo : function(el){
7288 var restorePos = false;
7289 if(el.getStyle('position') == 'static'){
7290 el.position('relative');
7295 while(op && op != d && op.tagName != 'HTML'){
7298 op = op.offsetParent;
7301 el.position('static');
7307 * Scrolls this element into view within the passed container.
7308 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7309 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7310 * @return {Roo.Element} this
7312 scrollIntoView : function(container, hscroll){
7313 var c = Roo.getDom(container) || document.body;
7316 var o = this.calcOffsetsTo(c),
7319 b = t+el.offsetHeight,
7320 r = l+el.offsetWidth;
7322 var ch = c.clientHeight;
7323 var ct = parseInt(c.scrollTop, 10);
7324 var cl = parseInt(c.scrollLeft, 10);
7326 var cr = cl + c.clientWidth;
7334 if(hscroll !== false){
7338 c.scrollLeft = r-c.clientWidth;
7345 scrollChildIntoView : function(child, hscroll){
7346 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7350 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7351 * the new height may not be available immediately.
7352 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7353 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7354 * @param {Function} onComplete (optional) Function to call when animation completes
7355 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7356 * @return {Roo.Element} this
7358 autoHeight : function(animate, duration, onComplete, easing){
7359 var oldHeight = this.getHeight();
7361 this.setHeight(1); // force clipping
7362 setTimeout(function(){
7363 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7365 this.setHeight(height);
7367 if(typeof onComplete == "function"){
7371 this.setHeight(oldHeight); // restore original height
7372 this.setHeight(height, animate, duration, function(){
7374 if(typeof onComplete == "function") { onComplete(); }
7375 }.createDelegate(this), easing);
7377 }.createDelegate(this), 0);
7382 * Returns true if this element is an ancestor of the passed element
7383 * @param {HTMLElement/String} el The element to check
7384 * @return {Boolean} True if this element is an ancestor of el, else false
7386 contains : function(el){
7387 if(!el){return false;}
7388 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7392 * Checks whether the element is currently visible using both visibility and display properties.
7393 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7394 * @return {Boolean} True if the element is currently visible, else false
7396 isVisible : function(deep) {
7397 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7398 if(deep !== true || !vis){
7401 var p = this.dom.parentNode;
7402 while(p && p.tagName.toLowerCase() != "body"){
7403 if(!Roo.fly(p, '_isVisible').isVisible()){
7412 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7413 * @param {String} selector The CSS selector
7414 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7415 * @return {CompositeElement/CompositeElementLite} The composite element
7417 select : function(selector, unique){
7418 return El.select(selector, unique, this.dom);
7422 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7423 * @param {String} selector The CSS selector
7424 * @return {Array} An array of the matched nodes
7426 query : function(selector, unique){
7427 return Roo.DomQuery.select(selector, this.dom);
7431 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7432 * @param {String} selector The CSS selector
7433 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7434 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7436 child : function(selector, returnDom){
7437 var n = Roo.DomQuery.selectNode(selector, this.dom);
7438 return returnDom ? n : Roo.get(n);
7442 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7443 * @param {String} selector The CSS selector
7444 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7445 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7447 down : function(selector, returnDom){
7448 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7449 return returnDom ? n : Roo.get(n);
7453 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7454 * @param {String} group The group the DD object is member of
7455 * @param {Object} config The DD config object
7456 * @param {Object} overrides An object containing methods to override/implement on the DD object
7457 * @return {Roo.dd.DD} The DD object
7459 initDD : function(group, config, overrides){
7460 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7461 return Roo.apply(dd, overrides);
7465 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7466 * @param {String} group The group the DDProxy object is member of
7467 * @param {Object} config The DDProxy config object
7468 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7469 * @return {Roo.dd.DDProxy} The DDProxy object
7471 initDDProxy : function(group, config, overrides){
7472 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7473 return Roo.apply(dd, overrides);
7477 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7478 * @param {String} group The group the DDTarget object is member of
7479 * @param {Object} config The DDTarget config object
7480 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7481 * @return {Roo.dd.DDTarget} The DDTarget object
7483 initDDTarget : function(group, config, overrides){
7484 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7485 return Roo.apply(dd, overrides);
7489 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7490 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7491 * @param {Boolean} visible Whether the element is visible
7492 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7493 * @return {Roo.Element} this
7495 setVisible : function(visible, animate){
7497 if(this.visibilityMode == El.DISPLAY){
7498 this.setDisplayed(visible);
7501 this.dom.style.visibility = visible ? "visible" : "hidden";
7504 // closure for composites
7506 var visMode = this.visibilityMode;
7508 this.setOpacity(.01);
7509 this.setVisible(true);
7511 this.anim({opacity: { to: (visible?1:0) }},
7512 this.preanim(arguments, 1),
7513 null, .35, 'easeIn', function(){
7515 if(visMode == El.DISPLAY){
7516 dom.style.display = "none";
7518 dom.style.visibility = "hidden";
7520 Roo.get(dom).setOpacity(1);
7528 * Returns true if display is not "none"
7531 isDisplayed : function() {
7532 return this.getStyle("display") != "none";
7536 * Toggles the element's visibility or display, depending on visibility mode.
7537 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7538 * @return {Roo.Element} this
7540 toggle : function(animate){
7541 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7546 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7547 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7548 * @return {Roo.Element} this
7550 setDisplayed : function(value) {
7551 if(typeof value == "boolean"){
7552 value = value ? this.originalDisplay : "none";
7554 this.setStyle("display", value);
7559 * Tries to focus the element. Any exceptions are caught and ignored.
7560 * @return {Roo.Element} this
7562 focus : function() {
7570 * Tries to blur the element. Any exceptions are caught and ignored.
7571 * @return {Roo.Element} this
7581 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7582 * @param {String/Array} className The CSS class to add, or an array of classes
7583 * @return {Roo.Element} this
7585 addClass : function(className){
7586 if(className instanceof Array){
7587 for(var i = 0, len = className.length; i < len; i++) {
7588 this.addClass(className[i]);
7591 if(className && !this.hasClass(className)){
7592 this.dom.className = this.dom.className + " " + className;
7599 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7600 * @param {String/Array} className The CSS class to add, or an array of classes
7601 * @return {Roo.Element} this
7603 radioClass : function(className){
7604 var siblings = this.dom.parentNode.childNodes;
7605 for(var i = 0; i < siblings.length; i++) {
7606 var s = siblings[i];
7607 if(s.nodeType == 1){
7608 Roo.get(s).removeClass(className);
7611 this.addClass(className);
7616 * Removes one or more CSS classes from the element.
7617 * @param {String/Array} className The CSS class to remove, or an array of classes
7618 * @return {Roo.Element} this
7620 removeClass : function(className){
7621 if(!className || !this.dom.className){
7624 if(className instanceof Array){
7625 for(var i = 0, len = className.length; i < len; i++) {
7626 this.removeClass(className[i]);
7629 if(this.hasClass(className)){
7630 var re = this.classReCache[className];
7632 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7633 this.classReCache[className] = re;
7635 this.dom.className =
7636 this.dom.className.replace(re, " ");
7646 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7647 * @param {String} className The CSS class to toggle
7648 * @return {Roo.Element} this
7650 toggleClass : function(className){
7651 if(this.hasClass(className)){
7652 this.removeClass(className);
7654 this.addClass(className);
7660 * Checks if the specified CSS class exists on this element's DOM node.
7661 * @param {String} className The CSS class to check for
7662 * @return {Boolean} True if the class exists, else false
7664 hasClass : function(className){
7665 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7669 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7670 * @param {String} oldClassName The CSS class to replace
7671 * @param {String} newClassName The replacement CSS class
7672 * @return {Roo.Element} this
7674 replaceClass : function(oldClassName, newClassName){
7675 this.removeClass(oldClassName);
7676 this.addClass(newClassName);
7681 * Returns an object with properties matching the styles requested.
7682 * For example, el.getStyles('color', 'font-size', 'width') might return
7683 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7684 * @param {String} style1 A style name
7685 * @param {String} style2 A style name
7686 * @param {String} etc.
7687 * @return {Object} The style object
7689 getStyles : function(){
7690 var a = arguments, len = a.length, r = {};
7691 for(var i = 0; i < len; i++){
7692 r[a[i]] = this.getStyle(a[i]);
7698 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7699 * @param {String} property The style property whose value is returned.
7700 * @return {String} The current value of the style property for this element.
7702 getStyle : function(){
7703 return view && view.getComputedStyle ?
7705 var el = this.dom, v, cs, camel;
7706 if(prop == 'float'){
7709 if(el.style && (v = el.style[prop])){
7712 if(cs = view.getComputedStyle(el, "")){
7713 if(!(camel = propCache[prop])){
7714 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7721 var el = this.dom, v, cs, camel;
7722 if(prop == 'opacity'){
7723 if(typeof el.style.filter == 'string'){
7724 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7726 var fv = parseFloat(m[1]);
7728 return fv ? fv / 100 : 0;
7733 }else if(prop == 'float'){
7734 prop = "styleFloat";
7736 if(!(camel = propCache[prop])){
7737 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7739 if(v = el.style[camel]){
7742 if(cs = el.currentStyle){
7750 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7751 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7752 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7753 * @return {Roo.Element} this
7755 setStyle : function(prop, value){
7756 if(typeof prop == "string"){
7758 if (prop == 'float') {
7759 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7764 if(!(camel = propCache[prop])){
7765 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7768 if(camel == 'opacity') {
7769 this.setOpacity(value);
7771 this.dom.style[camel] = value;
7774 for(var style in prop){
7775 if(typeof prop[style] != "function"){
7776 this.setStyle(style, prop[style]);
7784 * More flexible version of {@link #setStyle} for setting style properties.
7785 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7786 * a function which returns such a specification.
7787 * @return {Roo.Element} this
7789 applyStyles : function(style){
7790 Roo.DomHelper.applyStyles(this.dom, style);
7795 * 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).
7796 * @return {Number} The X position of the element
7799 return D.getX(this.dom);
7803 * 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).
7804 * @return {Number} The Y position of the element
7807 return D.getY(this.dom);
7811 * 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).
7812 * @return {Array} The XY position of the element
7815 return D.getXY(this.dom);
7819 * 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).
7820 * @param {Number} The X position of the element
7821 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7822 * @return {Roo.Element} this
7824 setX : function(x, animate){
7826 D.setX(this.dom, x);
7828 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7834 * 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).
7835 * @param {Number} The Y position of the element
7836 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7837 * @return {Roo.Element} this
7839 setY : function(y, animate){
7841 D.setY(this.dom, y);
7843 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7849 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7850 * @param {String} left The left CSS property value
7851 * @return {Roo.Element} this
7853 setLeft : function(left){
7854 this.setStyle("left", this.addUnits(left));
7859 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7860 * @param {String} top The top CSS property value
7861 * @return {Roo.Element} this
7863 setTop : function(top){
7864 this.setStyle("top", this.addUnits(top));
7869 * Sets the element's CSS right style.
7870 * @param {String} right The right CSS property value
7871 * @return {Roo.Element} this
7873 setRight : function(right){
7874 this.setStyle("right", this.addUnits(right));
7879 * Sets the element's CSS bottom style.
7880 * @param {String} bottom The bottom CSS property value
7881 * @return {Roo.Element} this
7883 setBottom : function(bottom){
7884 this.setStyle("bottom", this.addUnits(bottom));
7889 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7890 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7891 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7892 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7893 * @return {Roo.Element} this
7895 setXY : function(pos, animate){
7897 D.setXY(this.dom, pos);
7899 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7905 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7906 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7907 * @param {Number} x X value for new position (coordinates are page-based)
7908 * @param {Number} y Y value for new position (coordinates are page-based)
7909 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7910 * @return {Roo.Element} this
7912 setLocation : function(x, y, animate){
7913 this.setXY([x, y], this.preanim(arguments, 2));
7918 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7919 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7920 * @param {Number} x X value for new position (coordinates are page-based)
7921 * @param {Number} y Y value for new position (coordinates are page-based)
7922 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7923 * @return {Roo.Element} this
7925 moveTo : function(x, y, animate){
7926 this.setXY([x, y], this.preanim(arguments, 2));
7931 * Returns the region of the given element.
7932 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7933 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7935 getRegion : function(){
7936 return D.getRegion(this.dom);
7940 * Returns the offset height of the element
7941 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7942 * @return {Number} The element's height
7944 getHeight : function(contentHeight){
7945 var h = this.dom.offsetHeight || 0;
7946 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7950 * Returns the offset width of the element
7951 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7952 * @return {Number} The element's width
7954 getWidth : function(contentWidth){
7955 var w = this.dom.offsetWidth || 0;
7956 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7960 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7961 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7962 * if a height has not been set using CSS.
7965 getComputedHeight : function(){
7966 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7968 h = parseInt(this.getStyle('height'), 10) || 0;
7969 if(!this.isBorderBox()){
7970 h += this.getFrameWidth('tb');
7977 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7978 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7979 * if a width has not been set using CSS.
7982 getComputedWidth : function(){
7983 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7985 w = parseInt(this.getStyle('width'), 10) || 0;
7986 if(!this.isBorderBox()){
7987 w += this.getFrameWidth('lr');
7994 * Returns the size of the element.
7995 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7996 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7998 getSize : function(contentSize){
7999 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
8003 * Returns the width and height of the viewport.
8004 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
8006 getViewSize : function(){
8007 var d = this.dom, doc = document, aw = 0, ah = 0;
8008 if(d == doc || d == doc.body){
8009 return {width : D.getViewWidth(), height: D.getViewHeight()};
8012 width : d.clientWidth,
8013 height: d.clientHeight
8019 * Returns the value of the "value" attribute
8020 * @param {Boolean} asNumber true to parse the value as a number
8021 * @return {String/Number}
8023 getValue : function(asNumber){
8024 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
8028 adjustWidth : function(width){
8029 if(typeof width == "number"){
8030 if(this.autoBoxAdjust && !this.isBorderBox()){
8031 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8041 adjustHeight : function(height){
8042 if(typeof height == "number"){
8043 if(this.autoBoxAdjust && !this.isBorderBox()){
8044 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8054 * Set the width of the element
8055 * @param {Number} width The new width
8056 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8057 * @return {Roo.Element} this
8059 setWidth : function(width, animate){
8060 width = this.adjustWidth(width);
8062 this.dom.style.width = this.addUnits(width);
8064 this.anim({width: {to: width}}, this.preanim(arguments, 1));
8070 * Set the height of the element
8071 * @param {Number} height The new height
8072 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8073 * @return {Roo.Element} this
8075 setHeight : function(height, animate){
8076 height = this.adjustHeight(height);
8078 this.dom.style.height = this.addUnits(height);
8080 this.anim({height: {to: height}}, this.preanim(arguments, 1));
8086 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
8087 * @param {Number} width The new width
8088 * @param {Number} height The new height
8089 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8090 * @return {Roo.Element} this
8092 setSize : function(width, height, animate){
8093 if(typeof width == "object"){ // in case of object from getSize()
8094 height = width.height; width = width.width;
8096 width = this.adjustWidth(width); height = this.adjustHeight(height);
8098 this.dom.style.width = this.addUnits(width);
8099 this.dom.style.height = this.addUnits(height);
8101 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8107 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8108 * @param {Number} x X value for new position (coordinates are page-based)
8109 * @param {Number} y Y value for new position (coordinates are page-based)
8110 * @param {Number} width The new width
8111 * @param {Number} height The new height
8112 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8113 * @return {Roo.Element} this
8115 setBounds : function(x, y, width, height, animate){
8117 this.setSize(width, height);
8118 this.setLocation(x, y);
8120 width = this.adjustWidth(width); height = this.adjustHeight(height);
8121 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8122 this.preanim(arguments, 4), 'motion');
8128 * 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.
8129 * @param {Roo.lib.Region} region The region to fill
8130 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8131 * @return {Roo.Element} this
8133 setRegion : function(region, animate){
8134 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8139 * Appends an event handler
8141 * @param {String} eventName The type of event to append
8142 * @param {Function} fn The method the event invokes
8143 * @param {Object} scope (optional) The scope (this object) of the fn
8144 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8146 addListener : function(eventName, fn, scope, options){
8148 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8153 * Removes an event handler from this element
8154 * @param {String} eventName the type of event to remove
8155 * @param {Function} fn the method the event invokes
8156 * @return {Roo.Element} this
8158 removeListener : function(eventName, fn){
8159 Roo.EventManager.removeListener(this.dom, eventName, fn);
8164 * Removes all previous added listeners from this element
8165 * @return {Roo.Element} this
8167 removeAllListeners : function(){
8168 E.purgeElement(this.dom);
8172 relayEvent : function(eventName, observable){
8173 this.on(eventName, function(e){
8174 observable.fireEvent(eventName, e);
8179 * Set the opacity of the element
8180 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8181 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8182 * @return {Roo.Element} this
8184 setOpacity : function(opacity, animate){
8186 var s = this.dom.style;
8189 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8190 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8192 s.opacity = opacity;
8195 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8201 * Gets the left X coordinate
8202 * @param {Boolean} local True to get the local css position instead of page coordinate
8205 getLeft : function(local){
8209 return parseInt(this.getStyle("left"), 10) || 0;
8214 * Gets the right X coordinate of the element (element X position + element width)
8215 * @param {Boolean} local True to get the local css position instead of page coordinate
8218 getRight : function(local){
8220 return this.getX() + this.getWidth();
8222 return (this.getLeft(true) + this.getWidth()) || 0;
8227 * Gets the top Y coordinate
8228 * @param {Boolean} local True to get the local css position instead of page coordinate
8231 getTop : function(local) {
8235 return parseInt(this.getStyle("top"), 10) || 0;
8240 * Gets the bottom Y coordinate of the element (element Y position + element height)
8241 * @param {Boolean} local True to get the local css position instead of page coordinate
8244 getBottom : function(local){
8246 return this.getY() + this.getHeight();
8248 return (this.getTop(true) + this.getHeight()) || 0;
8253 * Initializes positioning on this element. If a desired position is not passed, it will make the
8254 * the element positioned relative IF it is not already positioned.
8255 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8256 * @param {Number} zIndex (optional) The zIndex to apply
8257 * @param {Number} x (optional) Set the page X position
8258 * @param {Number} y (optional) Set the page Y position
8260 position : function(pos, zIndex, x, y){
8262 if(this.getStyle('position') == 'static'){
8263 this.setStyle('position', 'relative');
8266 this.setStyle("position", pos);
8269 this.setStyle("z-index", zIndex);
8271 if(x !== undefined && y !== undefined){
8273 }else if(x !== undefined){
8275 }else if(y !== undefined){
8281 * Clear positioning back to the default when the document was loaded
8282 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8283 * @return {Roo.Element} this
8285 clearPositioning : function(value){
8293 "position" : "static"
8299 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8300 * snapshot before performing an update and then restoring the element.
8303 getPositioning : function(){
8304 var l = this.getStyle("left");
8305 var t = this.getStyle("top");
8307 "position" : this.getStyle("position"),
8309 "right" : l ? "" : this.getStyle("right"),
8311 "bottom" : t ? "" : this.getStyle("bottom"),
8312 "z-index" : this.getStyle("z-index")
8317 * Gets the width of the border(s) for the specified side(s)
8318 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8319 * passing lr would get the border (l)eft width + the border (r)ight width.
8320 * @return {Number} The width of the sides passed added together
8322 getBorderWidth : function(side){
8323 return this.addStyles(side, El.borders);
8327 * Gets the width of the padding(s) for the specified side(s)
8328 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8329 * passing lr would get the padding (l)eft + the padding (r)ight.
8330 * @return {Number} The padding of the sides passed added together
8332 getPadding : function(side){
8333 return this.addStyles(side, El.paddings);
8337 * Set positioning with an object returned by getPositioning().
8338 * @param {Object} posCfg
8339 * @return {Roo.Element} this
8341 setPositioning : function(pc){
8342 this.applyStyles(pc);
8343 if(pc.right == "auto"){
8344 this.dom.style.right = "";
8346 if(pc.bottom == "auto"){
8347 this.dom.style.bottom = "";
8353 fixDisplay : function(){
8354 if(this.getStyle("display") == "none"){
8355 this.setStyle("visibility", "hidden");
8356 this.setStyle("display", this.originalDisplay); // first try reverting to default
8357 if(this.getStyle("display") == "none"){ // if that fails, default to block
8358 this.setStyle("display", "block");
8364 * Quick set left and top adding default units
8365 * @param {String} left The left CSS property value
8366 * @param {String} top The top CSS property value
8367 * @return {Roo.Element} this
8369 setLeftTop : function(left, top){
8370 this.dom.style.left = this.addUnits(left);
8371 this.dom.style.top = this.addUnits(top);
8376 * Move this element relative to its current position.
8377 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8378 * @param {Number} distance How far to move the element in pixels
8379 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8380 * @return {Roo.Element} this
8382 move : function(direction, distance, animate){
8383 var xy = this.getXY();
8384 direction = direction.toLowerCase();
8388 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8392 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8397 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8402 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8409 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8410 * @return {Roo.Element} this
8413 if(!this.isClipped){
8414 this.isClipped = true;
8415 this.originalClip = {
8416 "o": this.getStyle("overflow"),
8417 "x": this.getStyle("overflow-x"),
8418 "y": this.getStyle("overflow-y")
8420 this.setStyle("overflow", "hidden");
8421 this.setStyle("overflow-x", "hidden");
8422 this.setStyle("overflow-y", "hidden");
8428 * Return clipping (overflow) to original clipping before clip() was called
8429 * @return {Roo.Element} this
8431 unclip : function(){
8433 this.isClipped = false;
8434 var o = this.originalClip;
8435 if(o.o){this.setStyle("overflow", o.o);}
8436 if(o.x){this.setStyle("overflow-x", o.x);}
8437 if(o.y){this.setStyle("overflow-y", o.y);}
8444 * Gets the x,y coordinates specified by the anchor position on the element.
8445 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8446 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8447 * {width: (target width), height: (target height)} (defaults to the element's current size)
8448 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8449 * @return {Array} [x, y] An array containing the element's x and y coordinates
8451 getAnchorXY : function(anchor, local, s){
8452 //Passing a different size is useful for pre-calculating anchors,
8453 //especially for anchored animations that change the el size.
8455 var w, h, vp = false;
8458 if(d == document.body || d == document){
8460 w = D.getViewWidth(); h = D.getViewHeight();
8462 w = this.getWidth(); h = this.getHeight();
8465 w = s.width; h = s.height;
8467 var x = 0, y = 0, r = Math.round;
8468 switch((anchor || "tl").toLowerCase()){
8510 var sc = this.getScroll();
8511 return [x + sc.left, y + sc.top];
8513 //Add the element's offset xy
8514 var o = this.getXY();
8515 return [x+o[0], y+o[1]];
8519 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8520 * supported position values.
8521 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8522 * @param {String} position The position to align to.
8523 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8524 * @return {Array} [x, y]
8526 getAlignToXY : function(el, p, o){
8530 throw "Element.alignTo with an element that doesn't exist";
8532 var c = false; //constrain to viewport
8533 var p1 = "", p2 = "";
8540 }else if(p.indexOf("-") == -1){
8543 p = p.toLowerCase();
8544 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8546 throw "Element.alignTo with an invalid alignment " + p;
8548 p1 = m[1]; p2 = m[2]; c = !!m[3];
8550 //Subtract the aligned el's internal xy from the target's offset xy
8551 //plus custom offset to get the aligned el's new offset xy
8552 var a1 = this.getAnchorXY(p1, true);
8553 var a2 = el.getAnchorXY(p2, false);
8554 var x = a2[0] - a1[0] + o[0];
8555 var y = a2[1] - a1[1] + o[1];
8557 //constrain the aligned el to viewport if necessary
8558 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8559 // 5px of margin for ie
8560 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8562 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8563 //perpendicular to the vp border, allow the aligned el to slide on that border,
8564 //otherwise swap the aligned el to the opposite border of the target.
8565 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8566 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8567 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8568 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8571 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8572 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8574 if((x+w) > dw + scrollX){
8575 x = swapX ? r.left-w : dw+scrollX-w;
8578 x = swapX ? r.right : scrollX;
8580 if((y+h) > dh + scrollY){
8581 y = swapY ? r.top-h : dh+scrollY-h;
8584 y = swapY ? r.bottom : scrollY;
8591 getConstrainToXY : function(){
8592 var os = {top:0, left:0, bottom:0, right: 0};
8594 return function(el, local, offsets, proposedXY){
8596 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8598 var vw, vh, vx = 0, vy = 0;
8599 if(el.dom == document.body || el.dom == document){
8600 vw = Roo.lib.Dom.getViewWidth();
8601 vh = Roo.lib.Dom.getViewHeight();
8603 vw = el.dom.clientWidth;
8604 vh = el.dom.clientHeight;
8606 var vxy = el.getXY();
8612 var s = el.getScroll();
8614 vx += offsets.left + s.left;
8615 vy += offsets.top + s.top;
8617 vw -= offsets.right;
8618 vh -= offsets.bottom;
8623 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8624 var x = xy[0], y = xy[1];
8625 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8627 // only move it if it needs it
8630 // first validate right/bottom
8639 // then make sure top/left isn't negative
8648 return moved ? [x, y] : false;
8653 adjustForConstraints : function(xy, parent, offsets){
8654 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8658 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8659 * document it aligns it to the viewport.
8660 * The position parameter is optional, and can be specified in any one of the following formats:
8662 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8663 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8664 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8665 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8666 * <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
8667 * element's anchor point, and the second value is used as the target's anchor point.</li>
8669 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8670 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8671 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8672 * that specified in order to enforce the viewport constraints.
8673 * Following are all of the supported anchor positions:
8676 ----- -----------------------------
8677 tl The top left corner (default)
8678 t The center of the top edge
8679 tr The top right corner
8680 l The center of the left edge
8681 c In the center of the element
8682 r The center of the right edge
8683 bl The bottom left corner
8684 b The center of the bottom edge
8685 br The bottom right corner
8689 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8690 el.alignTo("other-el");
8692 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8693 el.alignTo("other-el", "tr?");
8695 // align the bottom right corner of el with the center left edge of other-el
8696 el.alignTo("other-el", "br-l?");
8698 // align the center of el with the bottom left corner of other-el and
8699 // adjust the x position by -6 pixels (and the y position by 0)
8700 el.alignTo("other-el", "c-bl", [-6, 0]);
8702 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8703 * @param {String} position The position to align to.
8704 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8705 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8706 * @return {Roo.Element} this
8708 alignTo : function(element, position, offsets, animate){
8709 var xy = this.getAlignToXY(element, position, offsets);
8710 this.setXY(xy, this.preanim(arguments, 3));
8715 * Anchors an element to another element and realigns it when the window is resized.
8716 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8717 * @param {String} position The position to align to.
8718 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8719 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8720 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8721 * is a number, it is used as the buffer delay (defaults to 50ms).
8722 * @param {Function} callback The function to call after the animation finishes
8723 * @return {Roo.Element} this
8725 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8726 var action = function(){
8727 this.alignTo(el, alignment, offsets, animate);
8728 Roo.callback(callback, this);
8730 Roo.EventManager.onWindowResize(action, this);
8731 var tm = typeof monitorScroll;
8732 if(tm != 'undefined'){
8733 Roo.EventManager.on(window, 'scroll', action, this,
8734 {buffer: tm == 'number' ? monitorScroll : 50});
8736 action.call(this); // align immediately
8740 * Clears any opacity settings from this element. Required in some cases for IE.
8741 * @return {Roo.Element} this
8743 clearOpacity : function(){
8744 if (window.ActiveXObject) {
8745 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8746 this.dom.style.filter = "";
8749 this.dom.style.opacity = "";
8750 this.dom.style["-moz-opacity"] = "";
8751 this.dom.style["-khtml-opacity"] = "";
8757 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8758 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8759 * @return {Roo.Element} this
8761 hide : function(animate){
8762 this.setVisible(false, this.preanim(arguments, 0));
8767 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8768 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8769 * @return {Roo.Element} this
8771 show : function(animate){
8772 this.setVisible(true, this.preanim(arguments, 0));
8777 * @private Test if size has a unit, otherwise appends the default
8779 addUnits : function(size){
8780 return Roo.Element.addUnits(size, this.defaultUnit);
8784 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8785 * @return {Roo.Element} this
8787 beginMeasure : function(){
8789 if(el.offsetWidth || el.offsetHeight){
8790 return this; // offsets work already
8793 var p = this.dom, b = document.body; // start with this element
8794 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8795 var pe = Roo.get(p);
8796 if(pe.getStyle('display') == 'none'){
8797 changed.push({el: p, visibility: pe.getStyle("visibility")});
8798 p.style.visibility = "hidden";
8799 p.style.display = "block";
8803 this._measureChanged = changed;
8809 * Restores displays to before beginMeasure was called
8810 * @return {Roo.Element} this
8812 endMeasure : function(){
8813 var changed = this._measureChanged;
8815 for(var i = 0, len = changed.length; i < len; i++) {
8817 r.el.style.visibility = r.visibility;
8818 r.el.style.display = "none";
8820 this._measureChanged = null;
8826 * Update the innerHTML of this element, optionally searching for and processing scripts
8827 * @param {String} html The new HTML
8828 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8829 * @param {Function} callback For async script loading you can be noticed when the update completes
8830 * @return {Roo.Element} this
8832 update : function(html, loadScripts, callback){
8833 if(typeof html == "undefined"){
8836 if(loadScripts !== true){
8837 this.dom.innerHTML = html;
8838 if(typeof callback == "function"){
8846 html += '<span id="' + id + '"></span>';
8848 E.onAvailable(id, function(){
8849 var hd = document.getElementsByTagName("head")[0];
8850 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8851 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8852 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8855 while(match = re.exec(html)){
8856 var attrs = match[1];
8857 var srcMatch = attrs ? attrs.match(srcRe) : false;
8858 if(srcMatch && srcMatch[2]){
8859 var s = document.createElement("script");
8860 s.src = srcMatch[2];
8861 var typeMatch = attrs.match(typeRe);
8862 if(typeMatch && typeMatch[2]){
8863 s.type = typeMatch[2];
8866 }else if(match[2] && match[2].length > 0){
8867 if(window.execScript) {
8868 window.execScript(match[2]);
8876 window.eval(match[2]);
8880 var el = document.getElementById(id);
8881 if(el){el.parentNode.removeChild(el);}
8882 if(typeof callback == "function"){
8886 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8891 * Direct access to the UpdateManager update() method (takes the same parameters).
8892 * @param {String/Function} url The url for this request or a function to call to get the url
8893 * @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}
8894 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8895 * @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.
8896 * @return {Roo.Element} this
8899 var um = this.getUpdateManager();
8900 um.update.apply(um, arguments);
8905 * Gets this element's UpdateManager
8906 * @return {Roo.UpdateManager} The UpdateManager
8908 getUpdateManager : function(){
8909 if(!this.updateManager){
8910 this.updateManager = new Roo.UpdateManager(this);
8912 return this.updateManager;
8916 * Disables text selection for this element (normalized across browsers)
8917 * @return {Roo.Element} this
8919 unselectable : function(){
8920 this.dom.unselectable = "on";
8921 this.swallowEvent("selectstart", true);
8922 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8923 this.addClass("x-unselectable");
8928 * Calculates the x, y to center this element on the screen
8929 * @return {Array} The x, y values [x, y]
8931 getCenterXY : function(){
8932 return this.getAlignToXY(document, 'c-c');
8936 * Centers the Element in either the viewport, or another Element.
8937 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8939 center : function(centerIn){
8940 this.alignTo(centerIn || document, 'c-c');
8945 * Tests various css rules/browsers to determine if this element uses a border box
8948 isBorderBox : function(){
8949 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8953 * Return a box {x, y, width, height} that can be used to set another elements
8954 * size/location to match this element.
8955 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8956 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8957 * @return {Object} box An object in the format {x, y, width, height}
8959 getBox : function(contentBox, local){
8964 var left = parseInt(this.getStyle("left"), 10) || 0;
8965 var top = parseInt(this.getStyle("top"), 10) || 0;
8968 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8970 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8972 var l = this.getBorderWidth("l")+this.getPadding("l");
8973 var r = this.getBorderWidth("r")+this.getPadding("r");
8974 var t = this.getBorderWidth("t")+this.getPadding("t");
8975 var b = this.getBorderWidth("b")+this.getPadding("b");
8976 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)};
8978 bx.right = bx.x + bx.width;
8979 bx.bottom = bx.y + bx.height;
8984 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8985 for more information about the sides.
8986 * @param {String} sides
8989 getFrameWidth : function(sides, onlyContentBox){
8990 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8994 * 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.
8995 * @param {Object} box The box to fill {x, y, width, height}
8996 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8997 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8998 * @return {Roo.Element} this
9000 setBox : function(box, adjust, animate){
9001 var w = box.width, h = box.height;
9002 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
9003 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
9004 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
9006 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
9011 * Forces the browser to repaint this element
9012 * @return {Roo.Element} this
9014 repaint : function(){
9016 this.addClass("x-repaint");
9017 setTimeout(function(){
9018 Roo.get(dom).removeClass("x-repaint");
9024 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
9025 * then it returns the calculated width of the sides (see getPadding)
9026 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
9027 * @return {Object/Number}
9029 getMargins : function(side){
9032 top: parseInt(this.getStyle("margin-top"), 10) || 0,
9033 left: parseInt(this.getStyle("margin-left"), 10) || 0,
9034 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
9035 right: parseInt(this.getStyle("margin-right"), 10) || 0
9038 return this.addStyles(side, El.margins);
9043 addStyles : function(sides, styles){
9045 for(var i = 0, len = sides.length; i < len; i++){
9046 v = this.getStyle(styles[sides.charAt(i)]);
9048 w = parseInt(v, 10);
9056 * Creates a proxy element of this element
9057 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
9058 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
9059 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
9060 * @return {Roo.Element} The new proxy element
9062 createProxy : function(config, renderTo, matchBox){
9064 renderTo = Roo.getDom(renderTo);
9066 renderTo = document.body;
9068 config = typeof config == "object" ?
9069 config : {tag : "div", cls: config};
9070 var proxy = Roo.DomHelper.append(renderTo, config, true);
9072 proxy.setBox(this.getBox());
9078 * Puts a mask over this element to disable user interaction. Requires core.css.
9079 * This method can only be applied to elements which accept child nodes.
9080 * @param {String} msg (optional) A message to display in the mask
9081 * @param {String} msgCls (optional) A css class to apply to the msg element
9082 * @return {Element} The mask element
9084 mask : function(msg, msgCls)
9086 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
9087 this.setStyle("position", "relative");
9090 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
9092 this.addClass("x-masked");
9093 this._mask.setDisplayed(true);
9098 while (dom && dom.style) {
9099 if (!isNaN(parseInt(dom.style.zIndex))) {
9100 z = Math.max(z, parseInt(dom.style.zIndex));
9102 dom = dom.parentNode;
9104 // if we are masking the body - then it hides everything..
9105 if (this.dom == document.body) {
9107 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9108 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9111 if(typeof msg == 'string'){
9113 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9115 var mm = this._maskMsg;
9116 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9117 if (mm.dom.firstChild) { // weird IE issue?
9118 mm.dom.firstChild.innerHTML = msg;
9120 mm.setDisplayed(true);
9122 mm.setStyle('z-index', z + 102);
9124 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9125 this._mask.setHeight(this.getHeight());
9127 this._mask.setStyle('z-index', z + 100);
9133 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9134 * it is cached for reuse.
9136 unmask : function(removeEl){
9138 if(removeEl === true){
9139 this._mask.remove();
9142 this._maskMsg.remove();
9143 delete this._maskMsg;
9146 this._mask.setDisplayed(false);
9148 this._maskMsg.setDisplayed(false);
9152 this.removeClass("x-masked");
9156 * Returns true if this element is masked
9159 isMasked : function(){
9160 return this._mask && this._mask.isVisible();
9164 * Creates an iframe shim for this element to keep selects and other windowed objects from
9166 * @return {Roo.Element} The new shim element
9168 createShim : function(){
9169 var el = document.createElement('iframe');
9170 el.frameBorder = 'no';
9171 el.className = 'roo-shim';
9172 if(Roo.isIE && Roo.isSecure){
9173 el.src = Roo.SSL_SECURE_URL;
9175 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9176 shim.autoBoxAdjust = false;
9181 * Removes this element from the DOM and deletes it from the cache
9183 remove : function(){
9184 if(this.dom.parentNode){
9185 this.dom.parentNode.removeChild(this.dom);
9187 delete El.cache[this.dom.id];
9191 * Sets up event handlers to add and remove a css class when the mouse is over this element
9192 * @param {String} className
9193 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9194 * mouseout events for children elements
9195 * @return {Roo.Element} this
9197 addClassOnOver : function(className, preventFlicker){
9198 this.on("mouseover", function(){
9199 Roo.fly(this, '_internal').addClass(className);
9201 var removeFn = function(e){
9202 if(preventFlicker !== true || !e.within(this, true)){
9203 Roo.fly(this, '_internal').removeClass(className);
9206 this.on("mouseout", removeFn, this.dom);
9211 * Sets up event handlers to add and remove a css class when this element has the focus
9212 * @param {String} className
9213 * @return {Roo.Element} this
9215 addClassOnFocus : function(className){
9216 this.on("focus", function(){
9217 Roo.fly(this, '_internal').addClass(className);
9219 this.on("blur", function(){
9220 Roo.fly(this, '_internal').removeClass(className);
9225 * 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)
9226 * @param {String} className
9227 * @return {Roo.Element} this
9229 addClassOnClick : function(className){
9231 this.on("mousedown", function(){
9232 Roo.fly(dom, '_internal').addClass(className);
9233 var d = Roo.get(document);
9234 var fn = function(){
9235 Roo.fly(dom, '_internal').removeClass(className);
9236 d.removeListener("mouseup", fn);
9238 d.on("mouseup", fn);
9244 * Stops the specified event from bubbling and optionally prevents the default action
9245 * @param {String} eventName
9246 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9247 * @return {Roo.Element} this
9249 swallowEvent : function(eventName, preventDefault){
9250 var fn = function(e){
9251 e.stopPropagation();
9256 if(eventName instanceof Array){
9257 for(var i = 0, len = eventName.length; i < len; i++){
9258 this.on(eventName[i], fn);
9262 this.on(eventName, fn);
9269 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9272 * Sizes this element to its parent element's dimensions performing
9273 * neccessary box adjustments.
9274 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9275 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9276 * @return {Roo.Element} this
9278 fitToParent : function(monitorResize, targetParent) {
9279 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9280 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9281 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9284 var p = Roo.get(targetParent || this.dom.parentNode);
9285 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9286 if (monitorResize === true) {
9287 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9288 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9294 * Gets the next sibling, skipping text nodes
9295 * @return {HTMLElement} The next sibling or null
9297 getNextSibling : function(){
9298 var n = this.dom.nextSibling;
9299 while(n && n.nodeType != 1){
9306 * Gets the previous sibling, skipping text nodes
9307 * @return {HTMLElement} The previous sibling or null
9309 getPrevSibling : function(){
9310 var n = this.dom.previousSibling;
9311 while(n && n.nodeType != 1){
9312 n = n.previousSibling;
9319 * Appends the passed element(s) to this element
9320 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9321 * @return {Roo.Element} this
9323 appendChild: function(el){
9330 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9331 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9332 * automatically generated with the specified attributes.
9333 * @param {HTMLElement} insertBefore (optional) a child element of this element
9334 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9335 * @return {Roo.Element} The new child element
9337 createChild: function(config, insertBefore, returnDom){
9338 config = config || {tag:'div'};
9340 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9342 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9346 * Appends this element to the passed element
9347 * @param {String/HTMLElement/Element} el The new parent element
9348 * @return {Roo.Element} this
9350 appendTo: function(el){
9351 el = Roo.getDom(el);
9352 el.appendChild(this.dom);
9357 * Inserts this element before the passed element in the DOM
9358 * @param {String/HTMLElement/Element} el The element to insert before
9359 * @return {Roo.Element} this
9361 insertBefore: function(el){
9362 el = Roo.getDom(el);
9363 el.parentNode.insertBefore(this.dom, el);
9368 * Inserts this element after the passed element in the DOM
9369 * @param {String/HTMLElement/Element} el The element to insert after
9370 * @return {Roo.Element} this
9372 insertAfter: function(el){
9373 el = Roo.getDom(el);
9374 el.parentNode.insertBefore(this.dom, el.nextSibling);
9379 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9380 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9381 * @return {Roo.Element} The new child
9383 insertFirst: function(el, returnDom){
9385 if(typeof el == 'object' && !el.nodeType){ // dh config
9386 return this.createChild(el, this.dom.firstChild, returnDom);
9388 el = Roo.getDom(el);
9389 this.dom.insertBefore(el, this.dom.firstChild);
9390 return !returnDom ? Roo.get(el) : el;
9395 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9396 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9397 * @param {String} where (optional) 'before' or 'after' defaults to before
9398 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9399 * @return {Roo.Element} the inserted Element
9401 insertSibling: function(el, where, returnDom){
9402 where = where ? where.toLowerCase() : 'before';
9404 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9406 if(typeof el == 'object' && !el.nodeType){ // dh config
9407 if(where == 'after' && !this.dom.nextSibling){
9408 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9410 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9414 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9415 where == 'before' ? this.dom : this.dom.nextSibling);
9424 * Creates and wraps this element with another element
9425 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9426 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9427 * @return {HTMLElement/Element} The newly created wrapper element
9429 wrap: function(config, returnDom){
9431 config = {tag: "div"};
9433 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9434 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9439 * Replaces the passed element with this element
9440 * @param {String/HTMLElement/Element} el The element to replace
9441 * @return {Roo.Element} this
9443 replace: function(el){
9445 this.insertBefore(el);
9451 * Inserts an html fragment into this element
9452 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9453 * @param {String} html The HTML fragment
9454 * @param {Boolean} returnEl True to return an Roo.Element
9455 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9457 insertHtml : function(where, html, returnEl){
9458 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9459 return returnEl ? Roo.get(el) : el;
9463 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9464 * @param {Object} o The object with the attributes
9465 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9466 * @return {Roo.Element} this
9468 set : function(o, useSet){
9470 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9472 if(attr == "style" || typeof o[attr] == "function") { continue; }
9474 el.className = o["cls"];
9477 el.setAttribute(attr, o[attr]);
9484 Roo.DomHelper.applyStyles(el, o.style);
9490 * Convenience method for constructing a KeyMap
9491 * @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:
9492 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9493 * @param {Function} fn The function to call
9494 * @param {Object} scope (optional) The scope of the function
9495 * @return {Roo.KeyMap} The KeyMap created
9497 addKeyListener : function(key, fn, scope){
9499 if(typeof key != "object" || key instanceof Array){
9515 return new Roo.KeyMap(this, config);
9519 * Creates a KeyMap for this element
9520 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9521 * @return {Roo.KeyMap} The KeyMap created
9523 addKeyMap : function(config){
9524 return new Roo.KeyMap(this, config);
9528 * Returns true if this element is scrollable.
9531 isScrollable : function(){
9533 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9537 * 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().
9538 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9539 * @param {Number} value The new scroll value
9540 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9541 * @return {Element} this
9544 scrollTo : function(side, value, animate){
9545 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9547 this.dom[prop] = value;
9549 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9550 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9556 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9557 * within this element's scrollable range.
9558 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9559 * @param {Number} distance How far to scroll the element in pixels
9560 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9561 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9562 * was scrolled as far as it could go.
9564 scroll : function(direction, distance, animate){
9565 if(!this.isScrollable()){
9569 var l = el.scrollLeft, t = el.scrollTop;
9570 var w = el.scrollWidth, h = el.scrollHeight;
9571 var cw = el.clientWidth, ch = el.clientHeight;
9572 direction = direction.toLowerCase();
9573 var scrolled = false;
9574 var a = this.preanim(arguments, 2);
9579 var v = Math.min(l + distance, w-cw);
9580 this.scrollTo("left", v, a);
9587 var v = Math.max(l - distance, 0);
9588 this.scrollTo("left", v, a);
9596 var v = Math.max(t - distance, 0);
9597 this.scrollTo("top", v, a);
9605 var v = Math.min(t + distance, h-ch);
9606 this.scrollTo("top", v, a);
9615 * Translates the passed page coordinates into left/top css values for this element
9616 * @param {Number/Array} x The page x or an array containing [x, y]
9617 * @param {Number} y The page y
9618 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9620 translatePoints : function(x, y){
9621 if(typeof x == 'object' || x instanceof Array){
9624 var p = this.getStyle('position');
9625 var o = this.getXY();
9627 var l = parseInt(this.getStyle('left'), 10);
9628 var t = parseInt(this.getStyle('top'), 10);
9631 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9634 t = (p == "relative") ? 0 : this.dom.offsetTop;
9637 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9641 * Returns the current scroll position of the element.
9642 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9644 getScroll : function(){
9645 var d = this.dom, doc = document;
9646 if(d == doc || d == doc.body){
9647 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9648 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9649 return {left: l, top: t};
9651 return {left: d.scrollLeft, top: d.scrollTop};
9656 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9657 * are convert to standard 6 digit hex color.
9658 * @param {String} attr The css attribute
9659 * @param {String} defaultValue The default value to use when a valid color isn't found
9660 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9663 getColor : function(attr, defaultValue, prefix){
9664 var v = this.getStyle(attr);
9665 if(!v || v == "transparent" || v == "inherit") {
9666 return defaultValue;
9668 var color = typeof prefix == "undefined" ? "#" : prefix;
9669 if(v.substr(0, 4) == "rgb("){
9670 var rvs = v.slice(4, v.length -1).split(",");
9671 for(var i = 0; i < 3; i++){
9672 var h = parseInt(rvs[i]).toString(16);
9679 if(v.substr(0, 1) == "#"){
9681 for(var i = 1; i < 4; i++){
9682 var c = v.charAt(i);
9685 }else if(v.length == 7){
9686 color += v.substr(1);
9690 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9694 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9695 * gradient background, rounded corners and a 4-way shadow.
9696 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9697 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9698 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9699 * @return {Roo.Element} this
9701 boxWrap : function(cls){
9702 cls = cls || 'x-box';
9703 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9704 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9709 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9710 * @param {String} namespace The namespace in which to look for the attribute
9711 * @param {String} name The attribute name
9712 * @return {String} The attribute value
9714 getAttributeNS : Roo.isIE ? function(ns, name){
9716 var type = typeof d[ns+":"+name];
9717 if(type != 'undefined' && type != 'unknown'){
9718 return d[ns+":"+name];
9721 } : function(ns, name){
9723 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9728 * Sets or Returns the value the dom attribute value
9729 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9730 * @param {String} value (optional) The value to set the attribute to
9731 * @return {String} The attribute value
9733 attr : function(name){
9734 if (arguments.length > 1) {
9735 this.dom.setAttribute(name, arguments[1]);
9736 return arguments[1];
9738 if (typeof(name) == 'object') {
9739 for(var i in name) {
9740 this.attr(i, name[i]);
9746 if (!this.dom.hasAttribute(name)) {
9749 return this.dom.getAttribute(name);
9756 var ep = El.prototype;
9759 * Appends an event handler (Shorthand for addListener)
9760 * @param {String} eventName The type of event to append
9761 * @param {Function} fn The method the event invokes
9762 * @param {Object} scope (optional) The scope (this object) of the fn
9763 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9766 ep.on = ep.addListener;
9768 ep.mon = ep.addListener;
9771 * Removes an event handler from this element (shorthand for removeListener)
9772 * @param {String} eventName the type of event to remove
9773 * @param {Function} fn the method the event invokes
9774 * @return {Roo.Element} this
9777 ep.un = ep.removeListener;
9780 * true to automatically adjust width and height settings for box-model issues (default to true)
9782 ep.autoBoxAdjust = true;
9785 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9788 El.addUnits = function(v, defaultUnit){
9789 if(v === "" || v == "auto"){
9792 if(v === undefined){
9795 if(typeof v == "number" || !El.unitPattern.test(v)){
9796 return v + (defaultUnit || 'px');
9801 // special markup used throughout Roo when box wrapping elements
9802 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>';
9804 * Visibility mode constant - Use visibility to hide element
9810 * Visibility mode constant - Use display to hide element
9816 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9817 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9818 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9830 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9831 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9832 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9833 * @return {Element} The Element object
9836 El.get = function(el){
9838 if(!el){ return null; }
9839 if(typeof el == "string"){ // element id
9840 if(!(elm = document.getElementById(el))){
9843 if(ex = El.cache[el]){
9846 ex = El.cache[el] = new El(elm);
9849 }else if(el.tagName){ // dom element
9853 if(ex = El.cache[id]){
9856 ex = El.cache[id] = new El(el);
9859 }else if(el instanceof El){
9861 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9862 // catch case where it hasn't been appended
9863 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9866 }else if(el.isComposite){
9868 }else if(el instanceof Array){
9869 return El.select(el);
9870 }else if(el == document){
9871 // create a bogus element object representing the document object
9873 var f = function(){};
9874 f.prototype = El.prototype;
9876 docEl.dom = document;
9884 El.uncache = function(el){
9885 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9887 delete El.cache[a[i].id || a[i]];
9893 // Garbage collection - uncache elements/purge listeners on orphaned elements
9894 // so we don't hold a reference and cause the browser to retain them
9895 El.garbageCollect = function(){
9896 if(!Roo.enableGarbageCollector){
9897 clearInterval(El.collectorThread);
9900 for(var eid in El.cache){
9901 var el = El.cache[eid], d = el.dom;
9902 // -------------------------------------------------------
9903 // Determining what is garbage:
9904 // -------------------------------------------------------
9906 // dom node is null, definitely garbage
9907 // -------------------------------------------------------
9909 // no parentNode == direct orphan, definitely garbage
9910 // -------------------------------------------------------
9911 // !d.offsetParent && !document.getElementById(eid)
9912 // display none elements have no offsetParent so we will
9913 // also try to look it up by it's id. However, check
9914 // offsetParent first so we don't do unneeded lookups.
9915 // This enables collection of elements that are not orphans
9916 // directly, but somewhere up the line they have an orphan
9918 // -------------------------------------------------------
9919 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9920 delete El.cache[eid];
9921 if(d && Roo.enableListenerCollection){
9927 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9931 El.Flyweight = function(dom){
9934 El.Flyweight.prototype = El.prototype;
9936 El._flyweights = {};
9938 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9939 * the dom node can be overwritten by other code.
9940 * @param {String/HTMLElement} el The dom node or id
9941 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9942 * prevent conflicts (e.g. internally Roo uses "_internal")
9944 * @return {Element} The shared Element object
9946 El.fly = function(el, named){
9947 named = named || '_global';
9948 el = Roo.getDom(el);
9952 if(!El._flyweights[named]){
9953 El._flyweights[named] = new El.Flyweight();
9955 El._flyweights[named].dom = el;
9956 return El._flyweights[named];
9960 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9961 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9962 * Shorthand of {@link Roo.Element#get}
9963 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9964 * @return {Element} The Element object
9970 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9971 * the dom node can be overwritten by other code.
9972 * Shorthand of {@link Roo.Element#fly}
9973 * @param {String/HTMLElement} el The dom node or id
9974 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9975 * prevent conflicts (e.g. internally Roo uses "_internal")
9977 * @return {Element} The shared Element object
9983 // speedy lookup for elements never to box adjust
9984 var noBoxAdjust = Roo.isStrict ? {
9987 input:1, select:1, textarea:1
9989 if(Roo.isIE || Roo.isGecko){
9990 noBoxAdjust['button'] = 1;
9994 Roo.EventManager.on(window, 'unload', function(){
9996 delete El._flyweights;
10004 Roo.Element.selectorFunction = Roo.DomQuery.select;
10007 Roo.Element.select = function(selector, unique, root){
10009 if(typeof selector == "string"){
10010 els = Roo.Element.selectorFunction(selector, root);
10011 }else if(selector.length !== undefined){
10014 throw "Invalid selector";
10016 if(unique === true){
10017 return new Roo.CompositeElement(els);
10019 return new Roo.CompositeElementLite(els);
10023 * Selects elements based on the passed CSS selector to enable working on them as 1.
10024 * @param {String/Array} selector The CSS selector or an array of elements
10025 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
10026 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
10027 * @return {CompositeElementLite/CompositeElement}
10031 Roo.select = Roo.Element.select;
10048 * Ext JS Library 1.1.1
10049 * Copyright(c) 2006-2007, Ext JS, LLC.
10051 * Originally Released Under LGPL - original licence link has changed is not relivant.
10054 * <script type="text/javascript">
10059 //Notifies Element that fx methods are available
10060 Roo.enableFx = true;
10064 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
10065 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
10066 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
10067 * Element effects to work.</p><br/>
10069 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
10070 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
10071 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
10072 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
10073 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
10074 * expected results and should be done with care.</p><br/>
10076 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
10077 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
10080 ----- -----------------------------
10081 tl The top left corner
10082 t The center of the top edge
10083 tr The top right corner
10084 l The center of the left edge
10085 r The center of the right edge
10086 bl The bottom left corner
10087 b The center of the bottom edge
10088 br The bottom right corner
10090 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
10091 * below are common options that can be passed to any Fx method.</b>
10092 * @cfg {Function} callback A function called when the effect is finished
10093 * @cfg {Object} scope The scope of the effect function
10094 * @cfg {String} easing A valid Easing value for the effect
10095 * @cfg {String} afterCls A css class to apply after the effect
10096 * @cfg {Number} duration The length of time (in seconds) that the effect should last
10097 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
10098 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
10099 * effects that end with the element being visually hidden, ignored otherwise)
10100 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
10101 * a function which returns such a specification that will be applied to the Element after the effect finishes
10102 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
10103 * @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
10104 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10108 * Slides the element into view. An anchor point can be optionally passed to set the point of
10109 * origin for the slide effect. This function automatically handles wrapping the element with
10110 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10113 // default: slide the element in from the top
10116 // custom: slide the element in from the right with a 2-second duration
10117 el.slideIn('r', { duration: 2 });
10119 // common config options shown with default values
10125 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10126 * @param {Object} options (optional) Object literal with any of the Fx config options
10127 * @return {Roo.Element} The Element
10129 slideIn : function(anchor, o){
10130 var el = this.getFxEl();
10133 el.queueFx(o, function(){
10135 anchor = anchor || "t";
10137 // fix display to visibility
10140 // restore values after effect
10141 var r = this.getFxRestore();
10142 var b = this.getBox();
10143 // fixed size for slide
10147 var wrap = this.fxWrap(r.pos, o, "hidden");
10149 var st = this.dom.style;
10150 st.visibility = "visible";
10151 st.position = "absolute";
10153 // clear out temp styles after slide and unwrap
10154 var after = function(){
10155 el.fxUnwrap(wrap, r.pos, o);
10156 st.width = r.width;
10157 st.height = r.height;
10160 // time to calc the positions
10161 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10163 switch(anchor.toLowerCase()){
10165 wrap.setSize(b.width, 0);
10166 st.left = st.bottom = "0";
10170 wrap.setSize(0, b.height);
10171 st.right = st.top = "0";
10175 wrap.setSize(0, b.height);
10176 wrap.setX(b.right);
10177 st.left = st.top = "0";
10178 a = {width: bw, points: pt};
10181 wrap.setSize(b.width, 0);
10182 wrap.setY(b.bottom);
10183 st.left = st.top = "0";
10184 a = {height: bh, points: pt};
10187 wrap.setSize(0, 0);
10188 st.right = st.bottom = "0";
10189 a = {width: bw, height: bh};
10192 wrap.setSize(0, 0);
10193 wrap.setY(b.y+b.height);
10194 st.right = st.top = "0";
10195 a = {width: bw, height: bh, points: pt};
10198 wrap.setSize(0, 0);
10199 wrap.setXY([b.right, b.bottom]);
10200 st.left = st.top = "0";
10201 a = {width: bw, height: bh, points: pt};
10204 wrap.setSize(0, 0);
10205 wrap.setX(b.x+b.width);
10206 st.left = st.bottom = "0";
10207 a = {width: bw, height: bh, points: pt};
10210 this.dom.style.visibility = "visible";
10213 arguments.callee.anim = wrap.fxanim(a,
10223 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10224 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10225 * 'hidden') but block elements will still take up space in the document. The element must be removed
10226 * from the DOM using the 'remove' config option if desired. This function automatically handles
10227 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10230 // default: slide the element out to the top
10233 // custom: slide the element out to the right with a 2-second duration
10234 el.slideOut('r', { duration: 2 });
10236 // common config options shown with default values
10244 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10245 * @param {Object} options (optional) Object literal with any of the Fx config options
10246 * @return {Roo.Element} The Element
10248 slideOut : function(anchor, o){
10249 var el = this.getFxEl();
10252 el.queueFx(o, function(){
10254 anchor = anchor || "t";
10256 // restore values after effect
10257 var r = this.getFxRestore();
10259 var b = this.getBox();
10260 // fixed size for slide
10264 var wrap = this.fxWrap(r.pos, o, "visible");
10266 var st = this.dom.style;
10267 st.visibility = "visible";
10268 st.position = "absolute";
10272 var after = function(){
10274 el.setDisplayed(false);
10279 el.fxUnwrap(wrap, r.pos, o);
10281 st.width = r.width;
10282 st.height = r.height;
10287 var a, zero = {to: 0};
10288 switch(anchor.toLowerCase()){
10290 st.left = st.bottom = "0";
10291 a = {height: zero};
10294 st.right = st.top = "0";
10298 st.left = st.top = "0";
10299 a = {width: zero, points: {to:[b.right, b.y]}};
10302 st.left = st.top = "0";
10303 a = {height: zero, points: {to:[b.x, b.bottom]}};
10306 st.right = st.bottom = "0";
10307 a = {width: zero, height: zero};
10310 st.right = st.top = "0";
10311 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10314 st.left = st.top = "0";
10315 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10318 st.left = st.bottom = "0";
10319 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10323 arguments.callee.anim = wrap.fxanim(a,
10333 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10334 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10335 * The element must be removed from the DOM using the 'remove' config option if desired.
10341 // common config options shown with default values
10349 * @param {Object} options (optional) Object literal with any of the Fx config options
10350 * @return {Roo.Element} The Element
10352 puff : function(o){
10353 var el = this.getFxEl();
10356 el.queueFx(o, function(){
10357 this.clearOpacity();
10360 // restore values after effect
10361 var r = this.getFxRestore();
10362 var st = this.dom.style;
10364 var after = function(){
10366 el.setDisplayed(false);
10373 el.setPositioning(r.pos);
10374 st.width = r.width;
10375 st.height = r.height;
10380 var width = this.getWidth();
10381 var height = this.getHeight();
10383 arguments.callee.anim = this.fxanim({
10384 width : {to: this.adjustWidth(width * 2)},
10385 height : {to: this.adjustHeight(height * 2)},
10386 points : {by: [-(width * .5), -(height * .5)]},
10388 fontSize: {to:200, unit: "%"}
10399 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10400 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10401 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10407 // all config options shown with default values
10415 * @param {Object} options (optional) Object literal with any of the Fx config options
10416 * @return {Roo.Element} The Element
10418 switchOff : function(o){
10419 var el = this.getFxEl();
10422 el.queueFx(o, function(){
10423 this.clearOpacity();
10426 // restore values after effect
10427 var r = this.getFxRestore();
10428 var st = this.dom.style;
10430 var after = function(){
10432 el.setDisplayed(false);
10438 el.setPositioning(r.pos);
10439 st.width = r.width;
10440 st.height = r.height;
10445 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10446 this.clearOpacity();
10450 points:{by:[0, this.getHeight() * .5]}
10451 }, o, 'motion', 0.3, 'easeIn', after);
10452 }).defer(100, this);
10459 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10460 * changed using the "attr" config option) and then fading back to the original color. If no original
10461 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10464 // default: highlight background to yellow
10467 // custom: highlight foreground text to blue for 2 seconds
10468 el.highlight("0000ff", { attr: 'color', duration: 2 });
10470 // common config options shown with default values
10471 el.highlight("ffff9c", {
10472 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10473 endColor: (current color) or "ffffff",
10478 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10479 * @param {Object} options (optional) Object literal with any of the Fx config options
10480 * @return {Roo.Element} The Element
10482 highlight : function(color, o){
10483 var el = this.getFxEl();
10486 el.queueFx(o, function(){
10487 color = color || "ffff9c";
10488 attr = o.attr || "backgroundColor";
10490 this.clearOpacity();
10493 var origColor = this.getColor(attr);
10494 var restoreColor = this.dom.style[attr];
10495 endColor = (o.endColor || origColor) || "ffffff";
10497 var after = function(){
10498 el.dom.style[attr] = restoreColor;
10503 a[attr] = {from: color, to: endColor};
10504 arguments.callee.anim = this.fxanim(a,
10514 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10517 // default: a single light blue ripple
10520 // custom: 3 red ripples lasting 3 seconds total
10521 el.frame("ff0000", 3, { duration: 3 });
10523 // common config options shown with default values
10524 el.frame("C3DAF9", 1, {
10525 duration: 1 //duration of entire animation (not each individual ripple)
10526 // Note: Easing is not configurable and will be ignored if included
10529 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10530 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10531 * @param {Object} options (optional) Object literal with any of the Fx config options
10532 * @return {Roo.Element} The Element
10534 frame : function(color, count, o){
10535 var el = this.getFxEl();
10538 el.queueFx(o, function(){
10539 color = color || "#C3DAF9";
10540 if(color.length == 6){
10541 color = "#" + color;
10543 count = count || 1;
10544 duration = o.duration || 1;
10547 var b = this.getBox();
10548 var animFn = function(){
10549 var proxy = this.createProxy({
10552 visbility:"hidden",
10553 position:"absolute",
10554 "z-index":"35000", // yee haw
10555 border:"0px solid " + color
10558 var scale = Roo.isBorderBox ? 2 : 1;
10560 top:{from:b.y, to:b.y - 20},
10561 left:{from:b.x, to:b.x - 20},
10562 borderWidth:{from:0, to:10},
10563 opacity:{from:1, to:0},
10564 height:{from:b.height, to:(b.height + (20*scale))},
10565 width:{from:b.width, to:(b.width + (20*scale))}
10566 }, duration, function(){
10570 animFn.defer((duration/2)*1000, this);
10581 * Creates a pause before any subsequent queued effects begin. If there are
10582 * no effects queued after the pause it will have no effect.
10587 * @param {Number} seconds The length of time to pause (in seconds)
10588 * @return {Roo.Element} The Element
10590 pause : function(seconds){
10591 var el = this.getFxEl();
10594 el.queueFx(o, function(){
10595 setTimeout(function(){
10597 }, seconds * 1000);
10603 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10604 * using the "endOpacity" config option.
10607 // default: fade in from opacity 0 to 100%
10610 // custom: fade in from opacity 0 to 75% over 2 seconds
10611 el.fadeIn({ endOpacity: .75, duration: 2});
10613 // common config options shown with default values
10615 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10620 * @param {Object} options (optional) Object literal with any of the Fx config options
10621 * @return {Roo.Element} The Element
10623 fadeIn : function(o){
10624 var el = this.getFxEl();
10626 el.queueFx(o, function(){
10627 this.setOpacity(0);
10629 this.dom.style.visibility = 'visible';
10630 var to = o.endOpacity || 1;
10631 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10632 o, null, .5, "easeOut", function(){
10634 this.clearOpacity();
10643 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10644 * using the "endOpacity" config option.
10647 // default: fade out from the element's current opacity to 0
10650 // custom: fade out from the element's current opacity to 25% over 2 seconds
10651 el.fadeOut({ endOpacity: .25, duration: 2});
10653 // common config options shown with default values
10655 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10662 * @param {Object} options (optional) Object literal with any of the Fx config options
10663 * @return {Roo.Element} The Element
10665 fadeOut : function(o){
10666 var el = this.getFxEl();
10668 el.queueFx(o, function(){
10669 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10670 o, null, .5, "easeOut", function(){
10671 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10672 this.dom.style.display = "none";
10674 this.dom.style.visibility = "hidden";
10676 this.clearOpacity();
10684 * Animates the transition of an element's dimensions from a starting height/width
10685 * to an ending height/width.
10688 // change height and width to 100x100 pixels
10689 el.scale(100, 100);
10691 // common config options shown with default values. The height and width will default to
10692 // the element's existing values if passed as null.
10695 [element's height], {
10700 * @param {Number} width The new width (pass undefined to keep the original width)
10701 * @param {Number} height The new height (pass undefined to keep the original height)
10702 * @param {Object} options (optional) Object literal with any of the Fx config options
10703 * @return {Roo.Element} The Element
10705 scale : function(w, h, o){
10706 this.shift(Roo.apply({}, o, {
10714 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10715 * Any of these properties not specified in the config object will not be changed. This effect
10716 * requires that at least one new dimension, position or opacity setting must be passed in on
10717 * the config object in order for the function to have any effect.
10720 // slide the element horizontally to x position 200 while changing the height and opacity
10721 el.shift({ x: 200, height: 50, opacity: .8 });
10723 // common config options shown with default values.
10725 width: [element's width],
10726 height: [element's height],
10727 x: [element's x position],
10728 y: [element's y position],
10729 opacity: [element's opacity],
10734 * @param {Object} options Object literal with any of the Fx config options
10735 * @return {Roo.Element} The Element
10737 shift : function(o){
10738 var el = this.getFxEl();
10740 el.queueFx(o, function(){
10741 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10742 if(w !== undefined){
10743 a.width = {to: this.adjustWidth(w)};
10745 if(h !== undefined){
10746 a.height = {to: this.adjustHeight(h)};
10748 if(x !== undefined || y !== undefined){
10750 x !== undefined ? x : this.getX(),
10751 y !== undefined ? y : this.getY()
10754 if(op !== undefined){
10755 a.opacity = {to: op};
10757 if(o.xy !== undefined){
10758 a.points = {to: o.xy};
10760 arguments.callee.anim = this.fxanim(a,
10761 o, 'motion', .35, "easeOut", function(){
10769 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10770 * ending point of the effect.
10773 // default: slide the element downward while fading out
10776 // custom: slide the element out to the right with a 2-second duration
10777 el.ghost('r', { duration: 2 });
10779 // common config options shown with default values
10787 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10788 * @param {Object} options (optional) Object literal with any of the Fx config options
10789 * @return {Roo.Element} The Element
10791 ghost : function(anchor, o){
10792 var el = this.getFxEl();
10795 el.queueFx(o, function(){
10796 anchor = anchor || "b";
10798 // restore values after effect
10799 var r = this.getFxRestore();
10800 var w = this.getWidth(),
10801 h = this.getHeight();
10803 var st = this.dom.style;
10805 var after = function(){
10807 el.setDisplayed(false);
10813 el.setPositioning(r.pos);
10814 st.width = r.width;
10815 st.height = r.height;
10820 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10821 switch(anchor.toLowerCase()){
10848 arguments.callee.anim = this.fxanim(a,
10858 * Ensures that all effects queued after syncFx is called on the element are
10859 * run concurrently. This is the opposite of {@link #sequenceFx}.
10860 * @return {Roo.Element} The Element
10862 syncFx : function(){
10863 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10872 * Ensures that all effects queued after sequenceFx is called on the element are
10873 * run in sequence. This is the opposite of {@link #syncFx}.
10874 * @return {Roo.Element} The Element
10876 sequenceFx : function(){
10877 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10879 concurrent : false,
10886 nextFx : function(){
10887 var ef = this.fxQueue[0];
10894 * Returns true if the element has any effects actively running or queued, else returns false.
10895 * @return {Boolean} True if element has active effects, else false
10897 hasActiveFx : function(){
10898 return this.fxQueue && this.fxQueue[0];
10902 * Stops any running effects and clears the element's internal effects queue if it contains
10903 * any additional effects that haven't started yet.
10904 * @return {Roo.Element} The Element
10906 stopFx : function(){
10907 if(this.hasActiveFx()){
10908 var cur = this.fxQueue[0];
10909 if(cur && cur.anim && cur.anim.isAnimated()){
10910 this.fxQueue = [cur]; // clear out others
10911 cur.anim.stop(true);
10918 beforeFx : function(o){
10919 if(this.hasActiveFx() && !o.concurrent){
10930 * Returns true if the element is currently blocking so that no other effect can be queued
10931 * until this effect is finished, else returns false if blocking is not set. This is commonly
10932 * used to ensure that an effect initiated by a user action runs to completion prior to the
10933 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10934 * @return {Boolean} True if blocking, else false
10936 hasFxBlock : function(){
10937 var q = this.fxQueue;
10938 return q && q[0] && q[0].block;
10942 queueFx : function(o, fn){
10946 if(!this.hasFxBlock()){
10947 Roo.applyIf(o, this.fxDefaults);
10949 var run = this.beforeFx(o);
10950 fn.block = o.block;
10951 this.fxQueue.push(fn);
10963 fxWrap : function(pos, o, vis){
10965 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10968 wrapXY = this.getXY();
10970 var div = document.createElement("div");
10971 div.style.visibility = vis;
10972 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10973 wrap.setPositioning(pos);
10974 if(wrap.getStyle("position") == "static"){
10975 wrap.position("relative");
10977 this.clearPositioning('auto');
10979 wrap.dom.appendChild(this.dom);
10981 wrap.setXY(wrapXY);
10988 fxUnwrap : function(wrap, pos, o){
10989 this.clearPositioning();
10990 this.setPositioning(pos);
10992 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10998 getFxRestore : function(){
10999 var st = this.dom.style;
11000 return {pos: this.getPositioning(), width: st.width, height : st.height};
11004 afterFx : function(o){
11006 this.applyStyles(o.afterStyle);
11009 this.addClass(o.afterCls);
11011 if(o.remove === true){
11014 Roo.callback(o.callback, o.scope, [this]);
11016 this.fxQueue.shift();
11022 getFxEl : function(){ // support for composite element fx
11023 return Roo.get(this.dom);
11027 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
11028 animType = animType || 'run';
11030 var anim = Roo.lib.Anim[animType](
11032 (opt.duration || defaultDur) || .35,
11033 (opt.easing || defaultEase) || 'easeOut',
11035 Roo.callback(cb, this);
11044 // backwords compat
11045 Roo.Fx.resize = Roo.Fx.scale;
11047 //When included, Roo.Fx is automatically applied to Element so that all basic
11048 //effects are available directly via the Element API
11049 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
11051 * Ext JS Library 1.1.1
11052 * Copyright(c) 2006-2007, Ext JS, LLC.
11054 * Originally Released Under LGPL - original licence link has changed is not relivant.
11057 * <script type="text/javascript">
11062 * @class Roo.CompositeElement
11063 * Standard composite class. Creates a Roo.Element for every element in the collection.
11065 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11066 * actions will be performed on all the elements in this collection.</b>
11068 * All methods return <i>this</i> and can be chained.
11070 var els = Roo.select("#some-el div.some-class", true);
11071 // or select directly from an existing element
11072 var el = Roo.get('some-el');
11073 el.select('div.some-class', true);
11075 els.setWidth(100); // all elements become 100 width
11076 els.hide(true); // all elements fade out and hide
11078 els.setWidth(100).hide(true);
11081 Roo.CompositeElement = function(els){
11082 this.elements = [];
11083 this.addElements(els);
11085 Roo.CompositeElement.prototype = {
11087 addElements : function(els){
11091 if(typeof els == "string"){
11092 els = Roo.Element.selectorFunction(els);
11094 var yels = this.elements;
11095 var index = yels.length-1;
11096 for(var i = 0, len = els.length; i < len; i++) {
11097 yels[++index] = Roo.get(els[i]);
11103 * Clears this composite and adds the elements returned by the passed selector.
11104 * @param {String/Array} els A string CSS selector, an array of elements or an element
11105 * @return {CompositeElement} this
11107 fill : function(els){
11108 this.elements = [];
11114 * Filters this composite to only elements that match the passed selector.
11115 * @param {String} selector A string CSS selector
11116 * @param {Boolean} inverse return inverse filter (not matches)
11117 * @return {CompositeElement} this
11119 filter : function(selector, inverse){
11121 inverse = inverse || false;
11122 this.each(function(el){
11123 var match = inverse ? !el.is(selector) : el.is(selector);
11125 els[els.length] = el.dom;
11132 invoke : function(fn, args){
11133 var els = this.elements;
11134 for(var i = 0, len = els.length; i < len; i++) {
11135 Roo.Element.prototype[fn].apply(els[i], args);
11140 * Adds elements to this composite.
11141 * @param {String/Array} els A string CSS selector, an array of elements or an element
11142 * @return {CompositeElement} this
11144 add : function(els){
11145 if(typeof els == "string"){
11146 this.addElements(Roo.Element.selectorFunction(els));
11147 }else if(els.length !== undefined){
11148 this.addElements(els);
11150 this.addElements([els]);
11155 * Calls the passed function passing (el, this, index) for each element in this composite.
11156 * @param {Function} fn The function to call
11157 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11158 * @return {CompositeElement} this
11160 each : function(fn, scope){
11161 var els = this.elements;
11162 for(var i = 0, len = els.length; i < len; i++){
11163 if(fn.call(scope || els[i], els[i], this, i) === false) {
11171 * Returns the Element object at the specified index
11172 * @param {Number} index
11173 * @return {Roo.Element}
11175 item : function(index){
11176 return this.elements[index] || null;
11180 * Returns the first Element
11181 * @return {Roo.Element}
11183 first : function(){
11184 return this.item(0);
11188 * Returns the last Element
11189 * @return {Roo.Element}
11192 return this.item(this.elements.length-1);
11196 * Returns the number of elements in this composite
11199 getCount : function(){
11200 return this.elements.length;
11204 * Returns true if this composite contains the passed element
11207 contains : function(el){
11208 return this.indexOf(el) !== -1;
11212 * Returns true if this composite contains the passed element
11215 indexOf : function(el){
11216 return this.elements.indexOf(Roo.get(el));
11221 * Removes the specified element(s).
11222 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11223 * or an array of any of those.
11224 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11225 * @return {CompositeElement} this
11227 removeElement : function(el, removeDom){
11228 if(el instanceof Array){
11229 for(var i = 0, len = el.length; i < len; i++){
11230 this.removeElement(el[i]);
11234 var index = typeof el == 'number' ? el : this.indexOf(el);
11237 var d = this.elements[index];
11241 d.parentNode.removeChild(d);
11244 this.elements.splice(index, 1);
11250 * Replaces the specified element with the passed element.
11251 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11253 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11254 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11255 * @return {CompositeElement} this
11257 replaceElement : function(el, replacement, domReplace){
11258 var index = typeof el == 'number' ? el : this.indexOf(el);
11261 this.elements[index].replaceWith(replacement);
11263 this.elements.splice(index, 1, Roo.get(replacement))
11270 * Removes all elements.
11272 clear : function(){
11273 this.elements = [];
11277 Roo.CompositeElement.createCall = function(proto, fnName){
11278 if(!proto[fnName]){
11279 proto[fnName] = function(){
11280 return this.invoke(fnName, arguments);
11284 for(var fnName in Roo.Element.prototype){
11285 if(typeof Roo.Element.prototype[fnName] == "function"){
11286 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11292 * Ext JS Library 1.1.1
11293 * Copyright(c) 2006-2007, Ext JS, LLC.
11295 * Originally Released Under LGPL - original licence link has changed is not relivant.
11298 * <script type="text/javascript">
11302 * @class Roo.CompositeElementLite
11303 * @extends Roo.CompositeElement
11304 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11306 var els = Roo.select("#some-el div.some-class");
11307 // or select directly from an existing element
11308 var el = Roo.get('some-el');
11309 el.select('div.some-class');
11311 els.setWidth(100); // all elements become 100 width
11312 els.hide(true); // all elements fade out and hide
11314 els.setWidth(100).hide(true);
11315 </code></pre><br><br>
11316 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11317 * actions will be performed on all the elements in this collection.</b>
11319 Roo.CompositeElementLite = function(els){
11320 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11321 this.el = new Roo.Element.Flyweight();
11323 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11324 addElements : function(els){
11326 if(els instanceof Array){
11327 this.elements = this.elements.concat(els);
11329 var yels = this.elements;
11330 var index = yels.length-1;
11331 for(var i = 0, len = els.length; i < len; i++) {
11332 yels[++index] = els[i];
11338 invoke : function(fn, args){
11339 var els = this.elements;
11341 for(var i = 0, len = els.length; i < len; i++) {
11343 Roo.Element.prototype[fn].apply(el, args);
11348 * Returns a flyweight Element of the dom element object at the specified index
11349 * @param {Number} index
11350 * @return {Roo.Element}
11352 item : function(index){
11353 if(!this.elements[index]){
11356 this.el.dom = this.elements[index];
11360 // fixes scope with flyweight
11361 addListener : function(eventName, handler, scope, opt){
11362 var els = this.elements;
11363 for(var i = 0, len = els.length; i < len; i++) {
11364 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11370 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11371 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11372 * a reference to the dom node, use el.dom.</b>
11373 * @param {Function} fn The function to call
11374 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11375 * @return {CompositeElement} this
11377 each : function(fn, scope){
11378 var els = this.elements;
11380 for(var i = 0, len = els.length; i < len; i++){
11382 if(fn.call(scope || el, el, this, i) === false){
11389 indexOf : function(el){
11390 return this.elements.indexOf(Roo.getDom(el));
11393 replaceElement : function(el, replacement, domReplace){
11394 var index = typeof el == 'number' ? el : this.indexOf(el);
11396 replacement = Roo.getDom(replacement);
11398 var d = this.elements[index];
11399 d.parentNode.insertBefore(replacement, d);
11400 d.parentNode.removeChild(d);
11402 this.elements.splice(index, 1, replacement);
11407 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11411 * Ext JS Library 1.1.1
11412 * Copyright(c) 2006-2007, Ext JS, LLC.
11414 * Originally Released Under LGPL - original licence link has changed is not relivant.
11417 * <script type="text/javascript">
11423 * @class Roo.data.Connection
11424 * @extends Roo.util.Observable
11425 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11426 * either to a configured URL, or to a URL specified at request time.<br><br>
11428 * Requests made by this class are asynchronous, and will return immediately. No data from
11429 * the server will be available to the statement immediately following the {@link #request} call.
11430 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11432 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11433 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11434 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11435 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11436 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11437 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11438 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11439 * standard DOM methods.
11441 * @param {Object} config a configuration object.
11443 Roo.data.Connection = function(config){
11444 Roo.apply(this, config);
11447 * @event beforerequest
11448 * Fires before a network request is made to retrieve a data object.
11449 * @param {Connection} conn This Connection object.
11450 * @param {Object} options The options config object passed to the {@link #request} method.
11452 "beforerequest" : true,
11454 * @event requestcomplete
11455 * Fires if the request was successfully completed.
11456 * @param {Connection} conn This Connection object.
11457 * @param {Object} response The XHR object containing the response data.
11458 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11459 * @param {Object} options The options config object passed to the {@link #request} method.
11461 "requestcomplete" : true,
11463 * @event requestexception
11464 * Fires if an error HTTP status was returned from the server.
11465 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11466 * @param {Connection} conn This Connection object.
11467 * @param {Object} response The XHR object containing the response data.
11468 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11469 * @param {Object} options The options config object passed to the {@link #request} method.
11471 "requestexception" : true
11473 Roo.data.Connection.superclass.constructor.call(this);
11476 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11478 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11481 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11482 * extra parameters to each request made by this object. (defaults to undefined)
11485 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11486 * to each request made by this object. (defaults to undefined)
11489 * @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)
11492 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11496 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11502 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11505 disableCaching: true,
11508 * Sends an HTTP request to a remote server.
11509 * @param {Object} options An object which may contain the following properties:<ul>
11510 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11511 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11512 * request, a url encoded string or a function to call to get either.</li>
11513 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11514 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11515 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11516 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11517 * <li>options {Object} The parameter to the request call.</li>
11518 * <li>success {Boolean} True if the request succeeded.</li>
11519 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11521 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11522 * The callback is passed the following parameters:<ul>
11523 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11524 * <li>options {Object} The parameter to the request call.</li>
11526 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11527 * The callback is passed the following parameters:<ul>
11528 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11529 * <li>options {Object} The parameter to the request call.</li>
11531 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11532 * for the callback function. Defaults to the browser window.</li>
11533 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11534 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11535 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11536 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11537 * params for the post data. Any params will be appended to the URL.</li>
11538 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11540 * @return {Number} transactionId
11542 request : function(o){
11543 if(this.fireEvent("beforerequest", this, o) !== false){
11546 if(typeof p == "function"){
11547 p = p.call(o.scope||window, o);
11549 if(typeof p == "object"){
11550 p = Roo.urlEncode(o.params);
11552 if(this.extraParams){
11553 var extras = Roo.urlEncode(this.extraParams);
11554 p = p ? (p + '&' + extras) : extras;
11557 var url = o.url || this.url;
11558 if(typeof url == 'function'){
11559 url = url.call(o.scope||window, o);
11563 var form = Roo.getDom(o.form);
11564 url = url || form.action;
11566 var enctype = form.getAttribute("enctype");
11567 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11568 return this.doFormUpload(o, p, url);
11570 var f = Roo.lib.Ajax.serializeForm(form);
11571 p = p ? (p + '&' + f) : f;
11574 var hs = o.headers;
11575 if(this.defaultHeaders){
11576 hs = Roo.apply(hs || {}, this.defaultHeaders);
11583 success: this.handleResponse,
11584 failure: this.handleFailure,
11586 argument: {options: o},
11587 timeout : o.timeout || this.timeout
11590 var method = o.method||this.method||(p ? "POST" : "GET");
11592 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11593 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11596 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11600 }else if(this.autoAbort !== false){
11604 if((method == 'GET' && p) || o.xmlData){
11605 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11608 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11609 return this.transId;
11611 Roo.callback(o.callback, o.scope, [o, null, null]);
11617 * Determine whether this object has a request outstanding.
11618 * @param {Number} transactionId (Optional) defaults to the last transaction
11619 * @return {Boolean} True if there is an outstanding request.
11621 isLoading : function(transId){
11623 return Roo.lib.Ajax.isCallInProgress(transId);
11625 return this.transId ? true : false;
11630 * Aborts any outstanding request.
11631 * @param {Number} transactionId (Optional) defaults to the last transaction
11633 abort : function(transId){
11634 if(transId || this.isLoading()){
11635 Roo.lib.Ajax.abort(transId || this.transId);
11640 handleResponse : function(response){
11641 this.transId = false;
11642 var options = response.argument.options;
11643 response.argument = options ? options.argument : null;
11644 this.fireEvent("requestcomplete", this, response, options);
11645 Roo.callback(options.success, options.scope, [response, options]);
11646 Roo.callback(options.callback, options.scope, [options, true, response]);
11650 handleFailure : function(response, e){
11651 this.transId = false;
11652 var options = response.argument.options;
11653 response.argument = options ? options.argument : null;
11654 this.fireEvent("requestexception", this, response, options, e);
11655 Roo.callback(options.failure, options.scope, [response, options]);
11656 Roo.callback(options.callback, options.scope, [options, false, response]);
11660 doFormUpload : function(o, ps, url){
11662 var frame = document.createElement('iframe');
11665 frame.className = 'x-hidden';
11667 frame.src = Roo.SSL_SECURE_URL;
11669 document.body.appendChild(frame);
11672 document.frames[id].name = id;
11675 var form = Roo.getDom(o.form);
11677 form.method = 'POST';
11678 form.enctype = form.encoding = 'multipart/form-data';
11684 if(ps){ // add dynamic params
11686 ps = Roo.urlDecode(ps, false);
11688 if(ps.hasOwnProperty(k)){
11689 hd = document.createElement('input');
11690 hd.type = 'hidden';
11693 form.appendChild(hd);
11700 var r = { // bogus response object
11705 r.argument = o ? o.argument : null;
11710 doc = frame.contentWindow.document;
11712 doc = (frame.contentDocument || window.frames[id].document);
11714 if(doc && doc.body){
11715 r.responseText = doc.body.innerHTML;
11717 if(doc && doc.XMLDocument){
11718 r.responseXML = doc.XMLDocument;
11720 r.responseXML = doc;
11727 Roo.EventManager.removeListener(frame, 'load', cb, this);
11729 this.fireEvent("requestcomplete", this, r, o);
11730 Roo.callback(o.success, o.scope, [r, o]);
11731 Roo.callback(o.callback, o.scope, [o, true, r]);
11733 setTimeout(function(){document.body.removeChild(frame);}, 100);
11736 Roo.EventManager.on(frame, 'load', cb, this);
11739 if(hiddens){ // remove dynamic params
11740 for(var i = 0, len = hiddens.length; i < len; i++){
11741 form.removeChild(hiddens[i]);
11748 * Ext JS Library 1.1.1
11749 * Copyright(c) 2006-2007, Ext JS, LLC.
11751 * Originally Released Under LGPL - original licence link has changed is not relivant.
11754 * <script type="text/javascript">
11758 * Global Ajax request class.
11761 * @extends Roo.data.Connection
11764 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11765 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11766 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11767 * @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)
11768 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11769 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11770 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11772 Roo.Ajax = new Roo.data.Connection({
11781 * Serialize the passed form into a url encoded string
11783 * @param {String/HTMLElement} form
11786 serializeForm : function(form){
11787 return Roo.lib.Ajax.serializeForm(form);
11791 * Ext JS Library 1.1.1
11792 * Copyright(c) 2006-2007, Ext JS, LLC.
11794 * Originally Released Under LGPL - original licence link has changed is not relivant.
11797 * <script type="text/javascript">
11802 * @class Roo.UpdateManager
11803 * @extends Roo.util.Observable
11804 * Provides AJAX-style update for Element object.<br><br>
11807 * // Get it from a Roo.Element object
11808 * var el = Roo.get("foo");
11809 * var mgr = el.getUpdateManager();
11810 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11812 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11814 * // or directly (returns the same UpdateManager instance)
11815 * var mgr = new Roo.UpdateManager("myElementId");
11816 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11817 * mgr.on("update", myFcnNeedsToKnow);
11819 // short handed call directly from the element object
11820 Roo.get("foo").load({
11824 text: "Loading Foo..."
11828 * Create new UpdateManager directly.
11829 * @param {String/HTMLElement/Roo.Element} el The element to update
11830 * @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).
11832 Roo.UpdateManager = function(el, forceNew){
11834 if(!forceNew && el.updateManager){
11835 return el.updateManager;
11838 * The Element object
11839 * @type Roo.Element
11843 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11846 this.defaultUrl = null;
11850 * @event beforeupdate
11851 * Fired before an update is made, return false from your handler and the update is cancelled.
11852 * @param {Roo.Element} el
11853 * @param {String/Object/Function} url
11854 * @param {String/Object} params
11856 "beforeupdate": true,
11859 * Fired after successful update is made.
11860 * @param {Roo.Element} el
11861 * @param {Object} oResponseObject The response Object
11866 * Fired on update failure.
11867 * @param {Roo.Element} el
11868 * @param {Object} oResponseObject The response Object
11872 var d = Roo.UpdateManager.defaults;
11874 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11877 this.sslBlankUrl = d.sslBlankUrl;
11879 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11882 this.disableCaching = d.disableCaching;
11884 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11887 this.indicatorText = d.indicatorText;
11889 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11892 this.showLoadIndicator = d.showLoadIndicator;
11894 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11897 this.timeout = d.timeout;
11900 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11903 this.loadScripts = d.loadScripts;
11906 * Transaction object of current executing transaction
11908 this.transaction = null;
11913 this.autoRefreshProcId = null;
11915 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11918 this.refreshDelegate = this.refresh.createDelegate(this);
11920 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11923 this.updateDelegate = this.update.createDelegate(this);
11925 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11928 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11932 this.successDelegate = this.processSuccess.createDelegate(this);
11936 this.failureDelegate = this.processFailure.createDelegate(this);
11938 if(!this.renderer){
11940 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11942 this.renderer = new Roo.UpdateManager.BasicRenderer();
11945 Roo.UpdateManager.superclass.constructor.call(this);
11948 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11950 * Get the Element this UpdateManager is bound to
11951 * @return {Roo.Element} The element
11953 getEl : function(){
11957 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11958 * @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:
11961 url: "your-url.php",<br/>
11962 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11963 callback: yourFunction,<br/>
11964 scope: yourObject, //(optional scope) <br/>
11965 discardUrl: false, <br/>
11966 nocache: false,<br/>
11967 text: "Loading...",<br/>
11969 scripts: false<br/>
11972 * The only required property is url. The optional properties nocache, text and scripts
11973 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11974 * @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}
11975 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11976 * @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.
11978 update : function(url, params, callback, discardUrl){
11979 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11980 var method = this.method,
11982 if(typeof url == "object"){ // must be config object
11985 params = params || cfg.params;
11986 callback = callback || cfg.callback;
11987 discardUrl = discardUrl || cfg.discardUrl;
11988 if(callback && cfg.scope){
11989 callback = callback.createDelegate(cfg.scope);
11991 if(typeof cfg.method != "undefined"){method = cfg.method;};
11992 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11993 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11994 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11995 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11997 this.showLoading();
11999 this.defaultUrl = url;
12001 if(typeof url == "function"){
12002 url = url.call(this);
12005 method = method || (params ? "POST" : "GET");
12006 if(method == "GET"){
12007 url = this.prepareUrl(url);
12010 var o = Roo.apply(cfg ||{}, {
12013 success: this.successDelegate,
12014 failure: this.failureDelegate,
12015 callback: undefined,
12016 timeout: (this.timeout*1000),
12017 argument: {"url": url, "form": null, "callback": callback, "params": params}
12019 Roo.log("updated manager called with timeout of " + o.timeout);
12020 this.transaction = Roo.Ajax.request(o);
12025 * 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.
12026 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
12027 * @param {String/HTMLElement} form The form Id or form element
12028 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
12029 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
12030 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
12032 formUpdate : function(form, url, reset, callback){
12033 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
12034 if(typeof url == "function"){
12035 url = url.call(this);
12037 form = Roo.getDom(form);
12038 this.transaction = Roo.Ajax.request({
12041 success: this.successDelegate,
12042 failure: this.failureDelegate,
12043 timeout: (this.timeout*1000),
12044 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
12046 this.showLoading.defer(1, this);
12051 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
12052 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12054 refresh : function(callback){
12055 if(this.defaultUrl == null){
12058 this.update(this.defaultUrl, null, callback, true);
12062 * Set this element to auto refresh.
12063 * @param {Number} interval How often to update (in seconds).
12064 * @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)
12065 * @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}
12066 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12067 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
12069 startAutoRefresh : function(interval, url, params, callback, refreshNow){
12071 this.update(url || this.defaultUrl, params, callback, true);
12073 if(this.autoRefreshProcId){
12074 clearInterval(this.autoRefreshProcId);
12076 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
12080 * Stop auto refresh on this element.
12082 stopAutoRefresh : function(){
12083 if(this.autoRefreshProcId){
12084 clearInterval(this.autoRefreshProcId);
12085 delete this.autoRefreshProcId;
12089 isAutoRefreshing : function(){
12090 return this.autoRefreshProcId ? true : false;
12093 * Called to update the element to "Loading" state. Override to perform custom action.
12095 showLoading : function(){
12096 if(this.showLoadIndicator){
12097 this.el.update(this.indicatorText);
12102 * Adds unique parameter to query string if disableCaching = true
12105 prepareUrl : function(url){
12106 if(this.disableCaching){
12107 var append = "_dc=" + (new Date().getTime());
12108 if(url.indexOf("?") !== -1){
12109 url += "&" + append;
12111 url += "?" + append;
12120 processSuccess : function(response){
12121 this.transaction = null;
12122 if(response.argument.form && response.argument.reset){
12123 try{ // put in try/catch since some older FF releases had problems with this
12124 response.argument.form.reset();
12127 if(this.loadScripts){
12128 this.renderer.render(this.el, response, this,
12129 this.updateComplete.createDelegate(this, [response]));
12131 this.renderer.render(this.el, response, this);
12132 this.updateComplete(response);
12136 updateComplete : function(response){
12137 this.fireEvent("update", this.el, response);
12138 if(typeof response.argument.callback == "function"){
12139 response.argument.callback(this.el, true, response);
12146 processFailure : function(response){
12147 this.transaction = null;
12148 this.fireEvent("failure", this.el, response);
12149 if(typeof response.argument.callback == "function"){
12150 response.argument.callback(this.el, false, response);
12155 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12156 * @param {Object} renderer The object implementing the render() method
12158 setRenderer : function(renderer){
12159 this.renderer = renderer;
12162 getRenderer : function(){
12163 return this.renderer;
12167 * Set the defaultUrl used for updates
12168 * @param {String/Function} defaultUrl The url or a function to call to get the url
12170 setDefaultUrl : function(defaultUrl){
12171 this.defaultUrl = defaultUrl;
12175 * Aborts the executing transaction
12177 abort : function(){
12178 if(this.transaction){
12179 Roo.Ajax.abort(this.transaction);
12184 * Returns true if an update is in progress
12185 * @return {Boolean}
12187 isUpdating : function(){
12188 if(this.transaction){
12189 return Roo.Ajax.isLoading(this.transaction);
12196 * @class Roo.UpdateManager.defaults
12197 * @static (not really - but it helps the doc tool)
12198 * The defaults collection enables customizing the default properties of UpdateManager
12200 Roo.UpdateManager.defaults = {
12202 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12208 * True to process scripts by default (Defaults to false).
12211 loadScripts : false,
12214 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12217 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12219 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12222 disableCaching : false,
12224 * Whether to show indicatorText when loading (Defaults to true).
12227 showLoadIndicator : true,
12229 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12232 indicatorText : '<div class="loading-indicator">Loading...</div>'
12236 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12238 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12239 * @param {String/HTMLElement/Roo.Element} el The element to update
12240 * @param {String} url The url
12241 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12242 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12245 * @member Roo.UpdateManager
12247 Roo.UpdateManager.updateElement = function(el, url, params, options){
12248 var um = Roo.get(el, true).getUpdateManager();
12249 Roo.apply(um, options);
12250 um.update(url, params, options ? options.callback : null);
12252 // alias for backwards compat
12253 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12255 * @class Roo.UpdateManager.BasicRenderer
12256 * Default Content renderer. Updates the elements innerHTML with the responseText.
12258 Roo.UpdateManager.BasicRenderer = function(){};
12260 Roo.UpdateManager.BasicRenderer.prototype = {
12262 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12263 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12264 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12265 * @param {Roo.Element} el The element being rendered
12266 * @param {Object} response The YUI Connect response object
12267 * @param {UpdateManager} updateManager The calling update manager
12268 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12270 render : function(el, response, updateManager, callback){
12271 el.update(response.responseText, updateManager.loadScripts, callback);
12277 * (c)) Alan Knowles
12283 * @class Roo.DomTemplate
12284 * @extends Roo.Template
12285 * An effort at a dom based template engine..
12287 * Similar to XTemplate, except it uses dom parsing to create the template..
12289 * Supported features:
12294 {a_variable} - output encoded.
12295 {a_variable.format:("Y-m-d")} - call a method on the variable
12296 {a_variable:raw} - unencoded output
12297 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12298 {a_variable:this.method_on_template(...)} - call a method on the template object.
12303 <div roo-for="a_variable or condition.."></div>
12304 <div roo-if="a_variable or condition"></div>
12305 <div roo-exec="some javascript"></div>
12306 <div roo-name="named_template"></div>
12311 Roo.DomTemplate = function()
12313 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12320 Roo.extend(Roo.DomTemplate, Roo.Template, {
12322 * id counter for sub templates.
12326 * flag to indicate if dom parser is inside a pre,
12327 * it will strip whitespace if not.
12332 * The various sub templates
12340 * basic tag replacing syntax
12343 * // you can fake an object call by doing this
12347 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12348 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12350 iterChild : function (node, method) {
12352 var oldPre = this.inPre;
12353 if (node.tagName == 'PRE') {
12356 for( var i = 0; i < node.childNodes.length; i++) {
12357 method.call(this, node.childNodes[i]);
12359 this.inPre = oldPre;
12365 * compile the template
12367 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12370 compile: function()
12374 // covert the html into DOM...
12378 doc = document.implementation.createHTMLDocument("");
12379 doc.documentElement.innerHTML = this.html ;
12380 div = doc.documentElement;
12382 // old IE... - nasty -- it causes all sorts of issues.. with
12383 // images getting pulled from server..
12384 div = document.createElement('div');
12385 div.innerHTML = this.html;
12387 //doc.documentElement.innerHTML = htmlBody
12393 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12395 var tpls = this.tpls;
12397 // create a top level template from the snippet..
12399 //Roo.log(div.innerHTML);
12406 body : div.innerHTML,
12419 Roo.each(tpls, function(tp){
12420 this.compileTpl(tp);
12421 this.tpls[tp.id] = tp;
12424 this.master = tpls[0];
12430 compileNode : function(node, istop) {
12435 // skip anything not a tag..
12436 if (node.nodeType != 1) {
12437 if (node.nodeType == 3 && !this.inPre) {
12438 // reduce white space..
12439 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12462 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12463 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12464 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12465 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12471 // just itterate children..
12472 this.iterChild(node,this.compileNode);
12475 tpl.uid = this.id++;
12476 tpl.value = node.getAttribute('roo-' + tpl.attr);
12477 node.removeAttribute('roo-'+ tpl.attr);
12478 if (tpl.attr != 'name') {
12479 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12480 node.parentNode.replaceChild(placeholder, node);
12483 var placeholder = document.createElement('span');
12484 placeholder.className = 'roo-tpl-' + tpl.value;
12485 node.parentNode.replaceChild(placeholder, node);
12488 // parent now sees '{domtplXXXX}
12489 this.iterChild(node,this.compileNode);
12491 // we should now have node body...
12492 var div = document.createElement('div');
12493 div.appendChild(node);
12495 // this has the unfortunate side effect of converting tagged attributes
12496 // eg. href="{...}" into %7C...%7D
12497 // this has been fixed by searching for those combo's although it's a bit hacky..
12500 tpl.body = div.innerHTML;
12507 switch (tpl.value) {
12508 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12509 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12510 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12515 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12519 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12523 tpl.id = tpl.value; // replace non characters???
12529 this.tpls.push(tpl);
12539 * Compile a segment of the template into a 'sub-template'
12545 compileTpl : function(tpl)
12547 var fm = Roo.util.Format;
12548 var useF = this.disableFormats !== true;
12550 var sep = Roo.isGecko ? "+\n" : ",\n";
12552 var undef = function(str) {
12553 Roo.debug && Roo.log("Property not found :" + str);
12557 //Roo.log(tpl.body);
12561 var fn = function(m, lbrace, name, format, args)
12564 //Roo.log(arguments);
12565 args = args ? args.replace(/\\'/g,"'") : args;
12566 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12567 if (typeof(format) == 'undefined') {
12568 format = 'htmlEncode';
12570 if (format == 'raw' ) {
12574 if(name.substr(0, 6) == 'domtpl'){
12575 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12578 // build an array of options to determine if value is undefined..
12580 // basically get 'xxxx.yyyy' then do
12581 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12582 // (function () { Roo.log("Property not found"); return ''; })() :
12587 Roo.each(name.split('.'), function(st) {
12588 lookfor += (lookfor.length ? '.': '') + st;
12589 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12592 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12595 if(format && useF){
12597 args = args ? ',' + args : "";
12599 if(format.substr(0, 5) != "this."){
12600 format = "fm." + format + '(';
12602 format = 'this.call("'+ format.substr(5) + '", ';
12606 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12609 if (args && args.length) {
12610 // called with xxyx.yuu:(test,test)
12612 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12614 // raw.. - :raw modifier..
12615 return "'"+ sep + udef_st + name + ")"+sep+"'";
12619 // branched to use + in gecko and [].join() in others
12621 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12622 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12625 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12626 body.push(tpl.body.replace(/(\r\n|\n)/g,
12627 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12628 body.push("'].join('');};};");
12629 body = body.join('');
12632 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12634 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12641 * same as applyTemplate, except it's done to one of the subTemplates
12642 * when using named templates, you can do:
12644 * var str = pl.applySubTemplate('your-name', values);
12647 * @param {Number} id of the template
12648 * @param {Object} values to apply to template
12649 * @param {Object} parent (normaly the instance of this object)
12651 applySubTemplate : function(id, values, parent)
12655 var t = this.tpls[id];
12659 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12660 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12664 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12671 if(t.execCall && t.execCall.call(this, values, parent)){
12675 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12681 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12682 parent = t.target ? values : parent;
12683 if(t.forCall && vs instanceof Array){
12685 for(var i = 0, len = vs.length; i < len; i++){
12687 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12689 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12691 //Roo.log(t.compiled);
12695 return buf.join('');
12698 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12703 return t.compiled.call(this, vs, parent);
12705 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12707 //Roo.log(t.compiled);
12715 applyTemplate : function(values){
12716 return this.master.compiled.call(this, values, {});
12717 //var s = this.subs;
12720 apply : function(){
12721 return this.applyTemplate.apply(this, arguments);
12726 Roo.DomTemplate.from = function(el){
12727 el = Roo.getDom(el);
12728 return new Roo.Domtemplate(el.value || el.innerHTML);
12731 * Ext JS Library 1.1.1
12732 * Copyright(c) 2006-2007, Ext JS, LLC.
12734 * Originally Released Under LGPL - original licence link has changed is not relivant.
12737 * <script type="text/javascript">
12741 * @class Roo.util.DelayedTask
12742 * Provides a convenient method of performing setTimeout where a new
12743 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12744 * You can use this class to buffer
12745 * the keypress events for a certain number of milliseconds, and perform only if they stop
12746 * for that amount of time.
12747 * @constructor The parameters to this constructor serve as defaults and are not required.
12748 * @param {Function} fn (optional) The default function to timeout
12749 * @param {Object} scope (optional) The default scope of that timeout
12750 * @param {Array} args (optional) The default Array of arguments
12752 Roo.util.DelayedTask = function(fn, scope, args){
12753 var id = null, d, t;
12755 var call = function(){
12756 var now = new Date().getTime();
12760 fn.apply(scope, args || []);
12764 * Cancels any pending timeout and queues a new one
12765 * @param {Number} delay The milliseconds to delay
12766 * @param {Function} newFn (optional) Overrides function passed to constructor
12767 * @param {Object} newScope (optional) Overrides scope passed to constructor
12768 * @param {Array} newArgs (optional) Overrides args passed to constructor
12770 this.delay = function(delay, newFn, newScope, newArgs){
12771 if(id && delay != d){
12775 t = new Date().getTime();
12777 scope = newScope || scope;
12778 args = newArgs || args;
12780 id = setInterval(call, d);
12785 * Cancel the last queued timeout
12787 this.cancel = function(){
12795 * Ext JS Library 1.1.1
12796 * Copyright(c) 2006-2007, Ext JS, LLC.
12798 * Originally Released Under LGPL - original licence link has changed is not relivant.
12801 * <script type="text/javascript">
12805 Roo.util.TaskRunner = function(interval){
12806 interval = interval || 10;
12807 var tasks = [], removeQueue = [];
12809 var running = false;
12811 var stopThread = function(){
12817 var startThread = function(){
12820 id = setInterval(runTasks, interval);
12824 var removeTask = function(task){
12825 removeQueue.push(task);
12831 var runTasks = function(){
12832 if(removeQueue.length > 0){
12833 for(var i = 0, len = removeQueue.length; i < len; i++){
12834 tasks.remove(removeQueue[i]);
12837 if(tasks.length < 1){
12842 var now = new Date().getTime();
12843 for(var i = 0, len = tasks.length; i < len; ++i){
12845 var itime = now - t.taskRunTime;
12846 if(t.interval <= itime){
12847 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12848 t.taskRunTime = now;
12849 if(rt === false || t.taskRunCount === t.repeat){
12854 if(t.duration && t.duration <= (now - t.taskStartTime)){
12861 * Queues a new task.
12862 * @param {Object} task
12864 this.start = function(task){
12866 task.taskStartTime = new Date().getTime();
12867 task.taskRunTime = 0;
12868 task.taskRunCount = 0;
12873 this.stop = function(task){
12878 this.stopAll = function(){
12880 for(var i = 0, len = tasks.length; i < len; i++){
12881 if(tasks[i].onStop){
12890 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12892 * Ext JS Library 1.1.1
12893 * Copyright(c) 2006-2007, Ext JS, LLC.
12895 * Originally Released Under LGPL - original licence link has changed is not relivant.
12898 * <script type="text/javascript">
12903 * @class Roo.util.MixedCollection
12904 * @extends Roo.util.Observable
12905 * A Collection class that maintains both numeric indexes and keys and exposes events.
12907 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12908 * collection (defaults to false)
12909 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12910 * and return the key value for that item. This is used when available to look up the key on items that
12911 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12912 * equivalent to providing an implementation for the {@link #getKey} method.
12914 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12922 * Fires when the collection is cleared.
12927 * Fires when an item is added to the collection.
12928 * @param {Number} index The index at which the item was added.
12929 * @param {Object} o The item added.
12930 * @param {String} key The key associated with the added item.
12935 * Fires when an item is replaced in the collection.
12936 * @param {String} key he key associated with the new added.
12937 * @param {Object} old The item being replaced.
12938 * @param {Object} new The new item.
12943 * Fires when an item is removed from the collection.
12944 * @param {Object} o The item being removed.
12945 * @param {String} key (optional) The key associated with the removed item.
12950 this.allowFunctions = allowFunctions === true;
12952 this.getKey = keyFn;
12954 Roo.util.MixedCollection.superclass.constructor.call(this);
12957 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12958 allowFunctions : false,
12961 * Adds an item to the collection.
12962 * @param {String} key The key to associate with the item
12963 * @param {Object} o The item to add.
12964 * @return {Object} The item added.
12966 add : function(key, o){
12967 if(arguments.length == 1){
12969 key = this.getKey(o);
12971 if(typeof key == "undefined" || key === null){
12973 this.items.push(o);
12974 this.keys.push(null);
12976 var old = this.map[key];
12978 return this.replace(key, o);
12981 this.items.push(o);
12983 this.keys.push(key);
12985 this.fireEvent("add", this.length-1, o, key);
12990 * MixedCollection has a generic way to fetch keys if you implement getKey.
12993 var mc = new Roo.util.MixedCollection();
12994 mc.add(someEl.dom.id, someEl);
12995 mc.add(otherEl.dom.id, otherEl);
12999 var mc = new Roo.util.MixedCollection();
13000 mc.getKey = function(el){
13006 // or via the constructor
13007 var mc = new Roo.util.MixedCollection(false, function(el){
13013 * @param o {Object} The item for which to find the key.
13014 * @return {Object} The key for the passed item.
13016 getKey : function(o){
13021 * Replaces an item in the collection.
13022 * @param {String} key The key associated with the item to replace, or the item to replace.
13023 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
13024 * @return {Object} The new item.
13026 replace : function(key, o){
13027 if(arguments.length == 1){
13029 key = this.getKey(o);
13031 var old = this.item(key);
13032 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
13033 return this.add(key, o);
13035 var index = this.indexOfKey(key);
13036 this.items[index] = o;
13038 this.fireEvent("replace", key, old, o);
13043 * Adds all elements of an Array or an Object to the collection.
13044 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
13045 * an Array of values, each of which are added to the collection.
13047 addAll : function(objs){
13048 if(arguments.length > 1 || objs instanceof Array){
13049 var args = arguments.length > 1 ? arguments : objs;
13050 for(var i = 0, len = args.length; i < len; i++){
13054 for(var key in objs){
13055 if(this.allowFunctions || typeof objs[key] != "function"){
13056 this.add(key, objs[key]);
13063 * Executes the specified function once for every item in the collection, passing each
13064 * item as the first and only parameter. returning false from the function will stop the iteration.
13065 * @param {Function} fn The function to execute for each item.
13066 * @param {Object} scope (optional) The scope in which to execute the function.
13068 each : function(fn, scope){
13069 var items = [].concat(this.items); // each safe for removal
13070 for(var i = 0, len = items.length; i < len; i++){
13071 if(fn.call(scope || items[i], items[i], i, len) === false){
13078 * Executes the specified function once for every key in the collection, passing each
13079 * key, and its associated item as the first two parameters.
13080 * @param {Function} fn The function to execute for each item.
13081 * @param {Object} scope (optional) The scope in which to execute the function.
13083 eachKey : function(fn, scope){
13084 for(var i = 0, len = this.keys.length; i < len; i++){
13085 fn.call(scope || window, this.keys[i], this.items[i], i, len);
13090 * Returns the first item in the collection which elicits a true return value from the
13091 * passed selection function.
13092 * @param {Function} fn The selection function to execute for each item.
13093 * @param {Object} scope (optional) The scope in which to execute the function.
13094 * @return {Object} The first item in the collection which returned true from the selection function.
13096 find : function(fn, scope){
13097 for(var i = 0, len = this.items.length; i < len; i++){
13098 if(fn.call(scope || window, this.items[i], this.keys[i])){
13099 return this.items[i];
13106 * Inserts an item at the specified index in the collection.
13107 * @param {Number} index The index to insert the item at.
13108 * @param {String} key The key to associate with the new item, or the item itself.
13109 * @param {Object} o (optional) If the second parameter was a key, the new item.
13110 * @return {Object} The item inserted.
13112 insert : function(index, key, o){
13113 if(arguments.length == 2){
13115 key = this.getKey(o);
13117 if(index >= this.length){
13118 return this.add(key, o);
13121 this.items.splice(index, 0, o);
13122 if(typeof key != "undefined" && key != null){
13125 this.keys.splice(index, 0, key);
13126 this.fireEvent("add", index, o, key);
13131 * Removed an item from the collection.
13132 * @param {Object} o The item to remove.
13133 * @return {Object} The item removed.
13135 remove : function(o){
13136 return this.removeAt(this.indexOf(o));
13140 * Remove an item from a specified index in the collection.
13141 * @param {Number} index The index within the collection of the item to remove.
13143 removeAt : function(index){
13144 if(index < this.length && index >= 0){
13146 var o = this.items[index];
13147 this.items.splice(index, 1);
13148 var key = this.keys[index];
13149 if(typeof key != "undefined"){
13150 delete this.map[key];
13152 this.keys.splice(index, 1);
13153 this.fireEvent("remove", o, key);
13158 * Removed an item associated with the passed key fom the collection.
13159 * @param {String} key The key of the item to remove.
13161 removeKey : function(key){
13162 return this.removeAt(this.indexOfKey(key));
13166 * Returns the number of items in the collection.
13167 * @return {Number} the number of items in the collection.
13169 getCount : function(){
13170 return this.length;
13174 * Returns index within the collection of the passed Object.
13175 * @param {Object} o The item to find the index of.
13176 * @return {Number} index of the item.
13178 indexOf : function(o){
13179 if(!this.items.indexOf){
13180 for(var i = 0, len = this.items.length; i < len; i++){
13181 if(this.items[i] == o) {
13187 return this.items.indexOf(o);
13192 * Returns index within the collection of the passed key.
13193 * @param {String} key The key to find the index of.
13194 * @return {Number} index of the key.
13196 indexOfKey : function(key){
13197 if(!this.keys.indexOf){
13198 for(var i = 0, len = this.keys.length; i < len; i++){
13199 if(this.keys[i] == key) {
13205 return this.keys.indexOf(key);
13210 * Returns the item associated with the passed key OR index. Key has priority over index.
13211 * @param {String/Number} key The key or index of the item.
13212 * @return {Object} The item associated with the passed key.
13214 item : function(key){
13215 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13216 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13220 * Returns the item at the specified index.
13221 * @param {Number} index The index of the item.
13224 itemAt : function(index){
13225 return this.items[index];
13229 * Returns the item associated with the passed key.
13230 * @param {String/Number} key The key of the item.
13231 * @return {Object} The item associated with the passed key.
13233 key : function(key){
13234 return this.map[key];
13238 * Returns true if the collection contains the passed Object as an item.
13239 * @param {Object} o The Object to look for in the collection.
13240 * @return {Boolean} True if the collection contains the Object as an item.
13242 contains : function(o){
13243 return this.indexOf(o) != -1;
13247 * Returns true if the collection contains the passed Object as a key.
13248 * @param {String} key The key to look for in the collection.
13249 * @return {Boolean} True if the collection contains the Object as a key.
13251 containsKey : function(key){
13252 return typeof this.map[key] != "undefined";
13256 * Removes all items from the collection.
13258 clear : function(){
13263 this.fireEvent("clear");
13267 * Returns the first item in the collection.
13268 * @return {Object} the first item in the collection..
13270 first : function(){
13271 return this.items[0];
13275 * Returns the last item in the collection.
13276 * @return {Object} the last item in the collection..
13279 return this.items[this.length-1];
13282 _sort : function(property, dir, fn){
13283 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13284 fn = fn || function(a, b){
13287 var c = [], k = this.keys, items = this.items;
13288 for(var i = 0, len = items.length; i < len; i++){
13289 c[c.length] = {key: k[i], value: items[i], index: i};
13291 c.sort(function(a, b){
13292 var v = fn(a[property], b[property]) * dsc;
13294 v = (a.index < b.index ? -1 : 1);
13298 for(var i = 0, len = c.length; i < len; i++){
13299 items[i] = c[i].value;
13302 this.fireEvent("sort", this);
13306 * Sorts this collection with the passed comparison function
13307 * @param {String} direction (optional) "ASC" or "DESC"
13308 * @param {Function} fn (optional) comparison function
13310 sort : function(dir, fn){
13311 this._sort("value", dir, fn);
13315 * Sorts this collection by keys
13316 * @param {String} direction (optional) "ASC" or "DESC"
13317 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13319 keySort : function(dir, fn){
13320 this._sort("key", dir, fn || function(a, b){
13321 return String(a).toUpperCase()-String(b).toUpperCase();
13326 * Returns a range of items in this collection
13327 * @param {Number} startIndex (optional) defaults to 0
13328 * @param {Number} endIndex (optional) default to the last item
13329 * @return {Array} An array of items
13331 getRange : function(start, end){
13332 var items = this.items;
13333 if(items.length < 1){
13336 start = start || 0;
13337 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13340 for(var i = start; i <= end; i++) {
13341 r[r.length] = items[i];
13344 for(var i = start; i >= end; i--) {
13345 r[r.length] = items[i];
13352 * Filter the <i>objects</i> in this collection by a specific property.
13353 * Returns a new collection that has been filtered.
13354 * @param {String} property A property on your objects
13355 * @param {String/RegExp} value Either string that the property values
13356 * should start with or a RegExp to test against the property
13357 * @return {MixedCollection} The new filtered collection
13359 filter : function(property, value){
13360 if(!value.exec){ // not a regex
13361 value = String(value);
13362 if(value.length == 0){
13363 return this.clone();
13365 value = new RegExp("^" + Roo.escapeRe(value), "i");
13367 return this.filterBy(function(o){
13368 return o && value.test(o[property]);
13373 * Filter by a function. * Returns a new collection that has been filtered.
13374 * The passed function will be called with each
13375 * object in the collection. If the function returns true, the value is included
13376 * otherwise it is filtered.
13377 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13378 * @param {Object} scope (optional) The scope of the function (defaults to this)
13379 * @return {MixedCollection} The new filtered collection
13381 filterBy : function(fn, scope){
13382 var r = new Roo.util.MixedCollection();
13383 r.getKey = this.getKey;
13384 var k = this.keys, it = this.items;
13385 for(var i = 0, len = it.length; i < len; i++){
13386 if(fn.call(scope||this, it[i], k[i])){
13387 r.add(k[i], it[i]);
13394 * Creates a duplicate of this collection
13395 * @return {MixedCollection}
13397 clone : function(){
13398 var r = new Roo.util.MixedCollection();
13399 var k = this.keys, it = this.items;
13400 for(var i = 0, len = it.length; i < len; i++){
13401 r.add(k[i], it[i]);
13403 r.getKey = this.getKey;
13408 * Returns the item associated with the passed key or index.
13410 * @param {String/Number} key The key or index of the item.
13411 * @return {Object} The item associated with the passed key.
13413 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13415 * Ext JS Library 1.1.1
13416 * Copyright(c) 2006-2007, Ext JS, LLC.
13418 * Originally Released Under LGPL - original licence link has changed is not relivant.
13421 * <script type="text/javascript">
13424 * @class Roo.util.JSON
13425 * Modified version of Douglas Crockford"s json.js that doesn"t
13426 * mess with the Object prototype
13427 * http://www.json.org/js.html
13430 Roo.util.JSON = new (function(){
13431 var useHasOwn = {}.hasOwnProperty ? true : false;
13433 // crashes Safari in some instances
13434 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13436 var pad = function(n) {
13437 return n < 10 ? "0" + n : n;
13450 var encodeString = function(s){
13451 if (/["\\\x00-\x1f]/.test(s)) {
13452 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13457 c = b.charCodeAt();
13459 Math.floor(c / 16).toString(16) +
13460 (c % 16).toString(16);
13463 return '"' + s + '"';
13466 var encodeArray = function(o){
13467 var a = ["["], b, i, l = o.length, v;
13468 for (i = 0; i < l; i += 1) {
13470 switch (typeof v) {
13479 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13487 var encodeDate = function(o){
13488 return '"' + o.getFullYear() + "-" +
13489 pad(o.getMonth() + 1) + "-" +
13490 pad(o.getDate()) + "T" +
13491 pad(o.getHours()) + ":" +
13492 pad(o.getMinutes()) + ":" +
13493 pad(o.getSeconds()) + '"';
13497 * Encodes an Object, Array or other value
13498 * @param {Mixed} o The variable to encode
13499 * @return {String} The JSON string
13501 this.encode = function(o)
13503 // should this be extended to fully wrap stringify..
13505 if(typeof o == "undefined" || o === null){
13507 }else if(o instanceof Array){
13508 return encodeArray(o);
13509 }else if(o instanceof Date){
13510 return encodeDate(o);
13511 }else if(typeof o == "string"){
13512 return encodeString(o);
13513 }else if(typeof o == "number"){
13514 return isFinite(o) ? String(o) : "null";
13515 }else if(typeof o == "boolean"){
13518 var a = ["{"], b, i, v;
13520 if(!useHasOwn || o.hasOwnProperty(i)) {
13522 switch (typeof v) {
13531 a.push(this.encode(i), ":",
13532 v === null ? "null" : this.encode(v));
13543 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13544 * @param {String} json The JSON string
13545 * @return {Object} The resulting object
13547 this.decode = function(json){
13549 return /** eval:var:json */ eval("(" + json + ')');
13553 * Shorthand for {@link Roo.util.JSON#encode}
13554 * @member Roo encode
13556 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13558 * Shorthand for {@link Roo.util.JSON#decode}
13559 * @member Roo decode
13561 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13564 * Ext JS Library 1.1.1
13565 * Copyright(c) 2006-2007, Ext JS, LLC.
13567 * Originally Released Under LGPL - original licence link has changed is not relivant.
13570 * <script type="text/javascript">
13574 * @class Roo.util.Format
13575 * Reusable data formatting functions
13578 Roo.util.Format = function(){
13579 var trimRe = /^\s+|\s+$/g;
13582 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13583 * @param {String} value The string to truncate
13584 * @param {Number} length The maximum length to allow before truncating
13585 * @return {String} The converted text
13587 ellipsis : function(value, len){
13588 if(value && value.length > len){
13589 return value.substr(0, len-3)+"...";
13595 * Checks a reference and converts it to empty string if it is undefined
13596 * @param {Mixed} value Reference to check
13597 * @return {Mixed} Empty string if converted, otherwise the original value
13599 undef : function(value){
13600 return typeof value != "undefined" ? value : "";
13604 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13605 * @param {String} value The string to encode
13606 * @return {String} The encoded text
13608 htmlEncode : function(value){
13609 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13613 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13614 * @param {String} value The string to decode
13615 * @return {String} The decoded text
13617 htmlDecode : function(value){
13618 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13622 * Trims any whitespace from either side of a string
13623 * @param {String} value The text to trim
13624 * @return {String} The trimmed text
13626 trim : function(value){
13627 return String(value).replace(trimRe, "");
13631 * Returns a substring from within an original string
13632 * @param {String} value The original text
13633 * @param {Number} start The start index of the substring
13634 * @param {Number} length The length of the substring
13635 * @return {String} The substring
13637 substr : function(value, start, length){
13638 return String(value).substr(start, length);
13642 * Converts a string to all lower case letters
13643 * @param {String} value The text to convert
13644 * @return {String} The converted text
13646 lowercase : function(value){
13647 return String(value).toLowerCase();
13651 * Converts a string to all upper case letters
13652 * @param {String} value The text to convert
13653 * @return {String} The converted text
13655 uppercase : function(value){
13656 return String(value).toUpperCase();
13660 * Converts the first character only of a string to upper case
13661 * @param {String} value The text to convert
13662 * @return {String} The converted text
13664 capitalize : function(value){
13665 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13669 call : function(value, fn){
13670 if(arguments.length > 2){
13671 var args = Array.prototype.slice.call(arguments, 2);
13672 args.unshift(value);
13674 return /** eval:var:value */ eval(fn).apply(window, args);
13676 /** eval:var:value */
13677 return /** eval:var:value */ eval(fn).call(window, value);
13683 * safer version of Math.toFixed..??/
13684 * @param {Number/String} value The numeric value to format
13685 * @param {Number/String} value Decimal places
13686 * @return {String} The formatted currency string
13688 toFixed : function(v, n)
13690 // why not use to fixed - precision is buggered???
13692 return Math.round(v-0);
13694 var fact = Math.pow(10,n+1);
13695 v = (Math.round((v-0)*fact))/fact;
13696 var z = (''+fact).substring(2);
13697 if (v == Math.floor(v)) {
13698 return Math.floor(v) + '.' + z;
13701 // now just padd decimals..
13702 var ps = String(v).split('.');
13703 var fd = (ps[1] + z);
13704 var r = fd.substring(0,n);
13705 var rm = fd.substring(n);
13707 return ps[0] + '.' + r;
13709 r*=1; // turn it into a number;
13711 if (String(r).length != n) {
13714 r = String(r).substring(1); // chop the end off.
13717 return ps[0] + '.' + r;
13722 * Format a number as US currency
13723 * @param {Number/String} value The numeric value to format
13724 * @return {String} The formatted currency string
13726 usMoney : function(v){
13727 return '$' + Roo.util.Format.number(v);
13732 * eventually this should probably emulate php's number_format
13733 * @param {Number/String} value The numeric value to format
13734 * @param {Number} decimals number of decimal places
13735 * @return {String} The formatted currency string
13737 number : function(v,decimals)
13739 // multiply and round.
13740 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13741 var mul = Math.pow(10, decimals);
13742 var zero = String(mul).substring(1);
13743 v = (Math.round((v-0)*mul))/mul;
13745 // if it's '0' number.. then
13747 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13749 var ps = v.split('.');
13753 var r = /(\d+)(\d{3})/;
13755 while (r.test(whole)) {
13756 whole = whole.replace(r, '$1' + ',' + '$2');
13762 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13763 // does not have decimals
13764 (decimals ? ('.' + zero) : '');
13767 return whole + sub ;
13771 * Parse a value into a formatted date using the specified format pattern.
13772 * @param {Mixed} value The value to format
13773 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13774 * @return {String} The formatted date string
13776 date : function(v, format){
13780 if(!(v instanceof Date)){
13781 v = new Date(Date.parse(v));
13783 return v.dateFormat(format || Roo.util.Format.defaults.date);
13787 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13788 * @param {String} format Any valid date format string
13789 * @return {Function} The date formatting function
13791 dateRenderer : function(format){
13792 return function(v){
13793 return Roo.util.Format.date(v, format);
13798 stripTagsRE : /<\/?[^>]+>/gi,
13801 * Strips all HTML tags
13802 * @param {Mixed} value The text from which to strip tags
13803 * @return {String} The stripped text
13805 stripTags : function(v){
13806 return !v ? v : String(v).replace(this.stripTagsRE, "");
13810 Roo.util.Format.defaults = {
13814 * Ext JS Library 1.1.1
13815 * Copyright(c) 2006-2007, Ext JS, LLC.
13817 * Originally Released Under LGPL - original licence link has changed is not relivant.
13820 * <script type="text/javascript">
13827 * @class Roo.MasterTemplate
13828 * @extends Roo.Template
13829 * Provides a template that can have child templates. The syntax is:
13831 var t = new Roo.MasterTemplate(
13832 '<select name="{name}">',
13833 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13836 t.add('options', {value: 'foo', text: 'bar'});
13837 // or you can add multiple child elements in one shot
13838 t.addAll('options', [
13839 {value: 'foo', text: 'bar'},
13840 {value: 'foo2', text: 'bar2'},
13841 {value: 'foo3', text: 'bar3'}
13843 // then append, applying the master template values
13844 t.append('my-form', {name: 'my-select'});
13846 * A name attribute for the child template is not required if you have only one child
13847 * template or you want to refer to them by index.
13849 Roo.MasterTemplate = function(){
13850 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13851 this.originalHtml = this.html;
13853 var m, re = this.subTemplateRe;
13856 while(m = re.exec(this.html)){
13857 var name = m[1], content = m[2];
13862 tpl : new Roo.Template(content)
13865 st[name] = st[subIndex];
13867 st[subIndex].tpl.compile();
13868 st[subIndex].tpl.call = this.call.createDelegate(this);
13871 this.subCount = subIndex;
13874 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13876 * The regular expression used to match sub templates
13880 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13883 * Applies the passed values to a child template.
13884 * @param {String/Number} name (optional) The name or index of the child template
13885 * @param {Array/Object} values The values to be applied to the template
13886 * @return {MasterTemplate} this
13888 add : function(name, values){
13889 if(arguments.length == 1){
13890 values = arguments[0];
13893 var s = this.subs[name];
13894 s.buffer[s.buffer.length] = s.tpl.apply(values);
13899 * Applies all the passed values to a child template.
13900 * @param {String/Number} name (optional) The name or index of the child template
13901 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13902 * @param {Boolean} reset (optional) True to reset the template first
13903 * @return {MasterTemplate} this
13905 fill : function(name, values, reset){
13907 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13915 for(var i = 0, len = values.length; i < len; i++){
13916 this.add(name, values[i]);
13922 * Resets the template for reuse
13923 * @return {MasterTemplate} this
13925 reset : function(){
13927 for(var i = 0; i < this.subCount; i++){
13933 applyTemplate : function(values){
13935 var replaceIndex = -1;
13936 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13937 return s[++replaceIndex].buffer.join("");
13939 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13942 apply : function(){
13943 return this.applyTemplate.apply(this, arguments);
13946 compile : function(){return this;}
13950 * Alias for fill().
13953 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13955 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13956 * var tpl = Roo.MasterTemplate.from('element-id');
13957 * @param {String/HTMLElement} el
13958 * @param {Object} config
13961 Roo.MasterTemplate.from = function(el, config){
13962 el = Roo.getDom(el);
13963 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13966 * Ext JS Library 1.1.1
13967 * Copyright(c) 2006-2007, Ext JS, LLC.
13969 * Originally Released Under LGPL - original licence link has changed is not relivant.
13972 * <script type="text/javascript">
13977 * @class Roo.util.CSS
13978 * Utility class for manipulating CSS rules
13981 Roo.util.CSS = function(){
13983 var doc = document;
13985 var camelRe = /(-[a-z])/gi;
13986 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13990 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13991 * tag and appended to the HEAD of the document.
13992 * @param {String|Object} cssText The text containing the css rules
13993 * @param {String} id An id to add to the stylesheet for later removal
13994 * @return {StyleSheet}
13996 createStyleSheet : function(cssText, id){
13998 var head = doc.getElementsByTagName("head")[0];
13999 var nrules = doc.createElement("style");
14000 nrules.setAttribute("type", "text/css");
14002 nrules.setAttribute("id", id);
14004 if (typeof(cssText) != 'string') {
14005 // support object maps..
14006 // not sure if this a good idea..
14007 // perhaps it should be merged with the general css handling
14008 // and handle js style props.
14009 var cssTextNew = [];
14010 for(var n in cssText) {
14012 for(var k in cssText[n]) {
14013 citems.push( k + ' : ' +cssText[n][k] + ';' );
14015 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
14018 cssText = cssTextNew.join("\n");
14024 head.appendChild(nrules);
14025 ss = nrules.styleSheet;
14026 ss.cssText = cssText;
14029 nrules.appendChild(doc.createTextNode(cssText));
14031 nrules.cssText = cssText;
14033 head.appendChild(nrules);
14034 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
14036 this.cacheStyleSheet(ss);
14041 * Removes a style or link tag by id
14042 * @param {String} id The id of the tag
14044 removeStyleSheet : function(id){
14045 var existing = doc.getElementById(id);
14047 existing.parentNode.removeChild(existing);
14052 * Dynamically swaps an existing stylesheet reference for a new one
14053 * @param {String} id The id of an existing link tag to remove
14054 * @param {String} url The href of the new stylesheet to include
14056 swapStyleSheet : function(id, url){
14057 this.removeStyleSheet(id);
14058 var ss = doc.createElement("link");
14059 ss.setAttribute("rel", "stylesheet");
14060 ss.setAttribute("type", "text/css");
14061 ss.setAttribute("id", id);
14062 ss.setAttribute("href", url);
14063 doc.getElementsByTagName("head")[0].appendChild(ss);
14067 * Refresh the rule cache if you have dynamically added stylesheets
14068 * @return {Object} An object (hash) of rules indexed by selector
14070 refreshCache : function(){
14071 return this.getRules(true);
14075 cacheStyleSheet : function(stylesheet){
14079 try{// try catch for cross domain access issue
14080 var ssRules = stylesheet.cssRules || stylesheet.rules;
14081 for(var j = ssRules.length-1; j >= 0; --j){
14082 rules[ssRules[j].selectorText] = ssRules[j];
14088 * Gets all css rules for the document
14089 * @param {Boolean} refreshCache true to refresh the internal cache
14090 * @return {Object} An object (hash) of rules indexed by selector
14092 getRules : function(refreshCache){
14093 if(rules == null || refreshCache){
14095 var ds = doc.styleSheets;
14096 for(var i =0, len = ds.length; i < len; i++){
14098 this.cacheStyleSheet(ds[i]);
14106 * Gets an an individual CSS rule by selector(s)
14107 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
14108 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
14109 * @return {CSSRule} The CSS rule or null if one is not found
14111 getRule : function(selector, refreshCache){
14112 var rs = this.getRules(refreshCache);
14113 if(!(selector instanceof Array)){
14114 return rs[selector];
14116 for(var i = 0; i < selector.length; i++){
14117 if(rs[selector[i]]){
14118 return rs[selector[i]];
14126 * Updates a rule property
14127 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14128 * @param {String} property The css property
14129 * @param {String} value The new value for the property
14130 * @return {Boolean} true If a rule was found and updated
14132 updateRule : function(selector, property, value){
14133 if(!(selector instanceof Array)){
14134 var rule = this.getRule(selector);
14136 rule.style[property.replace(camelRe, camelFn)] = value;
14140 for(var i = 0; i < selector.length; i++){
14141 if(this.updateRule(selector[i], property, value)){
14151 * Ext JS Library 1.1.1
14152 * Copyright(c) 2006-2007, Ext JS, LLC.
14154 * Originally Released Under LGPL - original licence link has changed is not relivant.
14157 * <script type="text/javascript">
14163 * @class Roo.util.ClickRepeater
14164 * @extends Roo.util.Observable
14166 * A wrapper class which can be applied to any element. Fires a "click" event while the
14167 * mouse is pressed. The interval between firings may be specified in the config but
14168 * defaults to 10 milliseconds.
14170 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14172 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14173 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14174 * Similar to an autorepeat key delay.
14175 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14176 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14177 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14178 * "interval" and "delay" are ignored. "immediate" is honored.
14179 * @cfg {Boolean} preventDefault True to prevent the default click event
14180 * @cfg {Boolean} stopDefault True to stop the default click event
14183 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14184 * 2007-02-02 jvs Renamed to ClickRepeater
14185 * 2007-02-03 jvs Modifications for FF Mac and Safari
14188 * @param {String/HTMLElement/Element} el The element to listen on
14189 * @param {Object} config
14191 Roo.util.ClickRepeater = function(el, config)
14193 this.el = Roo.get(el);
14194 this.el.unselectable();
14196 Roo.apply(this, config);
14201 * Fires when the mouse button is depressed.
14202 * @param {Roo.util.ClickRepeater} this
14204 "mousedown" : true,
14207 * Fires on a specified interval during the time the element is pressed.
14208 * @param {Roo.util.ClickRepeater} this
14213 * Fires when the mouse key is released.
14214 * @param {Roo.util.ClickRepeater} this
14219 this.el.on("mousedown", this.handleMouseDown, this);
14220 if(this.preventDefault || this.stopDefault){
14221 this.el.on("click", function(e){
14222 if(this.preventDefault){
14223 e.preventDefault();
14225 if(this.stopDefault){
14231 // allow inline handler
14233 this.on("click", this.handler, this.scope || this);
14236 Roo.util.ClickRepeater.superclass.constructor.call(this);
14239 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14242 preventDefault : true,
14243 stopDefault : false,
14247 handleMouseDown : function(){
14248 clearTimeout(this.timer);
14250 if(this.pressClass){
14251 this.el.addClass(this.pressClass);
14253 this.mousedownTime = new Date();
14255 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14256 this.el.on("mouseout", this.handleMouseOut, this);
14258 this.fireEvent("mousedown", this);
14259 this.fireEvent("click", this);
14261 this.timer = this.click.defer(this.delay || this.interval, this);
14265 click : function(){
14266 this.fireEvent("click", this);
14267 this.timer = this.click.defer(this.getInterval(), this);
14271 getInterval: function(){
14272 if(!this.accelerate){
14273 return this.interval;
14275 var pressTime = this.mousedownTime.getElapsed();
14276 if(pressTime < 500){
14278 }else if(pressTime < 1700){
14280 }else if(pressTime < 2600){
14282 }else if(pressTime < 3500){
14284 }else if(pressTime < 4400){
14286 }else if(pressTime < 5300){
14288 }else if(pressTime < 6200){
14296 handleMouseOut : function(){
14297 clearTimeout(this.timer);
14298 if(this.pressClass){
14299 this.el.removeClass(this.pressClass);
14301 this.el.on("mouseover", this.handleMouseReturn, this);
14305 handleMouseReturn : function(){
14306 this.el.un("mouseover", this.handleMouseReturn);
14307 if(this.pressClass){
14308 this.el.addClass(this.pressClass);
14314 handleMouseUp : function(){
14315 clearTimeout(this.timer);
14316 this.el.un("mouseover", this.handleMouseReturn);
14317 this.el.un("mouseout", this.handleMouseOut);
14318 Roo.get(document).un("mouseup", this.handleMouseUp);
14319 this.el.removeClass(this.pressClass);
14320 this.fireEvent("mouseup", this);
14324 * Ext JS Library 1.1.1
14325 * Copyright(c) 2006-2007, Ext JS, LLC.
14327 * Originally Released Under LGPL - original licence link has changed is not relivant.
14330 * <script type="text/javascript">
14335 * @class Roo.KeyNav
14336 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14337 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14338 * way to implement custom navigation schemes for any UI component.</p>
14339 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14340 * pageUp, pageDown, del, home, end. Usage:</p>
14342 var nav = new Roo.KeyNav("my-element", {
14343 "left" : function(e){
14344 this.moveLeft(e.ctrlKey);
14346 "right" : function(e){
14347 this.moveRight(e.ctrlKey);
14349 "enter" : function(e){
14356 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14357 * @param {Object} config The config
14359 Roo.KeyNav = function(el, config){
14360 this.el = Roo.get(el);
14361 Roo.apply(this, config);
14362 if(!this.disabled){
14363 this.disabled = true;
14368 Roo.KeyNav.prototype = {
14370 * @cfg {Boolean} disabled
14371 * True to disable this KeyNav instance (defaults to false)
14375 * @cfg {String} defaultEventAction
14376 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14377 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14378 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14380 defaultEventAction: "stopEvent",
14382 * @cfg {Boolean} forceKeyDown
14383 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14384 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14385 * handle keydown instead of keypress.
14387 forceKeyDown : false,
14390 prepareEvent : function(e){
14391 var k = e.getKey();
14392 var h = this.keyToHandler[k];
14393 //if(h && this[h]){
14394 // e.stopPropagation();
14396 if(Roo.isSafari && h && k >= 37 && k <= 40){
14402 relay : function(e){
14403 var k = e.getKey();
14404 var h = this.keyToHandler[k];
14406 if(this.doRelay(e, this[h], h) !== true){
14407 e[this.defaultEventAction]();
14413 doRelay : function(e, h, hname){
14414 return h.call(this.scope || this, e);
14417 // possible handlers
14431 // quick lookup hash
14448 * Enable this KeyNav
14450 enable: function(){
14452 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14453 // the EventObject will normalize Safari automatically
14454 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14455 this.el.on("keydown", this.relay, this);
14457 this.el.on("keydown", this.prepareEvent, this);
14458 this.el.on("keypress", this.relay, this);
14460 this.disabled = false;
14465 * Disable this KeyNav
14467 disable: function(){
14468 if(!this.disabled){
14469 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14470 this.el.un("keydown", this.relay);
14472 this.el.un("keydown", this.prepareEvent);
14473 this.el.un("keypress", this.relay);
14475 this.disabled = true;
14480 * Ext JS Library 1.1.1
14481 * Copyright(c) 2006-2007, Ext JS, LLC.
14483 * Originally Released Under LGPL - original licence link has changed is not relivant.
14486 * <script type="text/javascript">
14491 * @class Roo.KeyMap
14492 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14493 * The constructor accepts the same config object as defined by {@link #addBinding}.
14494 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14495 * combination it will call the function with this signature (if the match is a multi-key
14496 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14497 * A KeyMap can also handle a string representation of keys.<br />
14500 // map one key by key code
14501 var map = new Roo.KeyMap("my-element", {
14502 key: 13, // or Roo.EventObject.ENTER
14507 // map multiple keys to one action by string
14508 var map = new Roo.KeyMap("my-element", {
14514 // map multiple keys to multiple actions by strings and array of codes
14515 var map = new Roo.KeyMap("my-element", [
14518 fn: function(){ alert("Return was pressed"); }
14521 fn: function(){ alert('a, b or c was pressed'); }
14526 fn: function(){ alert('Control + shift + tab was pressed.'); }
14530 * <b>Note: A KeyMap starts enabled</b>
14532 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14533 * @param {Object} config The config (see {@link #addBinding})
14534 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14536 Roo.KeyMap = function(el, config, eventName){
14537 this.el = Roo.get(el);
14538 this.eventName = eventName || "keydown";
14539 this.bindings = [];
14541 this.addBinding(config);
14546 Roo.KeyMap.prototype = {
14548 * True to stop the event from bubbling and prevent the default browser action if the
14549 * key was handled by the KeyMap (defaults to false)
14555 * Add a new binding to this KeyMap. The following config object properties are supported:
14557 Property Type Description
14558 ---------- --------------- ----------------------------------------------------------------------
14559 key String/Array A single keycode or an array of keycodes to handle
14560 shift Boolean True to handle key only when shift is pressed (defaults to false)
14561 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14562 alt Boolean True to handle key only when alt is pressed (defaults to false)
14563 fn Function The function to call when KeyMap finds the expected key combination
14564 scope Object The scope of the callback function
14570 var map = new Roo.KeyMap(document, {
14571 key: Roo.EventObject.ENTER,
14576 //Add a new binding to the existing KeyMap later
14584 * @param {Object/Array} config A single KeyMap config or an array of configs
14586 addBinding : function(config){
14587 if(config instanceof Array){
14588 for(var i = 0, len = config.length; i < len; i++){
14589 this.addBinding(config[i]);
14593 var keyCode = config.key,
14594 shift = config.shift,
14595 ctrl = config.ctrl,
14598 scope = config.scope;
14599 if(typeof keyCode == "string"){
14601 var keyString = keyCode.toUpperCase();
14602 for(var j = 0, len = keyString.length; j < len; j++){
14603 ks.push(keyString.charCodeAt(j));
14607 var keyArray = keyCode instanceof Array;
14608 var handler = function(e){
14609 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14610 var k = e.getKey();
14612 for(var i = 0, len = keyCode.length; i < len; i++){
14613 if(keyCode[i] == k){
14614 if(this.stopEvent){
14617 fn.call(scope || window, k, e);
14623 if(this.stopEvent){
14626 fn.call(scope || window, k, e);
14631 this.bindings.push(handler);
14635 * Shorthand for adding a single key listener
14636 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14637 * following options:
14638 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14639 * @param {Function} fn The function to call
14640 * @param {Object} scope (optional) The scope of the function
14642 on : function(key, fn, scope){
14643 var keyCode, shift, ctrl, alt;
14644 if(typeof key == "object" && !(key instanceof Array)){
14663 handleKeyDown : function(e){
14664 if(this.enabled){ //just in case
14665 var b = this.bindings;
14666 for(var i = 0, len = b.length; i < len; i++){
14667 b[i].call(this, e);
14673 * Returns true if this KeyMap is enabled
14674 * @return {Boolean}
14676 isEnabled : function(){
14677 return this.enabled;
14681 * Enables this KeyMap
14683 enable: function(){
14685 this.el.on(this.eventName, this.handleKeyDown, this);
14686 this.enabled = true;
14691 * Disable this KeyMap
14693 disable: function(){
14695 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14696 this.enabled = false;
14701 * Ext JS Library 1.1.1
14702 * Copyright(c) 2006-2007, Ext JS, LLC.
14704 * Originally Released Under LGPL - original licence link has changed is not relivant.
14707 * <script type="text/javascript">
14712 * @class Roo.util.TextMetrics
14713 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14714 * wide, in pixels, a given block of text will be.
14717 Roo.util.TextMetrics = function(){
14721 * Measures the size of the specified text
14722 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14723 * that can affect the size of the rendered text
14724 * @param {String} text The text to measure
14725 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14726 * in order to accurately measure the text height
14727 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14729 measure : function(el, text, fixedWidth){
14731 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14734 shared.setFixedWidth(fixedWidth || 'auto');
14735 return shared.getSize(text);
14739 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14740 * the overhead of multiple calls to initialize the style properties on each measurement.
14741 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14742 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14743 * in order to accurately measure the text height
14744 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14746 createInstance : function(el, fixedWidth){
14747 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14754 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14755 var ml = new Roo.Element(document.createElement('div'));
14756 document.body.appendChild(ml.dom);
14757 ml.position('absolute');
14758 ml.setLeftTop(-1000, -1000);
14762 ml.setWidth(fixedWidth);
14767 * Returns the size of the specified text based on the internal element's style and width properties
14768 * @memberOf Roo.util.TextMetrics.Instance#
14769 * @param {String} text The text to measure
14770 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14772 getSize : function(text){
14774 var s = ml.getSize();
14780 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14781 * that can affect the size of the rendered text
14782 * @memberOf Roo.util.TextMetrics.Instance#
14783 * @param {String/HTMLElement} el The element, dom node or id
14785 bind : function(el){
14787 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14792 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14793 * to set a fixed width in order to accurately measure the text height.
14794 * @memberOf Roo.util.TextMetrics.Instance#
14795 * @param {Number} width The width to set on the element
14797 setFixedWidth : function(width){
14798 ml.setWidth(width);
14802 * Returns the measured width of the specified text
14803 * @memberOf Roo.util.TextMetrics.Instance#
14804 * @param {String} text The text to measure
14805 * @return {Number} width The width in pixels
14807 getWidth : function(text){
14808 ml.dom.style.width = 'auto';
14809 return this.getSize(text).width;
14813 * Returns the measured height of the specified text. For multiline text, be sure to call
14814 * {@link #setFixedWidth} if necessary.
14815 * @memberOf Roo.util.TextMetrics.Instance#
14816 * @param {String} text The text to measure
14817 * @return {Number} height The height in pixels
14819 getHeight : function(text){
14820 return this.getSize(text).height;
14824 instance.bind(bindTo);
14829 // backwards compat
14830 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14832 * Ext JS Library 1.1.1
14833 * Copyright(c) 2006-2007, Ext JS, LLC.
14835 * Originally Released Under LGPL - original licence link has changed is not relivant.
14838 * <script type="text/javascript">
14842 * @class Roo.state.Provider
14843 * Abstract base class for state provider implementations. This class provides methods
14844 * for encoding and decoding <b>typed</b> variables including dates and defines the
14845 * Provider interface.
14847 Roo.state.Provider = function(){
14849 * @event statechange
14850 * Fires when a state change occurs.
14851 * @param {Provider} this This state provider
14852 * @param {String} key The state key which was changed
14853 * @param {String} value The encoded value for the state
14856 "statechange": true
14859 Roo.state.Provider.superclass.constructor.call(this);
14861 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14863 * Returns the current value for a key
14864 * @param {String} name The key name
14865 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14866 * @return {Mixed} The state data
14868 get : function(name, defaultValue){
14869 return typeof this.state[name] == "undefined" ?
14870 defaultValue : this.state[name];
14874 * Clears a value from the state
14875 * @param {String} name The key name
14877 clear : function(name){
14878 delete this.state[name];
14879 this.fireEvent("statechange", this, name, null);
14883 * Sets the value for a key
14884 * @param {String} name The key name
14885 * @param {Mixed} value The value to set
14887 set : function(name, value){
14888 this.state[name] = value;
14889 this.fireEvent("statechange", this, name, value);
14893 * Decodes a string previously encoded with {@link #encodeValue}.
14894 * @param {String} value The value to decode
14895 * @return {Mixed} The decoded value
14897 decodeValue : function(cookie){
14898 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14899 var matches = re.exec(unescape(cookie));
14900 if(!matches || !matches[1]) {
14901 return; // non state cookie
14903 var type = matches[1];
14904 var v = matches[2];
14907 return parseFloat(v);
14909 return new Date(Date.parse(v));
14914 var values = v.split("^");
14915 for(var i = 0, len = values.length; i < len; i++){
14916 all.push(this.decodeValue(values[i]));
14921 var values = v.split("^");
14922 for(var i = 0, len = values.length; i < len; i++){
14923 var kv = values[i].split("=");
14924 all[kv[0]] = this.decodeValue(kv[1]);
14933 * Encodes a value including type information. Decode with {@link #decodeValue}.
14934 * @param {Mixed} value The value to encode
14935 * @return {String} The encoded value
14937 encodeValue : function(v){
14939 if(typeof v == "number"){
14941 }else if(typeof v == "boolean"){
14942 enc = "b:" + (v ? "1" : "0");
14943 }else if(v instanceof Date){
14944 enc = "d:" + v.toGMTString();
14945 }else if(v instanceof Array){
14947 for(var i = 0, len = v.length; i < len; i++){
14948 flat += this.encodeValue(v[i]);
14954 }else if(typeof v == "object"){
14957 if(typeof v[key] != "function"){
14958 flat += key + "=" + this.encodeValue(v[key]) + "^";
14961 enc = "o:" + flat.substring(0, flat.length-1);
14965 return escape(enc);
14971 * Ext JS Library 1.1.1
14972 * Copyright(c) 2006-2007, Ext JS, LLC.
14974 * Originally Released Under LGPL - original licence link has changed is not relivant.
14977 * <script type="text/javascript">
14980 * @class Roo.state.Manager
14981 * This is the global state manager. By default all components that are "state aware" check this class
14982 * for state information if you don't pass them a custom state provider. In order for this class
14983 * to be useful, it must be initialized with a provider when your application initializes.
14985 // in your initialization function
14987 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14989 // supposed you have a {@link Roo.BorderLayout}
14990 var layout = new Roo.BorderLayout(...);
14991 layout.restoreState();
14992 // or a {Roo.BasicDialog}
14993 var dialog = new Roo.BasicDialog(...);
14994 dialog.restoreState();
14998 Roo.state.Manager = function(){
14999 var provider = new Roo.state.Provider();
15003 * Configures the default state provider for your application
15004 * @param {Provider} stateProvider The state provider to set
15006 setProvider : function(stateProvider){
15007 provider = stateProvider;
15011 * Returns the current value for a key
15012 * @param {String} name The key name
15013 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
15014 * @return {Mixed} The state data
15016 get : function(key, defaultValue){
15017 return provider.get(key, defaultValue);
15021 * Sets the value for a key
15022 * @param {String} name The key name
15023 * @param {Mixed} value The state data
15025 set : function(key, value){
15026 provider.set(key, value);
15030 * Clears a value from the state
15031 * @param {String} name The key name
15033 clear : function(key){
15034 provider.clear(key);
15038 * Gets the currently configured state provider
15039 * @return {Provider} The state provider
15041 getProvider : function(){
15048 * Ext JS Library 1.1.1
15049 * Copyright(c) 2006-2007, Ext JS, LLC.
15051 * Originally Released Under LGPL - original licence link has changed is not relivant.
15054 * <script type="text/javascript">
15057 * @class Roo.state.CookieProvider
15058 * @extends Roo.state.Provider
15059 * The default Provider implementation which saves state via cookies.
15062 var cp = new Roo.state.CookieProvider({
15064 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
15065 domain: "roojs.com"
15067 Roo.state.Manager.setProvider(cp);
15069 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
15070 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
15071 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
15072 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
15073 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
15074 * domain the page is running on including the 'www' like 'www.roojs.com')
15075 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
15077 * Create a new CookieProvider
15078 * @param {Object} config The configuration object
15080 Roo.state.CookieProvider = function(config){
15081 Roo.state.CookieProvider.superclass.constructor.call(this);
15083 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
15084 this.domain = null;
15085 this.secure = false;
15086 Roo.apply(this, config);
15087 this.state = this.readCookies();
15090 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
15092 set : function(name, value){
15093 if(typeof value == "undefined" || value === null){
15097 this.setCookie(name, value);
15098 Roo.state.CookieProvider.superclass.set.call(this, name, value);
15102 clear : function(name){
15103 this.clearCookie(name);
15104 Roo.state.CookieProvider.superclass.clear.call(this, name);
15108 readCookies : function(){
15110 var c = document.cookie + ";";
15111 var re = /\s?(.*?)=(.*?);/g;
15113 while((matches = re.exec(c)) != null){
15114 var name = matches[1];
15115 var value = matches[2];
15116 if(name && name.substring(0,3) == "ys-"){
15117 cookies[name.substr(3)] = this.decodeValue(value);
15124 setCookie : function(name, value){
15125 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15126 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15127 ((this.path == null) ? "" : ("; path=" + this.path)) +
15128 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15129 ((this.secure == true) ? "; secure" : "");
15133 clearCookie : function(name){
15134 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15135 ((this.path == null) ? "" : ("; path=" + this.path)) +
15136 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15137 ((this.secure == true) ? "; secure" : "");
15141 * Ext JS Library 1.1.1
15142 * Copyright(c) 2006-2007, Ext JS, LLC.
15144 * Originally Released Under LGPL - original licence link has changed is not relivant.
15147 * <script type="text/javascript">
15152 * @class Roo.ComponentMgr
15153 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15156 Roo.ComponentMgr = function(){
15157 var all = new Roo.util.MixedCollection();
15161 * Registers a component.
15162 * @param {Roo.Component} c The component
15164 register : function(c){
15169 * Unregisters a component.
15170 * @param {Roo.Component} c The component
15172 unregister : function(c){
15177 * Returns a component by id
15178 * @param {String} id The component id
15180 get : function(id){
15181 return all.get(id);
15185 * Registers a function that will be called when a specified component is added to ComponentMgr
15186 * @param {String} id The component id
15187 * @param {Funtction} fn The callback function
15188 * @param {Object} scope The scope of the callback
15190 onAvailable : function(id, fn, scope){
15191 all.on("add", function(index, o){
15193 fn.call(scope || o, o);
15194 all.un("add", fn, scope);
15201 * Ext JS Library 1.1.1
15202 * Copyright(c) 2006-2007, Ext JS, LLC.
15204 * Originally Released Under LGPL - original licence link has changed is not relivant.
15207 * <script type="text/javascript">
15211 * @class Roo.Component
15212 * @extends Roo.util.Observable
15213 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15214 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15215 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15216 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15217 * All visual components (widgets) that require rendering into a layout should subclass Component.
15219 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15220 * 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
15221 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15223 Roo.Component = function(config){
15224 config = config || {};
15225 if(config.tagName || config.dom || typeof config == "string"){ // element object
15226 config = {el: config, id: config.id || config};
15228 this.initialConfig = config;
15230 Roo.apply(this, config);
15234 * Fires after the component is disabled.
15235 * @param {Roo.Component} this
15240 * Fires after the component is enabled.
15241 * @param {Roo.Component} this
15245 * @event beforeshow
15246 * Fires before the component is shown. Return false to stop the show.
15247 * @param {Roo.Component} this
15252 * Fires after the component is shown.
15253 * @param {Roo.Component} this
15257 * @event beforehide
15258 * Fires before the component is hidden. Return false to stop the hide.
15259 * @param {Roo.Component} this
15264 * Fires after the component is hidden.
15265 * @param {Roo.Component} this
15269 * @event beforerender
15270 * Fires before the component is rendered. Return false to stop the render.
15271 * @param {Roo.Component} this
15273 beforerender : true,
15276 * Fires after the component is rendered.
15277 * @param {Roo.Component} this
15281 * @event beforedestroy
15282 * Fires before the component is destroyed. Return false to stop the destroy.
15283 * @param {Roo.Component} this
15285 beforedestroy : true,
15288 * Fires after the component is destroyed.
15289 * @param {Roo.Component} this
15294 this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
15296 Roo.ComponentMgr.register(this);
15297 Roo.Component.superclass.constructor.call(this);
15298 this.initComponent();
15299 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15300 this.render(this.renderTo);
15301 delete this.renderTo;
15306 Roo.Component.AUTO_ID = 1000;
15308 Roo.extend(Roo.Component, Roo.util.Observable, {
15310 * @scope Roo.Component.prototype
15312 * true if this component is hidden. Read-only.
15317 * true if this component is disabled. Read-only.
15322 * true if this component has been rendered. Read-only.
15326 /** @cfg {String} disableClass
15327 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15329 disabledClass : "x-item-disabled",
15330 /** @cfg {Boolean} allowDomMove
15331 * Whether the component can move the Dom node when rendering (defaults to true).
15333 allowDomMove : true,
15334 /** @cfg {String} hideMode (display|visibility)
15335 * How this component should hidden. Supported values are
15336 * "visibility" (css visibility), "offsets" (negative offset position) and
15337 * "display" (css display) - defaults to "display".
15339 hideMode: 'display',
15342 ctype : "Roo.Component",
15345 * @cfg {String} actionMode
15346 * which property holds the element that used for hide() / show() / disable() / enable()
15352 getActionEl : function(){
15353 return this[this.actionMode];
15356 initComponent : Roo.emptyFn,
15358 * If this is a lazy rendering component, render it to its container element.
15359 * @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.
15361 render : function(container, position){
15362 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15363 if(!container && this.el){
15364 this.el = Roo.get(this.el);
15365 container = this.el.dom.parentNode;
15366 this.allowDomMove = false;
15368 this.container = Roo.get(container);
15369 this.rendered = true;
15370 if(position !== undefined){
15371 if(typeof position == 'number'){
15372 position = this.container.dom.childNodes[position];
15374 position = Roo.getDom(position);
15377 this.onRender(this.container, position || null);
15379 this.el.addClass(this.cls);
15383 this.el.applyStyles(this.style);
15386 this.fireEvent("render", this);
15387 this.afterRender(this.container);
15399 // default function is not really useful
15400 onRender : function(ct, position){
15402 this.el = Roo.get(this.el);
15403 if(this.allowDomMove !== false){
15404 ct.dom.insertBefore(this.el.dom, position);
15410 getAutoCreate : function(){
15411 var cfg = typeof this.autoCreate == "object" ?
15412 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15413 if(this.id && !cfg.id){
15420 afterRender : Roo.emptyFn,
15423 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15424 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15426 destroy : function(){
15427 if(this.fireEvent("beforedestroy", this) !== false){
15428 this.purgeListeners();
15429 this.beforeDestroy();
15431 this.el.removeAllListeners();
15433 if(this.actionMode == "container"){
15434 this.container.remove();
15438 Roo.ComponentMgr.unregister(this);
15439 this.fireEvent("destroy", this);
15444 beforeDestroy : function(){
15449 onDestroy : function(){
15454 * Returns the underlying {@link Roo.Element}.
15455 * @return {Roo.Element} The element
15457 getEl : function(){
15462 * Returns the id of this component.
15465 getId : function(){
15470 * Try to focus this component.
15471 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15472 * @return {Roo.Component} this
15474 focus : function(selectText){
15477 if(selectText === true){
15478 this.el.dom.select();
15493 * Disable this component.
15494 * @return {Roo.Component} this
15496 disable : function(){
15500 this.disabled = true;
15501 this.fireEvent("disable", this);
15506 onDisable : function(){
15507 this.getActionEl().addClass(this.disabledClass);
15508 this.el.dom.disabled = true;
15512 * Enable this component.
15513 * @return {Roo.Component} this
15515 enable : function(){
15519 this.disabled = false;
15520 this.fireEvent("enable", this);
15525 onEnable : function(){
15526 this.getActionEl().removeClass(this.disabledClass);
15527 this.el.dom.disabled = false;
15531 * Convenience function for setting disabled/enabled by boolean.
15532 * @param {Boolean} disabled
15534 setDisabled : function(disabled){
15535 this[disabled ? "disable" : "enable"]();
15539 * Show this component.
15540 * @return {Roo.Component} this
15543 if(this.fireEvent("beforeshow", this) !== false){
15544 this.hidden = false;
15548 this.fireEvent("show", this);
15554 onShow : function(){
15555 var ae = this.getActionEl();
15556 if(this.hideMode == 'visibility'){
15557 ae.dom.style.visibility = "visible";
15558 }else if(this.hideMode == 'offsets'){
15559 ae.removeClass('x-hidden');
15561 ae.dom.style.display = "";
15566 * Hide this component.
15567 * @return {Roo.Component} this
15570 if(this.fireEvent("beforehide", this) !== false){
15571 this.hidden = true;
15575 this.fireEvent("hide", this);
15581 onHide : function(){
15582 var ae = this.getActionEl();
15583 if(this.hideMode == 'visibility'){
15584 ae.dom.style.visibility = "hidden";
15585 }else if(this.hideMode == 'offsets'){
15586 ae.addClass('x-hidden');
15588 ae.dom.style.display = "none";
15593 * Convenience function to hide or show this component by boolean.
15594 * @param {Boolean} visible True to show, false to hide
15595 * @return {Roo.Component} this
15597 setVisible: function(visible){
15607 * Returns true if this component is visible.
15609 isVisible : function(){
15610 return this.getActionEl().isVisible();
15613 cloneConfig : function(overrides){
15614 overrides = overrides || {};
15615 var id = overrides.id || Roo.id();
15616 var cfg = Roo.applyIf(overrides, this.initialConfig);
15617 cfg.id = id; // prevent dup id
15618 return new this.constructor(cfg);
15622 * Ext JS Library 1.1.1
15623 * Copyright(c) 2006-2007, Ext JS, LLC.
15625 * Originally Released Under LGPL - original licence link has changed is not relivant.
15628 * <script type="text/javascript">
15632 * @class Roo.BoxComponent
15633 * @extends Roo.Component
15634 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15635 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15636 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15637 * layout containers.
15639 * @param {Roo.Element/String/Object} config The configuration options.
15641 Roo.BoxComponent = function(config){
15642 Roo.Component.call(this, config);
15646 * Fires after the component is resized.
15647 * @param {Roo.Component} this
15648 * @param {Number} adjWidth The box-adjusted width that was set
15649 * @param {Number} adjHeight The box-adjusted height that was set
15650 * @param {Number} rawWidth The width that was originally specified
15651 * @param {Number} rawHeight The height that was originally specified
15656 * Fires after the component is moved.
15657 * @param {Roo.Component} this
15658 * @param {Number} x The new x position
15659 * @param {Number} y The new y position
15665 Roo.extend(Roo.BoxComponent, Roo.Component, {
15666 // private, set in afterRender to signify that the component has been rendered
15668 // private, used to defer height settings to subclasses
15669 deferHeight: false,
15670 /** @cfg {Number} width
15671 * width (optional) size of component
15673 /** @cfg {Number} height
15674 * height (optional) size of component
15678 * Sets the width and height of the component. This method fires the resize event. This method can accept
15679 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15680 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15681 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15682 * @return {Roo.BoxComponent} this
15684 setSize : function(w, h){
15685 // support for standard size objects
15686 if(typeof w == 'object'){
15691 if(!this.boxReady){
15697 // prevent recalcs when not needed
15698 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15701 this.lastSize = {width: w, height: h};
15703 var adj = this.adjustSize(w, h);
15704 var aw = adj.width, ah = adj.height;
15705 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15706 var rz = this.getResizeEl();
15707 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15708 rz.setSize(aw, ah);
15709 }else if(!this.deferHeight && ah !== undefined){
15711 }else if(aw !== undefined){
15714 this.onResize(aw, ah, w, h);
15715 this.fireEvent('resize', this, aw, ah, w, h);
15721 * Gets the current size of the component's underlying element.
15722 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15724 getSize : function(){
15725 return this.el.getSize();
15729 * Gets the current XY position of the component's underlying element.
15730 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15731 * @return {Array} The XY position of the element (e.g., [100, 200])
15733 getPosition : function(local){
15734 if(local === true){
15735 return [this.el.getLeft(true), this.el.getTop(true)];
15737 return this.xy || this.el.getXY();
15741 * Gets the current box measurements of the component's underlying element.
15742 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15743 * @returns {Object} box An object in the format {x, y, width, height}
15745 getBox : function(local){
15746 var s = this.el.getSize();
15748 s.x = this.el.getLeft(true);
15749 s.y = this.el.getTop(true);
15751 var xy = this.xy || this.el.getXY();
15759 * Sets the current box measurements of the component's underlying element.
15760 * @param {Object} box An object in the format {x, y, width, height}
15761 * @returns {Roo.BoxComponent} this
15763 updateBox : function(box){
15764 this.setSize(box.width, box.height);
15765 this.setPagePosition(box.x, box.y);
15770 getResizeEl : function(){
15771 return this.resizeEl || this.el;
15775 getPositionEl : function(){
15776 return this.positionEl || this.el;
15780 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15781 * This method fires the move event.
15782 * @param {Number} left The new left
15783 * @param {Number} top The new top
15784 * @returns {Roo.BoxComponent} this
15786 setPosition : function(x, y){
15789 if(!this.boxReady){
15792 var adj = this.adjustPosition(x, y);
15793 var ax = adj.x, ay = adj.y;
15795 var el = this.getPositionEl();
15796 if(ax !== undefined || ay !== undefined){
15797 if(ax !== undefined && ay !== undefined){
15798 el.setLeftTop(ax, ay);
15799 }else if(ax !== undefined){
15801 }else if(ay !== undefined){
15804 this.onPosition(ax, ay);
15805 this.fireEvent('move', this, ax, ay);
15811 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15812 * This method fires the move event.
15813 * @param {Number} x The new x position
15814 * @param {Number} y The new y position
15815 * @returns {Roo.BoxComponent} this
15817 setPagePosition : function(x, y){
15820 if(!this.boxReady){
15823 if(x === undefined || y === undefined){ // cannot translate undefined points
15826 var p = this.el.translatePoints(x, y);
15827 this.setPosition(p.left, p.top);
15832 onRender : function(ct, position){
15833 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15835 this.resizeEl = Roo.get(this.resizeEl);
15837 if(this.positionEl){
15838 this.positionEl = Roo.get(this.positionEl);
15843 afterRender : function(){
15844 Roo.BoxComponent.superclass.afterRender.call(this);
15845 this.boxReady = true;
15846 this.setSize(this.width, this.height);
15847 if(this.x || this.y){
15848 this.setPosition(this.x, this.y);
15850 if(this.pageX || this.pageY){
15851 this.setPagePosition(this.pageX, this.pageY);
15856 * Force the component's size to recalculate based on the underlying element's current height and width.
15857 * @returns {Roo.BoxComponent} this
15859 syncSize : function(){
15860 delete this.lastSize;
15861 this.setSize(this.el.getWidth(), this.el.getHeight());
15866 * Called after the component is resized, this method is empty by default but can be implemented by any
15867 * subclass that needs to perform custom logic after a resize occurs.
15868 * @param {Number} adjWidth The box-adjusted width that was set
15869 * @param {Number} adjHeight The box-adjusted height that was set
15870 * @param {Number} rawWidth The width that was originally specified
15871 * @param {Number} rawHeight The height that was originally specified
15873 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15878 * Called after the component is moved, this method is empty by default but can be implemented by any
15879 * subclass that needs to perform custom logic after a move occurs.
15880 * @param {Number} x The new x position
15881 * @param {Number} y The new y position
15883 onPosition : function(x, y){
15888 adjustSize : function(w, h){
15889 if(this.autoWidth){
15892 if(this.autoHeight){
15895 return {width : w, height: h};
15899 adjustPosition : function(x, y){
15900 return {x : x, y: y};
15903 * Original code for Roojs - LGPL
15904 * <script type="text/javascript">
15908 * @class Roo.XComponent
15909 * A delayed Element creator...
15910 * Or a way to group chunks of interface together.
15911 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15912 * used in conjunction with XComponent.build() it will create an instance of each element,
15913 * then call addxtype() to build the User interface.
15915 * Mypart.xyx = new Roo.XComponent({
15917 parent : 'Mypart.xyz', // empty == document.element.!!
15921 disabled : function() {}
15923 tree : function() { // return an tree of xtype declared components
15927 xtype : 'NestedLayoutPanel',
15934 * It can be used to build a big heiracy, with parent etc.
15935 * or you can just use this to render a single compoent to a dom element
15936 * MYPART.render(Roo.Element | String(id) | dom_element )
15943 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15944 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15946 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15948 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15949 * - if mulitple topModules exist, the last one is defined as the top module.
15953 * When the top level or multiple modules are to embedded into a existing HTML page,
15954 * the parent element can container '#id' of the element where the module will be drawn.
15958 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15959 * it relies more on a include mechanism, where sub modules are included into an outer page.
15960 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15962 * Bootstrap Roo Included elements
15964 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15965 * hence confusing the component builder as it thinks there are multiple top level elements.
15969 * @extends Roo.util.Observable
15971 * @param cfg {Object} configuration of component
15974 Roo.XComponent = function(cfg) {
15975 Roo.apply(this, cfg);
15979 * Fires when this the componnt is built
15980 * @param {Roo.XComponent} c the component
15985 this.region = this.region || 'center'; // default..
15986 Roo.XComponent.register(this);
15987 this.modules = false;
15988 this.el = false; // where the layout goes..
15992 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15995 * The created element (with Roo.factory())
15996 * @type {Roo.Layout}
16002 * for BC - use el in new code
16003 * @type {Roo.Layout}
16009 * for BC - use el in new code
16010 * @type {Roo.Layout}
16015 * @cfg {Function|boolean} disabled
16016 * If this module is disabled by some rule, return true from the funtion
16021 * @cfg {String} parent
16022 * Name of parent element which it get xtype added to..
16027 * @cfg {String} order
16028 * Used to set the order in which elements are created (usefull for multiple tabs)
16033 * @cfg {String} name
16034 * String to display while loading.
16038 * @cfg {String} region
16039 * Region to render component to (defaults to center)
16044 * @cfg {Array} items
16045 * A single item array - the first element is the root of the tree..
16046 * It's done this way to stay compatible with the Xtype system...
16052 * The method that retuns the tree of parts that make up this compoennt
16059 * render element to dom or tree
16060 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
16063 render : function(el)
16067 var hp = this.parent ? 1 : 0;
16068 Roo.debug && Roo.log(this);
16070 var tree = this._tree ? this._tree() : this.tree();
16073 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
16074 // if parent is a '#.....' string, then let's use that..
16075 var ename = this.parent.substr(1);
16076 this.parent = false;
16077 Roo.debug && Roo.log(ename);
16079 case 'bootstrap-body':
16080 if (typeof(tree.el) != 'undefined' && tree.el == document.body) {
16081 // this is the BorderLayout standard?
16082 this.parent = { el : true };
16085 if (["Nest", "Content", "Grid", "Tree"].indexOf(tree.xtype) > -1) {
16086 // need to insert stuff...
16088 el : new Roo.bootstrap.layout.Border({
16089 el : document.body,
16095 tabPosition: 'top',
16096 //resizeTabs: true,
16097 alwaysShowTabs: true,
16107 if (typeof(Roo.bootstrap.Body) != 'undefined' ) {
16108 this.parent = { el : new Roo.bootstrap.Body() };
16109 Roo.debug && Roo.log("setting el to doc body");
16112 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
16116 this.parent = { el : true};
16119 el = Roo.get(ename);
16120 if (typeof(Roo.bootstrap) != 'undefined' && tree['|xns'] == 'Roo.bootstrap') {
16121 this.parent = { el : true};
16128 if (!el && !this.parent) {
16129 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
16134 Roo.debug && Roo.log("EL:");
16135 Roo.debug && Roo.log(el);
16136 Roo.debug && Roo.log("this.parent.el:");
16137 Roo.debug && Roo.log(this.parent.el);
16140 // altertive root elements ??? - we need a better way to indicate these.
16141 var is_alt = Roo.XComponent.is_alt ||
16142 (typeof(tree.el) != 'undefined' && tree.el == document.body) ||
16143 (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
16144 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
16148 if (!this.parent && is_alt) {
16149 //el = Roo.get(document.body);
16150 this.parent = { el : true };
16155 if (!this.parent) {
16157 Roo.debug && Roo.log("no parent - creating one");
16159 el = el ? Roo.get(el) : false;
16161 if (typeof(Roo.BorderLayout) == 'undefined' ) {
16164 el : new Roo.bootstrap.layout.Border({
16165 el: el || document.body,
16171 tabPosition: 'top',
16172 //resizeTabs: true,
16173 alwaysShowTabs: false,
16176 overflow: 'visible'
16182 // it's a top level one..
16184 el : new Roo.BorderLayout(el || document.body, {
16189 tabPosition: 'top',
16190 //resizeTabs: true,
16191 alwaysShowTabs: el && hp? false : true,
16192 hideTabs: el || !hp ? true : false,
16200 if (!this.parent.el) {
16201 // probably an old style ctor, which has been disabled.
16205 // The 'tree' method is '_tree now'
16207 tree.region = tree.region || this.region;
16208 var is_body = false;
16209 if (this.parent.el === true) {
16210 // bootstrap... - body..
16214 this.parent.el = Roo.factory(tree);
16218 this.el = this.parent.el.addxtype(tree, undefined, is_body);
16219 this.fireEvent('built', this);
16221 this.panel = this.el;
16222 this.layout = this.panel.layout;
16223 this.parentLayout = this.parent.layout || false;
16229 Roo.apply(Roo.XComponent, {
16231 * @property hideProgress
16232 * true to disable the building progress bar.. usefull on single page renders.
16235 hideProgress : false,
16237 * @property buildCompleted
16238 * True when the builder has completed building the interface.
16241 buildCompleted : false,
16244 * @property topModule
16245 * the upper most module - uses document.element as it's constructor.
16252 * @property modules
16253 * array of modules to be created by registration system.
16254 * @type {Array} of Roo.XComponent
16259 * @property elmodules
16260 * array of modules to be created by which use #ID
16261 * @type {Array} of Roo.XComponent
16268 * Is an alternative Root - normally used by bootstrap or other systems,
16269 * where the top element in the tree can wrap 'body'
16270 * @type {boolean} (default false)
16275 * @property build_from_html
16276 * Build elements from html - used by bootstrap HTML stuff
16277 * - this is cleared after build is completed
16278 * @type {boolean} (default false)
16281 build_from_html : false,
16283 * Register components to be built later.
16285 * This solves the following issues
16286 * - Building is not done on page load, but after an authentication process has occured.
16287 * - Interface elements are registered on page load
16288 * - Parent Interface elements may not be loaded before child, so this handles that..
16295 module : 'Pman.Tab.projectMgr',
16297 parent : 'Pman.layout',
16298 disabled : false, // or use a function..
16301 * * @param {Object} details about module
16303 register : function(obj) {
16305 Roo.XComponent.event.fireEvent('register', obj);
16306 switch(typeof(obj.disabled) ) {
16312 if ( obj.disabled() ) {
16318 if (obj.disabled) {
16324 this.modules.push(obj);
16328 * convert a string to an object..
16329 * eg. 'AAA.BBB' -> finds AAA.BBB
16333 toObject : function(str)
16335 if (!str || typeof(str) == 'object') {
16338 if (str.substring(0,1) == '#') {
16342 var ar = str.split('.');
16347 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16349 throw "Module not found : " + str;
16353 throw "Module not found : " + str;
16355 Roo.each(ar, function(e) {
16356 if (typeof(o[e]) == 'undefined') {
16357 throw "Module not found : " + str;
16368 * move modules into their correct place in the tree..
16371 preBuild : function ()
16374 Roo.each(this.modules , function (obj)
16376 Roo.XComponent.event.fireEvent('beforebuild', obj);
16378 var opar = obj.parent;
16380 obj.parent = this.toObject(opar);
16382 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16387 Roo.debug && Roo.log("GOT top level module");
16388 Roo.debug && Roo.log(obj);
16389 obj.modules = new Roo.util.MixedCollection(false,
16390 function(o) { return o.order + '' }
16392 this.topModule = obj;
16395 // parent is a string (usually a dom element name..)
16396 if (typeof(obj.parent) == 'string') {
16397 this.elmodules.push(obj);
16400 if (obj.parent.constructor != Roo.XComponent) {
16401 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16403 if (!obj.parent.modules) {
16404 obj.parent.modules = new Roo.util.MixedCollection(false,
16405 function(o) { return o.order + '' }
16408 if (obj.parent.disabled) {
16409 obj.disabled = true;
16411 obj.parent.modules.add(obj);
16416 * make a list of modules to build.
16417 * @return {Array} list of modules.
16420 buildOrder : function()
16423 var cmp = function(a,b) {
16424 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16426 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16427 throw "No top level modules to build";
16430 // make a flat list in order of modules to build.
16431 var mods = this.topModule ? [ this.topModule ] : [];
16434 // elmodules (is a list of DOM based modules )
16435 Roo.each(this.elmodules, function(e) {
16437 if (!this.topModule &&
16438 typeof(e.parent) == 'string' &&
16439 e.parent.substring(0,1) == '#' &&
16440 Roo.get(e.parent.substr(1))
16443 _this.topModule = e;
16449 // add modules to their parents..
16450 var addMod = function(m) {
16451 Roo.debug && Roo.log("build Order: add: " + m.name);
16454 if (m.modules && !m.disabled) {
16455 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16456 m.modules.keySort('ASC', cmp );
16457 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16459 m.modules.each(addMod);
16461 Roo.debug && Roo.log("build Order: no child modules");
16463 // not sure if this is used any more..
16465 m.finalize.name = m.name + " (clean up) ";
16466 mods.push(m.finalize);
16470 if (this.topModule && this.topModule.modules) {
16471 this.topModule.modules.keySort('ASC', cmp );
16472 this.topModule.modules.each(addMod);
16478 * Build the registered modules.
16479 * @param {Object} parent element.
16480 * @param {Function} optional method to call after module has been added.
16484 build : function(opts)
16487 if (typeof(opts) != 'undefined') {
16488 Roo.apply(this,opts);
16492 var mods = this.buildOrder();
16494 //this.allmods = mods;
16495 //Roo.debug && Roo.log(mods);
16497 if (!mods.length) { // should not happen
16498 throw "NO modules!!!";
16502 var msg = "Building Interface...";
16503 // flash it up as modal - so we store the mask!?
16504 if (!this.hideProgress && Roo.MessageBox) {
16505 Roo.MessageBox.show({ title: 'loading' });
16506 Roo.MessageBox.show({
16507 title: "Please wait...",
16516 var total = mods.length;
16519 var progressRun = function() {
16520 if (!mods.length) {
16521 Roo.debug && Roo.log('hide?');
16522 if (!this.hideProgress && Roo.MessageBox) {
16523 Roo.MessageBox.hide();
16525 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16527 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16533 var m = mods.shift();
16536 Roo.debug && Roo.log(m);
16537 // not sure if this is supported any more.. - modules that are are just function
16538 if (typeof(m) == 'function') {
16540 return progressRun.defer(10, _this);
16544 msg = "Building Interface " + (total - mods.length) +
16546 (m.name ? (' - ' + m.name) : '');
16547 Roo.debug && Roo.log(msg);
16548 if (!_this.hideProgress && Roo.MessageBox) {
16549 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16553 // is the module disabled?
16554 var disabled = (typeof(m.disabled) == 'function') ?
16555 m.disabled.call(m.module.disabled) : m.disabled;
16559 return progressRun(); // we do not update the display!
16567 // it's 10 on top level, and 1 on others??? why...
16568 return progressRun.defer(10, _this);
16571 progressRun.defer(1, _this);
16585 * wrapper for event.on - aliased later..
16586 * Typically use to register a event handler for register:
16588 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16597 Roo.XComponent.event = new Roo.util.Observable({
16601 * Fires when an Component is registered,
16602 * set the disable property on the Component to stop registration.
16603 * @param {Roo.XComponent} c the component being registerd.
16608 * @event beforebuild
16609 * Fires before each Component is built
16610 * can be used to apply permissions.
16611 * @param {Roo.XComponent} c the component being registerd.
16614 'beforebuild' : true,
16616 * @event buildcomplete
16617 * Fires on the top level element when all elements have been built
16618 * @param {Roo.XComponent} the top level component.
16620 'buildcomplete' : true
16625 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);
16628 * marked - a markdown parser
16629 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
16630 * https://github.com/chjj/marked
16636 * Roo.Markdown - is a very crude wrapper around marked..
16640 * alert( Roo.Markdown.toHtml("Markdown *rocks*.") );
16642 * Note: move the sample code to the bottom of this
16643 * file before uncommenting it.
16648 Roo.Markdown.toHtml = function(text) {
16650 var c = new Roo.Markdown.marked.setOptions({
16651 renderer: new Roo.Markdown.marked.Renderer(),
16662 text = text.replace(/\\\n/g,' ');
16663 return Roo.Markdown.marked(text);
16668 // Wraps all "globals" so that the only thing
16669 // exposed is makeHtml().
16674 * Block-Level Grammar
16679 code: /^( {4}[^\n]+\n*)+/,
16681 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
16682 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
16684 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
16685 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
16686 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
16687 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
16688 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
16690 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
16694 block.bullet = /(?:[*+-]|\d+\.)/;
16695 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
16696 block.item = replace(block.item, 'gm')
16697 (/bull/g, block.bullet)
16700 block.list = replace(block.list)
16701 (/bull/g, block.bullet)
16702 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
16703 ('def', '\\n+(?=' + block.def.source + ')')
16706 block.blockquote = replace(block.blockquote)
16710 block._tag = '(?!(?:'
16711 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
16712 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
16713 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
16715 block.html = replace(block.html)
16716 ('comment', /<!--[\s\S]*?-->/)
16717 ('closed', /<(tag)[\s\S]+?<\/\1>/)
16718 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
16719 (/tag/g, block._tag)
16722 block.paragraph = replace(block.paragraph)
16724 ('heading', block.heading)
16725 ('lheading', block.lheading)
16726 ('blockquote', block.blockquote)
16727 ('tag', '<' + block._tag)
16732 * Normal Block Grammar
16735 block.normal = merge({}, block);
16738 * GFM Block Grammar
16741 block.gfm = merge({}, block.normal, {
16742 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
16744 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
16747 block.gfm.paragraph = replace(block.paragraph)
16749 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
16750 + block.list.source.replace('\\1', '\\3') + '|')
16754 * GFM + Tables Block Grammar
16757 block.tables = merge({}, block.gfm, {
16758 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
16759 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
16766 function Lexer(options) {
16768 this.tokens.links = {};
16769 this.options = options || marked.defaults;
16770 this.rules = block.normal;
16772 if (this.options.gfm) {
16773 if (this.options.tables) {
16774 this.rules = block.tables;
16776 this.rules = block.gfm;
16782 * Expose Block Rules
16785 Lexer.rules = block;
16788 * Static Lex Method
16791 Lexer.lex = function(src, options) {
16792 var lexer = new Lexer(options);
16793 return lexer.lex(src);
16800 Lexer.prototype.lex = function(src) {
16802 .replace(/\r\n|\r/g, '\n')
16803 .replace(/\t/g, ' ')
16804 .replace(/\u00a0/g, ' ')
16805 .replace(/\u2424/g, '\n');
16807 return this.token(src, true);
16814 Lexer.prototype.token = function(src, top, bq) {
16815 var src = src.replace(/^ +$/gm, '')
16828 if (cap = this.rules.newline.exec(src)) {
16829 src = src.substring(cap[0].length);
16830 if (cap[0].length > 1) {
16838 if (cap = this.rules.code.exec(src)) {
16839 src = src.substring(cap[0].length);
16840 cap = cap[0].replace(/^ {4}/gm, '');
16843 text: !this.options.pedantic
16844 ? cap.replace(/\n+$/, '')
16851 if (cap = this.rules.fences.exec(src)) {
16852 src = src.substring(cap[0].length);
16862 if (cap = this.rules.heading.exec(src)) {
16863 src = src.substring(cap[0].length);
16866 depth: cap[1].length,
16872 // table no leading pipe (gfm)
16873 if (top && (cap = this.rules.nptable.exec(src))) {
16874 src = src.substring(cap[0].length);
16878 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
16879 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
16880 cells: cap[3].replace(/\n$/, '').split('\n')
16883 for (i = 0; i < item.align.length; i++) {
16884 if (/^ *-+: *$/.test(item.align[i])) {
16885 item.align[i] = 'right';
16886 } else if (/^ *:-+: *$/.test(item.align[i])) {
16887 item.align[i] = 'center';
16888 } else if (/^ *:-+ *$/.test(item.align[i])) {
16889 item.align[i] = 'left';
16891 item.align[i] = null;
16895 for (i = 0; i < item.cells.length; i++) {
16896 item.cells[i] = item.cells[i].split(/ *\| */);
16899 this.tokens.push(item);
16905 if (cap = this.rules.lheading.exec(src)) {
16906 src = src.substring(cap[0].length);
16909 depth: cap[2] === '=' ? 1 : 2,
16916 if (cap = this.rules.hr.exec(src)) {
16917 src = src.substring(cap[0].length);
16925 if (cap = this.rules.blockquote.exec(src)) {
16926 src = src.substring(cap[0].length);
16929 type: 'blockquote_start'
16932 cap = cap[0].replace(/^ *> ?/gm, '');
16934 // Pass `top` to keep the current
16935 // "toplevel" state. This is exactly
16936 // how markdown.pl works.
16937 this.token(cap, top, true);
16940 type: 'blockquote_end'
16947 if (cap = this.rules.list.exec(src)) {
16948 src = src.substring(cap[0].length);
16952 type: 'list_start',
16953 ordered: bull.length > 1
16956 // Get each top-level item.
16957 cap = cap[0].match(this.rules.item);
16963 for (; i < l; i++) {
16966 // Remove the list item's bullet
16967 // so it is seen as the next token.
16968 space = item.length;
16969 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
16971 // Outdent whatever the
16972 // list item contains. Hacky.
16973 if (~item.indexOf('\n ')) {
16974 space -= item.length;
16975 item = !this.options.pedantic
16976 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
16977 : item.replace(/^ {1,4}/gm, '');
16980 // Determine whether the next list item belongs here.
16981 // Backpedal if it does not belong in this list.
16982 if (this.options.smartLists && i !== l - 1) {
16983 b = block.bullet.exec(cap[i + 1])[0];
16984 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
16985 src = cap.slice(i + 1).join('\n') + src;
16990 // Determine whether item is loose or not.
16991 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
16992 // for discount behavior.
16993 loose = next || /\n\n(?!\s*$)/.test(item);
16995 next = item.charAt(item.length - 1) === '\n';
16996 if (!loose) { loose = next; }
17001 ? 'loose_item_start'
17002 : 'list_item_start'
17006 this.token(item, false, bq);
17009 type: 'list_item_end'
17021 if (cap = this.rules.html.exec(src)) {
17022 src = src.substring(cap[0].length);
17024 type: this.options.sanitize
17027 pre: !this.options.sanitizer
17028 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
17035 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
17036 src = src.substring(cap[0].length);
17037 this.tokens.links[cap[1].toLowerCase()] = {
17045 if (top && (cap = this.rules.table.exec(src))) {
17046 src = src.substring(cap[0].length);
17050 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
17051 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
17052 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
17055 for (i = 0; i < item.align.length; i++) {
17056 if (/^ *-+: *$/.test(item.align[i])) {
17057 item.align[i] = 'right';
17058 } else if (/^ *:-+: *$/.test(item.align[i])) {
17059 item.align[i] = 'center';
17060 } else if (/^ *:-+ *$/.test(item.align[i])) {
17061 item.align[i] = 'left';
17063 item.align[i] = null;
17067 for (i = 0; i < item.cells.length; i++) {
17068 item.cells[i] = item.cells[i]
17069 .replace(/^ *\| *| *\| *$/g, '')
17073 this.tokens.push(item);
17078 // top-level paragraph
17079 if (top && (cap = this.rules.paragraph.exec(src))) {
17080 src = src.substring(cap[0].length);
17083 text: cap[1].charAt(cap[1].length - 1) === '\n'
17084 ? cap[1].slice(0, -1)
17091 if (cap = this.rules.text.exec(src)) {
17092 // Top-level should never reach here.
17093 src = src.substring(cap[0].length);
17103 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17107 return this.tokens;
17111 * Inline-Level Grammar
17115 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
17116 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
17118 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
17119 link: /^!?\[(inside)\]\(href\)/,
17120 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
17121 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
17122 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
17123 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
17124 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
17125 br: /^ {2,}\n(?!\s*$)/,
17127 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
17130 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
17131 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
17133 inline.link = replace(inline.link)
17134 ('inside', inline._inside)
17135 ('href', inline._href)
17138 inline.reflink = replace(inline.reflink)
17139 ('inside', inline._inside)
17143 * Normal Inline Grammar
17146 inline.normal = merge({}, inline);
17149 * Pedantic Inline Grammar
17152 inline.pedantic = merge({}, inline.normal, {
17153 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
17154 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
17158 * GFM Inline Grammar
17161 inline.gfm = merge({}, inline.normal, {
17162 escape: replace(inline.escape)('])', '~|])')(),
17163 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
17164 del: /^~~(?=\S)([\s\S]*?\S)~~/,
17165 text: replace(inline.text)
17167 ('|', '|https?://|')
17172 * GFM + Line Breaks Inline Grammar
17175 inline.breaks = merge({}, inline.gfm, {
17176 br: replace(inline.br)('{2,}', '*')(),
17177 text: replace(inline.gfm.text)('{2,}', '*')()
17181 * Inline Lexer & Compiler
17184 function InlineLexer(links, options) {
17185 this.options = options || marked.defaults;
17186 this.links = links;
17187 this.rules = inline.normal;
17188 this.renderer = this.options.renderer || new Renderer;
17189 this.renderer.options = this.options;
17193 Error('Tokens array requires a `links` property.');
17196 if (this.options.gfm) {
17197 if (this.options.breaks) {
17198 this.rules = inline.breaks;
17200 this.rules = inline.gfm;
17202 } else if (this.options.pedantic) {
17203 this.rules = inline.pedantic;
17208 * Expose Inline Rules
17211 InlineLexer.rules = inline;
17214 * Static Lexing/Compiling Method
17217 InlineLexer.output = function(src, links, options) {
17218 var inline = new InlineLexer(links, options);
17219 return inline.output(src);
17226 InlineLexer.prototype.output = function(src) {
17235 if (cap = this.rules.escape.exec(src)) {
17236 src = src.substring(cap[0].length);
17242 if (cap = this.rules.autolink.exec(src)) {
17243 src = src.substring(cap[0].length);
17244 if (cap[2] === '@') {
17245 text = cap[1].charAt(6) === ':'
17246 ? this.mangle(cap[1].substring(7))
17247 : this.mangle(cap[1]);
17248 href = this.mangle('mailto:') + text;
17250 text = escape(cap[1]);
17253 out += this.renderer.link(href, null, text);
17258 if (!this.inLink && (cap = this.rules.url.exec(src))) {
17259 src = src.substring(cap[0].length);
17260 text = escape(cap[1]);
17262 out += this.renderer.link(href, null, text);
17267 if (cap = this.rules.tag.exec(src)) {
17268 if (!this.inLink && /^<a /i.test(cap[0])) {
17269 this.inLink = true;
17270 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
17271 this.inLink = false;
17273 src = src.substring(cap[0].length);
17274 out += this.options.sanitize
17275 ? this.options.sanitizer
17276 ? this.options.sanitizer(cap[0])
17283 if (cap = this.rules.link.exec(src)) {
17284 src = src.substring(cap[0].length);
17285 this.inLink = true;
17286 out += this.outputLink(cap, {
17290 this.inLink = false;
17295 if ((cap = this.rules.reflink.exec(src))
17296 || (cap = this.rules.nolink.exec(src))) {
17297 src = src.substring(cap[0].length);
17298 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
17299 link = this.links[link.toLowerCase()];
17300 if (!link || !link.href) {
17301 out += cap[0].charAt(0);
17302 src = cap[0].substring(1) + src;
17305 this.inLink = true;
17306 out += this.outputLink(cap, link);
17307 this.inLink = false;
17312 if (cap = this.rules.strong.exec(src)) {
17313 src = src.substring(cap[0].length);
17314 out += this.renderer.strong(this.output(cap[2] || cap[1]));
17319 if (cap = this.rules.em.exec(src)) {
17320 src = src.substring(cap[0].length);
17321 out += this.renderer.em(this.output(cap[2] || cap[1]));
17326 if (cap = this.rules.code.exec(src)) {
17327 src = src.substring(cap[0].length);
17328 out += this.renderer.codespan(escape(cap[2], true));
17333 if (cap = this.rules.br.exec(src)) {
17334 src = src.substring(cap[0].length);
17335 out += this.renderer.br();
17340 if (cap = this.rules.del.exec(src)) {
17341 src = src.substring(cap[0].length);
17342 out += this.renderer.del(this.output(cap[1]));
17347 if (cap = this.rules.text.exec(src)) {
17348 src = src.substring(cap[0].length);
17349 out += this.renderer.text(escape(this.smartypants(cap[0])));
17355 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17366 InlineLexer.prototype.outputLink = function(cap, link) {
17367 var href = escape(link.href)
17368 , title = link.title ? escape(link.title) : null;
17370 return cap[0].charAt(0) !== '!'
17371 ? this.renderer.link(href, title, this.output(cap[1]))
17372 : this.renderer.image(href, title, escape(cap[1]));
17376 * Smartypants Transformations
17379 InlineLexer.prototype.smartypants = function(text) {
17380 if (!this.options.smartypants) { return text; }
17383 .replace(/---/g, '\u2014')
17385 .replace(/--/g, '\u2013')
17387 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
17388 // closing singles & apostrophes
17389 .replace(/'/g, '\u2019')
17391 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
17393 .replace(/"/g, '\u201d')
17395 .replace(/\.{3}/g, '\u2026');
17402 InlineLexer.prototype.mangle = function(text) {
17403 if (!this.options.mangle) { return text; }
17409 for (; i < l; i++) {
17410 ch = text.charCodeAt(i);
17411 if (Math.random() > 0.5) {
17412 ch = 'x' + ch.toString(16);
17414 out += '&#' + ch + ';';
17424 function Renderer(options) {
17425 this.options = options || {};
17428 Renderer.prototype.code = function(code, lang, escaped) {
17429 if (this.options.highlight) {
17430 var out = this.options.highlight(code, lang);
17431 if (out != null && out !== code) {
17436 // hack!!! - it's already escapeD?
17441 return '<pre><code>'
17442 + (escaped ? code : escape(code, true))
17443 + '\n</code></pre>';
17446 return '<pre><code class="'
17447 + this.options.langPrefix
17448 + escape(lang, true)
17450 + (escaped ? code : escape(code, true))
17451 + '\n</code></pre>\n';
17454 Renderer.prototype.blockquote = function(quote) {
17455 return '<blockquote>\n' + quote + '</blockquote>\n';
17458 Renderer.prototype.html = function(html) {
17462 Renderer.prototype.heading = function(text, level, raw) {
17466 + this.options.headerPrefix
17467 + raw.toLowerCase().replace(/[^\w]+/g, '-')
17475 Renderer.prototype.hr = function() {
17476 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
17479 Renderer.prototype.list = function(body, ordered) {
17480 var type = ordered ? 'ol' : 'ul';
17481 return '<' + type + '>\n' + body + '</' + type + '>\n';
17484 Renderer.prototype.listitem = function(text) {
17485 return '<li>' + text + '</li>\n';
17488 Renderer.prototype.paragraph = function(text) {
17489 return '<p>' + text + '</p>\n';
17492 Renderer.prototype.table = function(header, body) {
17493 return '<table class="table table-striped">\n'
17503 Renderer.prototype.tablerow = function(content) {
17504 return '<tr>\n' + content + '</tr>\n';
17507 Renderer.prototype.tablecell = function(content, flags) {
17508 var type = flags.header ? 'th' : 'td';
17509 var tag = flags.align
17510 ? '<' + type + ' style="text-align:' + flags.align + '">'
17511 : '<' + type + '>';
17512 return tag + content + '</' + type + '>\n';
17515 // span level renderer
17516 Renderer.prototype.strong = function(text) {
17517 return '<strong>' + text + '</strong>';
17520 Renderer.prototype.em = function(text) {
17521 return '<em>' + text + '</em>';
17524 Renderer.prototype.codespan = function(text) {
17525 return '<code>' + text + '</code>';
17528 Renderer.prototype.br = function() {
17529 return this.options.xhtml ? '<br/>' : '<br>';
17532 Renderer.prototype.del = function(text) {
17533 return '<del>' + text + '</del>';
17536 Renderer.prototype.link = function(href, title, text) {
17537 if (this.options.sanitize) {
17539 var prot = decodeURIComponent(unescape(href))
17540 .replace(/[^\w:]/g, '')
17545 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
17549 var out = '<a href="' + href + '"';
17551 out += ' title="' + title + '"';
17553 out += '>' + text + '</a>';
17557 Renderer.prototype.image = function(href, title, text) {
17558 var out = '<img src="' + href + '" alt="' + text + '"';
17560 out += ' title="' + title + '"';
17562 out += this.options.xhtml ? '/>' : '>';
17566 Renderer.prototype.text = function(text) {
17571 * Parsing & Compiling
17574 function Parser(options) {
17577 this.options = options || marked.defaults;
17578 this.options.renderer = this.options.renderer || new Renderer;
17579 this.renderer = this.options.renderer;
17580 this.renderer.options = this.options;
17584 * Static Parse Method
17587 Parser.parse = function(src, options, renderer) {
17588 var parser = new Parser(options, renderer);
17589 return parser.parse(src);
17596 Parser.prototype.parse = function(src) {
17597 this.inline = new InlineLexer(src.links, this.options, this.renderer);
17598 this.tokens = src.reverse();
17601 while (this.next()) {
17612 Parser.prototype.next = function() {
17613 return this.token = this.tokens.pop();
17617 * Preview Next Token
17620 Parser.prototype.peek = function() {
17621 return this.tokens[this.tokens.length - 1] || 0;
17625 * Parse Text Tokens
17628 Parser.prototype.parseText = function() {
17629 var body = this.token.text;
17631 while (this.peek().type === 'text') {
17632 body += '\n' + this.next().text;
17635 return this.inline.output(body);
17639 * Parse Current Token
17642 Parser.prototype.tok = function() {
17643 switch (this.token.type) {
17648 return this.renderer.hr();
17651 return this.renderer.heading(
17652 this.inline.output(this.token.text),
17657 return this.renderer.code(this.token.text,
17659 this.token.escaped);
17672 for (i = 0; i < this.token.header.length; i++) {
17673 flags = { header: true, align: this.token.align[i] };
17674 cell += this.renderer.tablecell(
17675 this.inline.output(this.token.header[i]),
17676 { header: true, align: this.token.align[i] }
17679 header += this.renderer.tablerow(cell);
17681 for (i = 0; i < this.token.cells.length; i++) {
17682 row = this.token.cells[i];
17685 for (j = 0; j < row.length; j++) {
17686 cell += this.renderer.tablecell(
17687 this.inline.output(row[j]),
17688 { header: false, align: this.token.align[j] }
17692 body += this.renderer.tablerow(cell);
17694 return this.renderer.table(header, body);
17696 case 'blockquote_start': {
17699 while (this.next().type !== 'blockquote_end') {
17700 body += this.tok();
17703 return this.renderer.blockquote(body);
17705 case 'list_start': {
17707 , ordered = this.token.ordered;
17709 while (this.next().type !== 'list_end') {
17710 body += this.tok();
17713 return this.renderer.list(body, ordered);
17715 case 'list_item_start': {
17718 while (this.next().type !== 'list_item_end') {
17719 body += this.token.type === 'text'
17724 return this.renderer.listitem(body);
17726 case 'loose_item_start': {
17729 while (this.next().type !== 'list_item_end') {
17730 body += this.tok();
17733 return this.renderer.listitem(body);
17736 var html = !this.token.pre && !this.options.pedantic
17737 ? this.inline.output(this.token.text)
17739 return this.renderer.html(html);
17741 case 'paragraph': {
17742 return this.renderer.paragraph(this.inline.output(this.token.text));
17745 return this.renderer.paragraph(this.parseText());
17754 function escape(html, encode) {
17756 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
17757 .replace(/</g, '<')
17758 .replace(/>/g, '>')
17759 .replace(/"/g, '"')
17760 .replace(/'/g, ''');
17763 function unescape(html) {
17764 // explicitly match decimal, hex, and named HTML entities
17765 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
17766 n = n.toLowerCase();
17767 if (n === 'colon') { return ':'; }
17768 if (n.charAt(0) === '#') {
17769 return n.charAt(1) === 'x'
17770 ? String.fromCharCode(parseInt(n.substring(2), 16))
17771 : String.fromCharCode(+n.substring(1));
17777 function replace(regex, opt) {
17778 regex = regex.source;
17780 return function self(name, val) {
17781 if (!name) { return new RegExp(regex, opt); }
17782 val = val.source || val;
17783 val = val.replace(/(^|[^\[])\^/g, '$1');
17784 regex = regex.replace(name, val);
17792 function merge(obj) {
17797 for (; i < arguments.length; i++) {
17798 target = arguments[i];
17799 for (key in target) {
17800 if (Object.prototype.hasOwnProperty.call(target, key)) {
17801 obj[key] = target[key];
17814 function marked(src, opt, callback) {
17815 if (callback || typeof opt === 'function') {
17821 opt = merge({}, marked.defaults, opt || {});
17823 var highlight = opt.highlight
17829 tokens = Lexer.lex(src, opt)
17831 return callback(e);
17834 pending = tokens.length;
17836 var done = function(err) {
17838 opt.highlight = highlight;
17839 return callback(err);
17845 out = Parser.parse(tokens, opt);
17850 opt.highlight = highlight;
17854 : callback(null, out);
17857 if (!highlight || highlight.length < 3) {
17861 delete opt.highlight;
17863 if (!pending) { return done(); }
17865 for (; i < tokens.length; i++) {
17867 if (token.type !== 'code') {
17868 return --pending || done();
17870 return highlight(token.text, token.lang, function(err, code) {
17871 if (err) { return done(err); }
17872 if (code == null || code === token.text) {
17873 return --pending || done();
17876 token.escaped = true;
17877 --pending || done();
17885 if (opt) { opt = merge({}, marked.defaults, opt); }
17886 return Parser.parse(Lexer.lex(src, opt), opt);
17888 e.message += '\nPlease report this to https://github.com/chjj/marked.';
17889 if ((opt || marked.defaults).silent) {
17890 return '<p>An error occured:</p><pre>'
17891 + escape(e.message + '', true)
17903 marked.setOptions = function(opt) {
17904 merge(marked.defaults, opt);
17908 marked.defaults = {
17919 langPrefix: 'lang-',
17920 smartypants: false,
17922 renderer: new Renderer,
17930 marked.Parser = Parser;
17931 marked.parser = Parser.parse;
17933 marked.Renderer = Renderer;
17935 marked.Lexer = Lexer;
17936 marked.lexer = Lexer.lex;
17938 marked.InlineLexer = InlineLexer;
17939 marked.inlineLexer = InlineLexer.output;
17941 marked.parse = marked;
17943 Roo.Markdown.marked = marked;
17947 * Ext JS Library 1.1.1
17948 * Copyright(c) 2006-2007, Ext JS, LLC.
17950 * Originally Released Under LGPL - original licence link has changed is not relivant.
17953 * <script type="text/javascript">
17959 * These classes are derivatives of the similarly named classes in the YUI Library.
17960 * The original license:
17961 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
17962 * Code licensed under the BSD License:
17963 * http://developer.yahoo.net/yui/license.txt
17968 var Event=Roo.EventManager;
17969 var Dom=Roo.lib.Dom;
17972 * @class Roo.dd.DragDrop
17973 * @extends Roo.util.Observable
17974 * Defines the interface and base operation of items that that can be
17975 * dragged or can be drop targets. It was designed to be extended, overriding
17976 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
17977 * Up to three html elements can be associated with a DragDrop instance:
17979 * <li>linked element: the element that is passed into the constructor.
17980 * This is the element which defines the boundaries for interaction with
17981 * other DragDrop objects.</li>
17982 * <li>handle element(s): The drag operation only occurs if the element that
17983 * was clicked matches a handle element. By default this is the linked
17984 * element, but there are times that you will want only a portion of the
17985 * linked element to initiate the drag operation, and the setHandleElId()
17986 * method provides a way to define this.</li>
17987 * <li>drag element: this represents the element that would be moved along
17988 * with the cursor during a drag operation. By default, this is the linked
17989 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
17990 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
17993 * This class should not be instantiated until the onload event to ensure that
17994 * the associated elements are available.
17995 * The following would define a DragDrop obj that would interact with any
17996 * other DragDrop obj in the "group1" group:
17998 * dd = new Roo.dd.DragDrop("div1", "group1");
18000 * Since none of the event handlers have been implemented, nothing would
18001 * actually happen if you were to run the code above. Normally you would
18002 * override this class or one of the default implementations, but you can
18003 * also override the methods you want on an instance of the class...
18005 * dd.onDragDrop = function(e, id) {
18006 * alert("dd was dropped on " + id);
18010 * @param {String} id of the element that is linked to this instance
18011 * @param {String} sGroup the group of related DragDrop objects
18012 * @param {object} config an object containing configurable attributes
18013 * Valid properties for DragDrop:
18014 * padding, isTarget, maintainOffset, primaryButtonOnly
18016 Roo.dd.DragDrop = function(id, sGroup, config) {
18018 this.init(id, sGroup, config);
18023 Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
18026 * The id of the element associated with this object. This is what we
18027 * refer to as the "linked element" because the size and position of
18028 * this element is used to determine when the drag and drop objects have
18036 * Configuration attributes passed into the constructor
18043 * The id of the element that will be dragged. By default this is same
18044 * as the linked element , but could be changed to another element. Ex:
18046 * @property dragElId
18053 * the id of the element that initiates the drag operation. By default
18054 * this is the linked element, but could be changed to be a child of this
18055 * element. This lets us do things like only starting the drag when the
18056 * header element within the linked html element is clicked.
18057 * @property handleElId
18064 * An associative array of HTML tags that will be ignored if clicked.
18065 * @property invalidHandleTypes
18066 * @type {string: string}
18068 invalidHandleTypes: null,
18071 * An associative array of ids for elements that will be ignored if clicked
18072 * @property invalidHandleIds
18073 * @type {string: string}
18075 invalidHandleIds: null,
18078 * An indexted array of css class names for elements that will be ignored
18080 * @property invalidHandleClasses
18083 invalidHandleClasses: null,
18086 * The linked element's absolute X position at the time the drag was
18088 * @property startPageX
18095 * The linked element's absolute X position at the time the drag was
18097 * @property startPageY
18104 * The group defines a logical collection of DragDrop objects that are
18105 * related. Instances only get events when interacting with other
18106 * DragDrop object in the same group. This lets us define multiple
18107 * groups using a single DragDrop subclass if we want.
18109 * @type {string: string}
18114 * Individual drag/drop instances can be locked. This will prevent
18115 * onmousedown start drag.
18123 * Lock this instance
18126 lock: function() { this.locked = true; },
18129 * Unlock this instace
18132 unlock: function() { this.locked = false; },
18135 * By default, all insances can be a drop target. This can be disabled by
18136 * setting isTarget to false.
18143 * The padding configured for this drag and drop object for calculating
18144 * the drop zone intersection with this object.
18151 * Cached reference to the linked element
18152 * @property _domRef
18158 * Internal typeof flag
18159 * @property __ygDragDrop
18162 __ygDragDrop: true,
18165 * Set to true when horizontal contraints are applied
18166 * @property constrainX
18173 * Set to true when vertical contraints are applied
18174 * @property constrainY
18181 * The left constraint
18189 * The right constraint
18197 * The up constraint
18206 * The down constraint
18214 * Maintain offsets when we resetconstraints. Set to true when you want
18215 * the position of the element relative to its parent to stay the same
18216 * when the page changes
18218 * @property maintainOffset
18221 maintainOffset: false,
18224 * Array of pixel locations the element will snap to if we specified a
18225 * horizontal graduation/interval. This array is generated automatically
18226 * when you define a tick interval.
18233 * Array of pixel locations the element will snap to if we specified a
18234 * vertical graduation/interval. This array is generated automatically
18235 * when you define a tick interval.
18242 * By default the drag and drop instance will only respond to the primary
18243 * button click (left button for a right-handed mouse). Set to true to
18244 * allow drag and drop to start with any mouse click that is propogated
18246 * @property primaryButtonOnly
18249 primaryButtonOnly: true,
18252 * The availabe property is false until the linked dom element is accessible.
18253 * @property available
18259 * By default, drags can only be initiated if the mousedown occurs in the
18260 * region the linked element is. This is done in part to work around a
18261 * bug in some browsers that mis-report the mousedown if the previous
18262 * mouseup happened outside of the window. This property is set to true
18263 * if outer handles are defined.
18265 * @property hasOuterHandles
18269 hasOuterHandles: false,
18272 * Code that executes immediately before the startDrag event
18273 * @method b4StartDrag
18276 b4StartDrag: function(x, y) { },
18279 * Abstract method called after a drag/drop object is clicked
18280 * and the drag or mousedown time thresholds have beeen met.
18281 * @method startDrag
18282 * @param {int} X click location
18283 * @param {int} Y click location
18285 startDrag: function(x, y) { /* override this */ },
18288 * Code that executes immediately before the onDrag event
18292 b4Drag: function(e) { },
18295 * Abstract method called during the onMouseMove event while dragging an
18298 * @param {Event} e the mousemove event
18300 onDrag: function(e) { /* override this */ },
18303 * Abstract method called when this element fist begins hovering over
18304 * another DragDrop obj
18305 * @method onDragEnter
18306 * @param {Event} e the mousemove event
18307 * @param {String|DragDrop[]} id In POINT mode, the element
18308 * id this is hovering over. In INTERSECT mode, an array of one or more
18309 * dragdrop items being hovered over.
18311 onDragEnter: function(e, id) { /* override this */ },
18314 * Code that executes immediately before the onDragOver event
18315 * @method b4DragOver
18318 b4DragOver: function(e) { },
18321 * Abstract method called when this element is hovering over another
18323 * @method onDragOver
18324 * @param {Event} e the mousemove event
18325 * @param {String|DragDrop[]} id In POINT mode, the element
18326 * id this is hovering over. In INTERSECT mode, an array of dd items
18327 * being hovered over.
18329 onDragOver: function(e, id) { /* override this */ },
18332 * Code that executes immediately before the onDragOut event
18333 * @method b4DragOut
18336 b4DragOut: function(e) { },
18339 * Abstract method called when we are no longer hovering over an element
18340 * @method onDragOut
18341 * @param {Event} e the mousemove event
18342 * @param {String|DragDrop[]} id In POINT mode, the element
18343 * id this was hovering over. In INTERSECT mode, an array of dd items
18344 * that the mouse is no longer over.
18346 onDragOut: function(e, id) { /* override this */ },
18349 * Code that executes immediately before the onDragDrop event
18350 * @method b4DragDrop
18353 b4DragDrop: function(e) { },
18356 * Abstract method called when this item is dropped on another DragDrop
18358 * @method onDragDrop
18359 * @param {Event} e the mouseup event
18360 * @param {String|DragDrop[]} id In POINT mode, the element
18361 * id this was dropped on. In INTERSECT mode, an array of dd items this
18364 onDragDrop: function(e, id) { /* override this */ },
18367 * Abstract method called when this item is dropped on an area with no
18369 * @method onInvalidDrop
18370 * @param {Event} e the mouseup event
18372 onInvalidDrop: function(e) { /* override this */ },
18375 * Code that executes immediately before the endDrag event
18376 * @method b4EndDrag
18379 b4EndDrag: function(e) { },
18382 * Fired when we are done dragging the object
18384 * @param {Event} e the mouseup event
18386 endDrag: function(e) { /* override this */ },
18389 * Code executed immediately before the onMouseDown event
18390 * @method b4MouseDown
18391 * @param {Event} e the mousedown event
18394 b4MouseDown: function(e) { },
18397 * Event handler that fires when a drag/drop obj gets a mousedown
18398 * @method onMouseDown
18399 * @param {Event} e the mousedown event
18401 onMouseDown: function(e) { /* override this */ },
18404 * Event handler that fires when a drag/drop obj gets a mouseup
18405 * @method onMouseUp
18406 * @param {Event} e the mouseup event
18408 onMouseUp: function(e) { /* override this */ },
18411 * Override the onAvailable method to do what is needed after the initial
18412 * position was determined.
18413 * @method onAvailable
18415 onAvailable: function () {
18419 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
18422 defaultPadding : {left:0, right:0, top:0, bottom:0},
18425 * Initializes the drag drop object's constraints to restrict movement to a certain element.
18429 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
18430 { dragElId: "existingProxyDiv" });
18431 dd.startDrag = function(){
18432 this.constrainTo("parent-id");
18435 * Or you can initalize it using the {@link Roo.Element} object:
18437 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
18438 startDrag : function(){
18439 this.constrainTo("parent-id");
18443 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
18444 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
18445 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
18446 * an object containing the sides to pad. For example: {right:10, bottom:10}
18447 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
18449 constrainTo : function(constrainTo, pad, inContent){
18450 if(typeof pad == "number"){
18451 pad = {left: pad, right:pad, top:pad, bottom:pad};
18453 pad = pad || this.defaultPadding;
18454 var b = Roo.get(this.getEl()).getBox();
18455 var ce = Roo.get(constrainTo);
18456 var s = ce.getScroll();
18457 var c, cd = ce.dom;
18458 if(cd == document.body){
18459 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
18462 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
18466 var topSpace = b.y - c.y;
18467 var leftSpace = b.x - c.x;
18469 this.resetConstraints();
18470 this.setXConstraint(leftSpace - (pad.left||0), // left
18471 c.width - leftSpace - b.width - (pad.right||0) //right
18473 this.setYConstraint(topSpace - (pad.top||0), //top
18474 c.height - topSpace - b.height - (pad.bottom||0) //bottom
18479 * Returns a reference to the linked element
18481 * @return {HTMLElement} the html element
18483 getEl: function() {
18484 if (!this._domRef) {
18485 this._domRef = Roo.getDom(this.id);
18488 return this._domRef;
18492 * Returns a reference to the actual element to drag. By default this is
18493 * the same as the html element, but it can be assigned to another
18494 * element. An example of this can be found in Roo.dd.DDProxy
18495 * @method getDragEl
18496 * @return {HTMLElement} the html element
18498 getDragEl: function() {
18499 return Roo.getDom(this.dragElId);
18503 * Sets up the DragDrop object. Must be called in the constructor of any
18504 * Roo.dd.DragDrop subclass
18506 * @param id the id of the linked element
18507 * @param {String} sGroup the group of related items
18508 * @param {object} config configuration attributes
18510 init: function(id, sGroup, config) {
18511 this.initTarget(id, sGroup, config);
18512 if (!Roo.isTouch) {
18513 Event.on(this.id, "mousedown", this.handleMouseDown, this);
18515 Event.on(this.id, "touchstart", this.handleMouseDown, this);
18516 // Event.on(this.id, "selectstart", Event.preventDefault);
18520 * Initializes Targeting functionality only... the object does not
18521 * get a mousedown handler.
18522 * @method initTarget
18523 * @param id the id of the linked element
18524 * @param {String} sGroup the group of related items
18525 * @param {object} config configuration attributes
18527 initTarget: function(id, sGroup, config) {
18529 // configuration attributes
18530 this.config = config || {};
18532 // create a local reference to the drag and drop manager
18533 this.DDM = Roo.dd.DDM;
18534 // initialize the groups array
18537 // assume that we have an element reference instead of an id if the
18538 // parameter is not a string
18539 if (typeof id !== "string") {
18546 // add to an interaction group
18547 this.addToGroup((sGroup) ? sGroup : "default");
18549 // We don't want to register this as the handle with the manager
18550 // so we just set the id rather than calling the setter.
18551 this.handleElId = id;
18553 // the linked element is the element that gets dragged by default
18554 this.setDragElId(id);
18556 // by default, clicked anchors will not start drag operations.
18557 this.invalidHandleTypes = { A: "A" };
18558 this.invalidHandleIds = {};
18559 this.invalidHandleClasses = [];
18561 this.applyConfig();
18563 this.handleOnAvailable();
18567 * Applies the configuration parameters that were passed into the constructor.
18568 * This is supposed to happen at each level through the inheritance chain. So
18569 * a DDProxy implentation will execute apply config on DDProxy, DD, and
18570 * DragDrop in order to get all of the parameters that are available in
18572 * @method applyConfig
18574 applyConfig: function() {
18576 // configurable properties:
18577 // padding, isTarget, maintainOffset, primaryButtonOnly
18578 this.padding = this.config.padding || [0, 0, 0, 0];
18579 this.isTarget = (this.config.isTarget !== false);
18580 this.maintainOffset = (this.config.maintainOffset);
18581 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
18586 * Executed when the linked element is available
18587 * @method handleOnAvailable
18590 handleOnAvailable: function() {
18591 this.available = true;
18592 this.resetConstraints();
18593 this.onAvailable();
18597 * Configures the padding for the target zone in px. Effectively expands
18598 * (or reduces) the virtual object size for targeting calculations.
18599 * Supports css-style shorthand; if only one parameter is passed, all sides
18600 * will have that padding, and if only two are passed, the top and bottom
18601 * will have the first param, the left and right the second.
18602 * @method setPadding
18603 * @param {int} iTop Top pad
18604 * @param {int} iRight Right pad
18605 * @param {int} iBot Bot pad
18606 * @param {int} iLeft Left pad
18608 setPadding: function(iTop, iRight, iBot, iLeft) {
18609 // this.padding = [iLeft, iRight, iTop, iBot];
18610 if (!iRight && 0 !== iRight) {
18611 this.padding = [iTop, iTop, iTop, iTop];
18612 } else if (!iBot && 0 !== iBot) {
18613 this.padding = [iTop, iRight, iTop, iRight];
18615 this.padding = [iTop, iRight, iBot, iLeft];
18620 * Stores the initial placement of the linked element.
18621 * @method setInitialPosition
18622 * @param {int} diffX the X offset, default 0
18623 * @param {int} diffY the Y offset, default 0
18625 setInitPosition: function(diffX, diffY) {
18626 var el = this.getEl();
18628 if (!this.DDM.verifyEl(el)) {
18632 var dx = diffX || 0;
18633 var dy = diffY || 0;
18635 var p = Dom.getXY( el );
18637 this.initPageX = p[0] - dx;
18638 this.initPageY = p[1] - dy;
18640 this.lastPageX = p[0];
18641 this.lastPageY = p[1];
18644 this.setStartPosition(p);
18648 * Sets the start position of the element. This is set when the obj
18649 * is initialized, the reset when a drag is started.
18650 * @method setStartPosition
18651 * @param pos current position (from previous lookup)
18654 setStartPosition: function(pos) {
18655 var p = pos || Dom.getXY( this.getEl() );
18656 this.deltaSetXY = null;
18658 this.startPageX = p[0];
18659 this.startPageY = p[1];
18663 * Add this instance to a group of related drag/drop objects. All
18664 * instances belong to at least one group, and can belong to as many
18665 * groups as needed.
18666 * @method addToGroup
18667 * @param sGroup {string} the name of the group
18669 addToGroup: function(sGroup) {
18670 this.groups[sGroup] = true;
18671 this.DDM.regDragDrop(this, sGroup);
18675 * Remove's this instance from the supplied interaction group
18676 * @method removeFromGroup
18677 * @param {string} sGroup The group to drop
18679 removeFromGroup: function(sGroup) {
18680 if (this.groups[sGroup]) {
18681 delete this.groups[sGroup];
18684 this.DDM.removeDDFromGroup(this, sGroup);
18688 * Allows you to specify that an element other than the linked element
18689 * will be moved with the cursor during a drag
18690 * @method setDragElId
18691 * @param id {string} the id of the element that will be used to initiate the drag
18693 setDragElId: function(id) {
18694 this.dragElId = id;
18698 * Allows you to specify a child of the linked element that should be
18699 * used to initiate the drag operation. An example of this would be if
18700 * you have a content div with text and links. Clicking anywhere in the
18701 * content area would normally start the drag operation. Use this method
18702 * to specify that an element inside of the content div is the element
18703 * that starts the drag operation.
18704 * @method setHandleElId
18705 * @param id {string} the id of the element that will be used to
18706 * initiate the drag.
18708 setHandleElId: function(id) {
18709 if (typeof id !== "string") {
18712 this.handleElId = id;
18713 this.DDM.regHandle(this.id, id);
18717 * Allows you to set an element outside of the linked element as a drag
18719 * @method setOuterHandleElId
18720 * @param id the id of the element that will be used to initiate the drag
18722 setOuterHandleElId: function(id) {
18723 if (typeof id !== "string") {
18726 Event.on(id, "mousedown",
18727 this.handleMouseDown, this);
18728 this.setHandleElId(id);
18730 this.hasOuterHandles = true;
18734 * Remove all drag and drop hooks for this element
18737 unreg: function() {
18738 Event.un(this.id, "mousedown",
18739 this.handleMouseDown);
18740 Event.un(this.id, "touchstart",
18741 this.handleMouseDown);
18742 this._domRef = null;
18743 this.DDM._remove(this);
18746 destroy : function(){
18751 * Returns true if this instance is locked, or the drag drop mgr is locked
18752 * (meaning that all drag/drop is disabled on the page.)
18754 * @return {boolean} true if this obj or all drag/drop is locked, else
18757 isLocked: function() {
18758 return (this.DDM.isLocked() || this.locked);
18762 * Fired when this object is clicked
18763 * @method handleMouseDown
18765 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
18768 handleMouseDown: function(e, oDD){
18770 if (!Roo.isTouch && this.primaryButtonOnly && e.button != 0) {
18771 //Roo.log('not touch/ button !=0');
18774 if (e.browserEvent.touches && e.browserEvent.touches.length != 1) {
18775 return; // double touch..
18779 if (this.isLocked()) {
18780 //Roo.log('locked');
18784 this.DDM.refreshCache(this.groups);
18785 // Roo.log([Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e)]);
18786 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
18787 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
18788 //Roo.log('no outer handes or not over target');
18791 // Roo.log('check validator');
18792 if (this.clickValidator(e)) {
18793 // Roo.log('validate success');
18794 // set the initial element position
18795 this.setStartPosition();
18798 this.b4MouseDown(e);
18799 this.onMouseDown(e);
18801 this.DDM.handleMouseDown(e, this);
18803 this.DDM.stopEvent(e);
18811 clickValidator: function(e) {
18812 var target = e.getTarget();
18813 return ( this.isValidHandleChild(target) &&
18814 (this.id == this.handleElId ||
18815 this.DDM.handleWasClicked(target, this.id)) );
18819 * Allows you to specify a tag name that should not start a drag operation
18820 * when clicked. This is designed to facilitate embedding links within a
18821 * drag handle that do something other than start the drag.
18822 * @method addInvalidHandleType
18823 * @param {string} tagName the type of element to exclude
18825 addInvalidHandleType: function(tagName) {
18826 var type = tagName.toUpperCase();
18827 this.invalidHandleTypes[type] = type;
18831 * Lets you to specify an element id for a child of a drag handle
18832 * that should not initiate a drag
18833 * @method addInvalidHandleId
18834 * @param {string} id the element id of the element you wish to ignore
18836 addInvalidHandleId: function(id) {
18837 if (typeof id !== "string") {
18840 this.invalidHandleIds[id] = id;
18844 * Lets you specify a css class of elements that will not initiate a drag
18845 * @method addInvalidHandleClass
18846 * @param {string} cssClass the class of the elements you wish to ignore
18848 addInvalidHandleClass: function(cssClass) {
18849 this.invalidHandleClasses.push(cssClass);
18853 * Unsets an excluded tag name set by addInvalidHandleType
18854 * @method removeInvalidHandleType
18855 * @param {string} tagName the type of element to unexclude
18857 removeInvalidHandleType: function(tagName) {
18858 var type = tagName.toUpperCase();
18859 // this.invalidHandleTypes[type] = null;
18860 delete this.invalidHandleTypes[type];
18864 * Unsets an invalid handle id
18865 * @method removeInvalidHandleId
18866 * @param {string} id the id of the element to re-enable
18868 removeInvalidHandleId: function(id) {
18869 if (typeof id !== "string") {
18872 delete this.invalidHandleIds[id];
18876 * Unsets an invalid css class
18877 * @method removeInvalidHandleClass
18878 * @param {string} cssClass the class of the element(s) you wish to
18881 removeInvalidHandleClass: function(cssClass) {
18882 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
18883 if (this.invalidHandleClasses[i] == cssClass) {
18884 delete this.invalidHandleClasses[i];
18890 * Checks the tag exclusion list to see if this click should be ignored
18891 * @method isValidHandleChild
18892 * @param {HTMLElement} node the HTMLElement to evaluate
18893 * @return {boolean} true if this is a valid tag type, false if not
18895 isValidHandleChild: function(node) {
18898 // var n = (node.nodeName == "#text") ? node.parentNode : node;
18901 nodeName = node.nodeName.toUpperCase();
18903 nodeName = node.nodeName;
18905 valid = valid && !this.invalidHandleTypes[nodeName];
18906 valid = valid && !this.invalidHandleIds[node.id];
18908 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
18909 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
18918 * Create the array of horizontal tick marks if an interval was specified
18919 * in setXConstraint().
18920 * @method setXTicks
18923 setXTicks: function(iStartX, iTickSize) {
18925 this.xTickSize = iTickSize;
18929 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
18931 this.xTicks[this.xTicks.length] = i;
18936 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
18938 this.xTicks[this.xTicks.length] = i;
18943 this.xTicks.sort(this.DDM.numericSort) ;
18947 * Create the array of vertical tick marks if an interval was specified in
18948 * setYConstraint().
18949 * @method setYTicks
18952 setYTicks: function(iStartY, iTickSize) {
18954 this.yTickSize = iTickSize;
18958 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
18960 this.yTicks[this.yTicks.length] = i;
18965 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
18967 this.yTicks[this.yTicks.length] = i;
18972 this.yTicks.sort(this.DDM.numericSort) ;
18976 * By default, the element can be dragged any place on the screen. Use
18977 * this method to limit the horizontal travel of the element. Pass in
18978 * 0,0 for the parameters if you want to lock the drag to the y axis.
18979 * @method setXConstraint
18980 * @param {int} iLeft the number of pixels the element can move to the left
18981 * @param {int} iRight the number of pixels the element can move to the
18983 * @param {int} iTickSize optional parameter for specifying that the
18985 * should move iTickSize pixels at a time.
18987 setXConstraint: function(iLeft, iRight, iTickSize) {
18988 this.leftConstraint = iLeft;
18989 this.rightConstraint = iRight;
18991 this.minX = this.initPageX - iLeft;
18992 this.maxX = this.initPageX + iRight;
18993 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
18995 this.constrainX = true;
18999 * Clears any constraints applied to this instance. Also clears ticks
19000 * since they can't exist independent of a constraint at this time.
19001 * @method clearConstraints
19003 clearConstraints: function() {
19004 this.constrainX = false;
19005 this.constrainY = false;
19010 * Clears any tick interval defined for this instance
19011 * @method clearTicks
19013 clearTicks: function() {
19014 this.xTicks = null;
19015 this.yTicks = null;
19016 this.xTickSize = 0;
19017 this.yTickSize = 0;
19021 * By default, the element can be dragged any place on the screen. Set
19022 * this to limit the vertical travel of the element. Pass in 0,0 for the
19023 * parameters if you want to lock the drag to the x axis.
19024 * @method setYConstraint
19025 * @param {int} iUp the number of pixels the element can move up
19026 * @param {int} iDown the number of pixels the element can move down
19027 * @param {int} iTickSize optional parameter for specifying that the
19028 * element should move iTickSize pixels at a time.
19030 setYConstraint: function(iUp, iDown, iTickSize) {
19031 this.topConstraint = iUp;
19032 this.bottomConstraint = iDown;
19034 this.minY = this.initPageY - iUp;
19035 this.maxY = this.initPageY + iDown;
19036 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
19038 this.constrainY = true;
19043 * resetConstraints must be called if you manually reposition a dd element.
19044 * @method resetConstraints
19045 * @param {boolean} maintainOffset
19047 resetConstraints: function() {
19050 // Maintain offsets if necessary
19051 if (this.initPageX || this.initPageX === 0) {
19052 // figure out how much this thing has moved
19053 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
19054 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
19056 this.setInitPosition(dx, dy);
19058 // This is the first time we have detected the element's position
19060 this.setInitPosition();
19063 if (this.constrainX) {
19064 this.setXConstraint( this.leftConstraint,
19065 this.rightConstraint,
19069 if (this.constrainY) {
19070 this.setYConstraint( this.topConstraint,
19071 this.bottomConstraint,
19077 * Normally the drag element is moved pixel by pixel, but we can specify
19078 * that it move a number of pixels at a time. This method resolves the
19079 * location when we have it set up like this.
19081 * @param {int} val where we want to place the object
19082 * @param {int[]} tickArray sorted array of valid points
19083 * @return {int} the closest tick
19086 getTick: function(val, tickArray) {
19089 // If tick interval is not defined, it is effectively 1 pixel,
19090 // so we return the value passed to us.
19092 } else if (tickArray[0] >= val) {
19093 // The value is lower than the first tick, so we return the first
19095 return tickArray[0];
19097 for (var i=0, len=tickArray.length; i<len; ++i) {
19099 if (tickArray[next] && tickArray[next] >= val) {
19100 var diff1 = val - tickArray[i];
19101 var diff2 = tickArray[next] - val;
19102 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
19106 // The value is larger than the last tick, so we return the last
19108 return tickArray[tickArray.length - 1];
19115 * @return {string} string representation of the dd obj
19117 toString: function() {
19118 return ("DragDrop " + this.id);
19126 * Ext JS Library 1.1.1
19127 * Copyright(c) 2006-2007, Ext JS, LLC.
19129 * Originally Released Under LGPL - original licence link has changed is not relivant.
19132 * <script type="text/javascript">
19137 * The drag and drop utility provides a framework for building drag and drop
19138 * applications. In addition to enabling drag and drop for specific elements,
19139 * the drag and drop elements are tracked by the manager class, and the
19140 * interactions between the various elements are tracked during the drag and
19141 * the implementing code is notified about these important moments.
19144 // Only load the library once. Rewriting the manager class would orphan
19145 // existing drag and drop instances.
19146 if (!Roo.dd.DragDropMgr) {
19149 * @class Roo.dd.DragDropMgr
19150 * DragDropMgr is a singleton that tracks the element interaction for
19151 * all DragDrop items in the window. Generally, you will not call
19152 * this class directly, but it does have helper methods that could
19153 * be useful in your DragDrop implementations.
19156 Roo.dd.DragDropMgr = function() {
19158 var Event = Roo.EventManager;
19163 * Two dimensional Array of registered DragDrop objects. The first
19164 * dimension is the DragDrop item group, the second the DragDrop
19167 * @type {string: string}
19174 * Array of element ids defined as drag handles. Used to determine
19175 * if the element that generated the mousedown event is actually the
19176 * handle and not the html element itself.
19177 * @property handleIds
19178 * @type {string: string}
19185 * the DragDrop object that is currently being dragged
19186 * @property dragCurrent
19194 * the DragDrop object(s) that are being hovered over
19195 * @property dragOvers
19203 * the X distance between the cursor and the object being dragged
19212 * the Y distance between the cursor and the object being dragged
19221 * Flag to determine if we should prevent the default behavior of the
19222 * events we define. By default this is true, but this can be set to
19223 * false if you need the default behavior (not recommended)
19224 * @property preventDefault
19228 preventDefault: true,
19231 * Flag to determine if we should stop the propagation of the events
19232 * we generate. This is true by default but you may want to set it to
19233 * false if the html element contains other features that require the
19235 * @property stopPropagation
19239 stopPropagation: true,
19242 * Internal flag that is set to true when drag and drop has been
19244 * @property initialized
19251 * All drag and drop can be disabled.
19259 * Called the first time an element is registered.
19265 this.initialized = true;
19269 * In point mode, drag and drop interaction is defined by the
19270 * location of the cursor during the drag/drop
19278 * In intersect mode, drag and drop interactio nis defined by the
19279 * overlap of two or more drag and drop objects.
19280 * @property INTERSECT
19287 * The current drag and drop mode. Default: POINT
19295 * Runs method on all drag and drop objects
19296 * @method _execOnAll
19300 _execOnAll: function(sMethod, args) {
19301 for (var i in this.ids) {
19302 for (var j in this.ids[i]) {
19303 var oDD = this.ids[i][j];
19304 if (! this.isTypeOfDD(oDD)) {
19307 oDD[sMethod].apply(oDD, args);
19313 * Drag and drop initialization. Sets up the global event handlers
19318 _onLoad: function() {
19322 if (!Roo.isTouch) {
19323 Event.on(document, "mouseup", this.handleMouseUp, this, true);
19324 Event.on(document, "mousemove", this.handleMouseMove, this, true);
19326 Event.on(document, "touchend", this.handleMouseUp, this, true);
19327 Event.on(document, "touchmove", this.handleMouseMove, this, true);
19329 Event.on(window, "unload", this._onUnload, this, true);
19330 Event.on(window, "resize", this._onResize, this, true);
19331 // Event.on(window, "mouseout", this._test);
19336 * Reset constraints on all drag and drop objs
19337 * @method _onResize
19341 _onResize: function(e) {
19342 this._execOnAll("resetConstraints", []);
19346 * Lock all drag and drop functionality
19350 lock: function() { this.locked = true; },
19353 * Unlock all drag and drop functionality
19357 unlock: function() { this.locked = false; },
19360 * Is drag and drop locked?
19362 * @return {boolean} True if drag and drop is locked, false otherwise.
19365 isLocked: function() { return this.locked; },
19368 * Location cache that is set for all drag drop objects when a drag is
19369 * initiated, cleared when the drag is finished.
19370 * @property locationCache
19377 * Set useCache to false if you want to force object the lookup of each
19378 * drag and drop linked element constantly during a drag.
19379 * @property useCache
19386 * The number of pixels that the mouse needs to move after the
19387 * mousedown before the drag is initiated. Default=3;
19388 * @property clickPixelThresh
19392 clickPixelThresh: 3,
19395 * The number of milliseconds after the mousedown event to initiate the
19396 * drag if we don't get a mouseup event. Default=1000
19397 * @property clickTimeThresh
19401 clickTimeThresh: 350,
19404 * Flag that indicates that either the drag pixel threshold or the
19405 * mousdown time threshold has been met
19406 * @property dragThreshMet
19411 dragThreshMet: false,
19414 * Timeout used for the click time threshold
19415 * @property clickTimeout
19420 clickTimeout: null,
19423 * The X position of the mousedown event stored for later use when a
19424 * drag threshold is met.
19433 * The Y position of the mousedown event stored for later use when a
19434 * drag threshold is met.
19443 * Each DragDrop instance must be registered with the DragDropMgr.
19444 * This is executed in DragDrop.init()
19445 * @method regDragDrop
19446 * @param {DragDrop} oDD the DragDrop object to register
19447 * @param {String} sGroup the name of the group this element belongs to
19450 regDragDrop: function(oDD, sGroup) {
19451 if (!this.initialized) { this.init(); }
19453 if (!this.ids[sGroup]) {
19454 this.ids[sGroup] = {};
19456 this.ids[sGroup][oDD.id] = oDD;
19460 * Removes the supplied dd instance from the supplied group. Executed
19461 * by DragDrop.removeFromGroup, so don't call this function directly.
19462 * @method removeDDFromGroup
19466 removeDDFromGroup: function(oDD, sGroup) {
19467 if (!this.ids[sGroup]) {
19468 this.ids[sGroup] = {};
19471 var obj = this.ids[sGroup];
19472 if (obj && obj[oDD.id]) {
19473 delete obj[oDD.id];
19478 * Unregisters a drag and drop item. This is executed in
19479 * DragDrop.unreg, use that method instead of calling this directly.
19484 _remove: function(oDD) {
19485 for (var g in oDD.groups) {
19486 if (g && this.ids[g][oDD.id]) {
19487 delete this.ids[g][oDD.id];
19490 delete this.handleIds[oDD.id];
19494 * Each DragDrop handle element must be registered. This is done
19495 * automatically when executing DragDrop.setHandleElId()
19496 * @method regHandle
19497 * @param {String} sDDId the DragDrop id this element is a handle for
19498 * @param {String} sHandleId the id of the element that is the drag
19502 regHandle: function(sDDId, sHandleId) {
19503 if (!this.handleIds[sDDId]) {
19504 this.handleIds[sDDId] = {};
19506 this.handleIds[sDDId][sHandleId] = sHandleId;
19510 * Utility function to determine if a given element has been
19511 * registered as a drag drop item.
19512 * @method isDragDrop
19513 * @param {String} id the element id to check
19514 * @return {boolean} true if this element is a DragDrop item,
19518 isDragDrop: function(id) {
19519 return ( this.getDDById(id) ) ? true : false;
19523 * Returns the drag and drop instances that are in all groups the
19524 * passed in instance belongs to.
19525 * @method getRelated
19526 * @param {DragDrop} p_oDD the obj to get related data for
19527 * @param {boolean} bTargetsOnly if true, only return targetable objs
19528 * @return {DragDrop[]} the related instances
19531 getRelated: function(p_oDD, bTargetsOnly) {
19533 for (var i in p_oDD.groups) {
19534 for (j in this.ids[i]) {
19535 var dd = this.ids[i][j];
19536 if (! this.isTypeOfDD(dd)) {
19539 if (!bTargetsOnly || dd.isTarget) {
19540 oDDs[oDDs.length] = dd;
19549 * Returns true if the specified dd target is a legal target for
19550 * the specifice drag obj
19551 * @method isLegalTarget
19552 * @param {DragDrop} the drag obj
19553 * @param {DragDrop} the target
19554 * @return {boolean} true if the target is a legal target for the
19558 isLegalTarget: function (oDD, oTargetDD) {
19559 var targets = this.getRelated(oDD, true);
19560 for (var i=0, len=targets.length;i<len;++i) {
19561 if (targets[i].id == oTargetDD.id) {
19570 * My goal is to be able to transparently determine if an object is
19571 * typeof DragDrop, and the exact subclass of DragDrop. typeof
19572 * returns "object", oDD.constructor.toString() always returns
19573 * "DragDrop" and not the name of the subclass. So for now it just
19574 * evaluates a well-known variable in DragDrop.
19575 * @method isTypeOfDD
19576 * @param {Object} the object to evaluate
19577 * @return {boolean} true if typeof oDD = DragDrop
19580 isTypeOfDD: function (oDD) {
19581 return (oDD && oDD.__ygDragDrop);
19585 * Utility function to determine if a given element has been
19586 * registered as a drag drop handle for the given Drag Drop object.
19588 * @param {String} id the element id to check
19589 * @return {boolean} true if this element is a DragDrop handle, false
19593 isHandle: function(sDDId, sHandleId) {
19594 return ( this.handleIds[sDDId] &&
19595 this.handleIds[sDDId][sHandleId] );
19599 * Returns the DragDrop instance for a given id
19600 * @method getDDById
19601 * @param {String} id the id of the DragDrop object
19602 * @return {DragDrop} the drag drop object, null if it is not found
19605 getDDById: function(id) {
19606 for (var i in this.ids) {
19607 if (this.ids[i][id]) {
19608 return this.ids[i][id];
19615 * Fired after a registered DragDrop object gets the mousedown event.
19616 * Sets up the events required to track the object being dragged
19617 * @method handleMouseDown
19618 * @param {Event} e the event
19619 * @param oDD the DragDrop object being dragged
19623 handleMouseDown: function(e, oDD) {
19625 Roo.QuickTips.disable();
19627 this.currentTarget = e.getTarget();
19629 this.dragCurrent = oDD;
19631 var el = oDD.getEl();
19633 // track start position
19634 this.startX = e.getPageX();
19635 this.startY = e.getPageY();
19637 this.deltaX = this.startX - el.offsetLeft;
19638 this.deltaY = this.startY - el.offsetTop;
19640 this.dragThreshMet = false;
19642 this.clickTimeout = setTimeout(
19644 var DDM = Roo.dd.DDM;
19645 DDM.startDrag(DDM.startX, DDM.startY);
19647 this.clickTimeThresh );
19651 * Fired when either the drag pixel threshol or the mousedown hold
19652 * time threshold has been met.
19653 * @method startDrag
19654 * @param x {int} the X position of the original mousedown
19655 * @param y {int} the Y position of the original mousedown
19658 startDrag: function(x, y) {
19659 clearTimeout(this.clickTimeout);
19660 if (this.dragCurrent) {
19661 this.dragCurrent.b4StartDrag(x, y);
19662 this.dragCurrent.startDrag(x, y);
19664 this.dragThreshMet = true;
19668 * Internal function to handle the mouseup event. Will be invoked
19669 * from the context of the document.
19670 * @method handleMouseUp
19671 * @param {Event} e the event
19675 handleMouseUp: function(e) {
19678 Roo.QuickTips.enable();
19680 if (! this.dragCurrent) {
19684 clearTimeout(this.clickTimeout);
19686 if (this.dragThreshMet) {
19687 this.fireEvents(e, true);
19697 * Utility to stop event propagation and event default, if these
19698 * features are turned on.
19699 * @method stopEvent
19700 * @param {Event} e the event as returned by this.getEvent()
19703 stopEvent: function(e){
19704 if(this.stopPropagation) {
19705 e.stopPropagation();
19708 if (this.preventDefault) {
19709 e.preventDefault();
19714 * Internal function to clean up event handlers after the drag
19715 * operation is complete
19717 * @param {Event} e the event
19721 stopDrag: function(e) {
19722 // Fire the drag end event for the item that was dragged
19723 if (this.dragCurrent) {
19724 if (this.dragThreshMet) {
19725 this.dragCurrent.b4EndDrag(e);
19726 this.dragCurrent.endDrag(e);
19729 this.dragCurrent.onMouseUp(e);
19732 this.dragCurrent = null;
19733 this.dragOvers = {};
19737 * Internal function to handle the mousemove event. Will be invoked
19738 * from the context of the html element.
19740 * @TODO figure out what we can do about mouse events lost when the
19741 * user drags objects beyond the window boundary. Currently we can
19742 * detect this in internet explorer by verifying that the mouse is
19743 * down during the mousemove event. Firefox doesn't give us the
19744 * button state on the mousemove event.
19745 * @method handleMouseMove
19746 * @param {Event} e the event
19750 handleMouseMove: function(e) {
19751 if (! this.dragCurrent) {
19755 // var button = e.which || e.button;
19757 // check for IE mouseup outside of page boundary
19758 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
19760 return this.handleMouseUp(e);
19763 if (!this.dragThreshMet) {
19764 var diffX = Math.abs(this.startX - e.getPageX());
19765 var diffY = Math.abs(this.startY - e.getPageY());
19766 if (diffX > this.clickPixelThresh ||
19767 diffY > this.clickPixelThresh) {
19768 this.startDrag(this.startX, this.startY);
19772 if (this.dragThreshMet) {
19773 this.dragCurrent.b4Drag(e);
19774 this.dragCurrent.onDrag(e);
19775 if(!this.dragCurrent.moveOnly){
19776 this.fireEvents(e, false);
19786 * Iterates over all of the DragDrop elements to find ones we are
19787 * hovering over or dropping on
19788 * @method fireEvents
19789 * @param {Event} e the event
19790 * @param {boolean} isDrop is this a drop op or a mouseover op?
19794 fireEvents: function(e, isDrop) {
19795 var dc = this.dragCurrent;
19797 // If the user did the mouse up outside of the window, we could
19798 // get here even though we have ended the drag.
19799 if (!dc || dc.isLocked()) {
19803 var pt = e.getPoint();
19805 // cache the previous dragOver array
19811 var enterEvts = [];
19813 // Check to see if the object(s) we were hovering over is no longer
19814 // being hovered over so we can fire the onDragOut event
19815 for (var i in this.dragOvers) {
19817 var ddo = this.dragOvers[i];
19819 if (! this.isTypeOfDD(ddo)) {
19823 if (! this.isOverTarget(pt, ddo, this.mode)) {
19824 outEvts.push( ddo );
19827 oldOvers[i] = true;
19828 delete this.dragOvers[i];
19831 for (var sGroup in dc.groups) {
19833 if ("string" != typeof sGroup) {
19837 for (i in this.ids[sGroup]) {
19838 var oDD = this.ids[sGroup][i];
19839 if (! this.isTypeOfDD(oDD)) {
19843 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
19844 if (this.isOverTarget(pt, oDD, this.mode)) {
19845 // look for drop interactions
19847 dropEvts.push( oDD );
19848 // look for drag enter and drag over interactions
19851 // initial drag over: dragEnter fires
19852 if (!oldOvers[oDD.id]) {
19853 enterEvts.push( oDD );
19854 // subsequent drag overs: dragOver fires
19856 overEvts.push( oDD );
19859 this.dragOvers[oDD.id] = oDD;
19867 if (outEvts.length) {
19868 dc.b4DragOut(e, outEvts);
19869 dc.onDragOut(e, outEvts);
19872 if (enterEvts.length) {
19873 dc.onDragEnter(e, enterEvts);
19876 if (overEvts.length) {
19877 dc.b4DragOver(e, overEvts);
19878 dc.onDragOver(e, overEvts);
19881 if (dropEvts.length) {
19882 dc.b4DragDrop(e, dropEvts);
19883 dc.onDragDrop(e, dropEvts);
19887 // fire dragout events
19889 for (i=0, len=outEvts.length; i<len; ++i) {
19890 dc.b4DragOut(e, outEvts[i].id);
19891 dc.onDragOut(e, outEvts[i].id);
19894 // fire enter events
19895 for (i=0,len=enterEvts.length; i<len; ++i) {
19896 // dc.b4DragEnter(e, oDD.id);
19897 dc.onDragEnter(e, enterEvts[i].id);
19900 // fire over events
19901 for (i=0,len=overEvts.length; i<len; ++i) {
19902 dc.b4DragOver(e, overEvts[i].id);
19903 dc.onDragOver(e, overEvts[i].id);
19906 // fire drop events
19907 for (i=0, len=dropEvts.length; i<len; ++i) {
19908 dc.b4DragDrop(e, dropEvts[i].id);
19909 dc.onDragDrop(e, dropEvts[i].id);
19914 // notify about a drop that did not find a target
19915 if (isDrop && !dropEvts.length) {
19916 dc.onInvalidDrop(e);
19922 * Helper function for getting the best match from the list of drag
19923 * and drop objects returned by the drag and drop events when we are
19924 * in INTERSECT mode. It returns either the first object that the
19925 * cursor is over, or the object that has the greatest overlap with
19926 * the dragged element.
19927 * @method getBestMatch
19928 * @param {DragDrop[]} dds The array of drag and drop objects
19930 * @return {DragDrop} The best single match
19933 getBestMatch: function(dds) {
19935 // Return null if the input is not what we expect
19936 //if (!dds || !dds.length || dds.length == 0) {
19938 // If there is only one item, it wins
19939 //} else if (dds.length == 1) {
19941 var len = dds.length;
19946 // Loop through the targeted items
19947 for (var i=0; i<len; ++i) {
19949 // If the cursor is over the object, it wins. If the
19950 // cursor is over multiple matches, the first one we come
19952 if (dd.cursorIsOver) {
19955 // Otherwise the object with the most overlap wins
19958 winner.overlap.getArea() < dd.overlap.getArea()) {
19969 * Refreshes the cache of the top-left and bottom-right points of the
19970 * drag and drop objects in the specified group(s). This is in the
19971 * format that is stored in the drag and drop instance, so typical
19974 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
19978 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
19980 * @TODO this really should be an indexed array. Alternatively this
19981 * method could accept both.
19982 * @method refreshCache
19983 * @param {Object} groups an associative array of groups to refresh
19986 refreshCache: function(groups) {
19987 for (var sGroup in groups) {
19988 if ("string" != typeof sGroup) {
19991 for (var i in this.ids[sGroup]) {
19992 var oDD = this.ids[sGroup][i];
19994 if (this.isTypeOfDD(oDD)) {
19995 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
19996 var loc = this.getLocation(oDD);
19998 this.locationCache[oDD.id] = loc;
20000 delete this.locationCache[oDD.id];
20001 // this will unregister the drag and drop object if
20002 // the element is not in a usable state
20011 * This checks to make sure an element exists and is in the DOM. The
20012 * main purpose is to handle cases where innerHTML is used to remove
20013 * drag and drop objects from the DOM. IE provides an 'unspecified
20014 * error' when trying to access the offsetParent of such an element
20016 * @param {HTMLElement} el the element to check
20017 * @return {boolean} true if the element looks usable
20020 verifyEl: function(el) {
20025 parent = el.offsetParent;
20028 parent = el.offsetParent;
20039 * Returns a Region object containing the drag and drop element's position
20040 * and size, including the padding configured for it
20041 * @method getLocation
20042 * @param {DragDrop} oDD the drag and drop object to get the
20044 * @return {Roo.lib.Region} a Region object representing the total area
20045 * the element occupies, including any padding
20046 * the instance is configured for.
20049 getLocation: function(oDD) {
20050 if (! this.isTypeOfDD(oDD)) {
20054 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
20057 pos= Roo.lib.Dom.getXY(el);
20065 x2 = x1 + el.offsetWidth;
20067 y2 = y1 + el.offsetHeight;
20069 t = y1 - oDD.padding[0];
20070 r = x2 + oDD.padding[1];
20071 b = y2 + oDD.padding[2];
20072 l = x1 - oDD.padding[3];
20074 return new Roo.lib.Region( t, r, b, l );
20078 * Checks the cursor location to see if it over the target
20079 * @method isOverTarget
20080 * @param {Roo.lib.Point} pt The point to evaluate
20081 * @param {DragDrop} oTarget the DragDrop object we are inspecting
20082 * @return {boolean} true if the mouse is over the target
20086 isOverTarget: function(pt, oTarget, intersect) {
20087 // use cache if available
20088 var loc = this.locationCache[oTarget.id];
20089 if (!loc || !this.useCache) {
20090 loc = this.getLocation(oTarget);
20091 this.locationCache[oTarget.id] = loc;
20099 oTarget.cursorIsOver = loc.contains( pt );
20101 // DragDrop is using this as a sanity check for the initial mousedown
20102 // in this case we are done. In POINT mode, if the drag obj has no
20103 // contraints, we are also done. Otherwise we need to evaluate the
20104 // location of the target as related to the actual location of the
20105 // dragged element.
20106 var dc = this.dragCurrent;
20107 if (!dc || !dc.getTargetCoord ||
20108 (!intersect && !dc.constrainX && !dc.constrainY)) {
20109 return oTarget.cursorIsOver;
20112 oTarget.overlap = null;
20114 // Get the current location of the drag element, this is the
20115 // location of the mouse event less the delta that represents
20116 // where the original mousedown happened on the element. We
20117 // need to consider constraints and ticks as well.
20118 var pos = dc.getTargetCoord(pt.x, pt.y);
20120 var el = dc.getDragEl();
20121 var curRegion = new Roo.lib.Region( pos.y,
20122 pos.x + el.offsetWidth,
20123 pos.y + el.offsetHeight,
20126 var overlap = curRegion.intersect(loc);
20129 oTarget.overlap = overlap;
20130 return (intersect) ? true : oTarget.cursorIsOver;
20137 * unload event handler
20138 * @method _onUnload
20142 _onUnload: function(e, me) {
20143 Roo.dd.DragDropMgr.unregAll();
20147 * Cleans up the drag and drop events and objects.
20152 unregAll: function() {
20154 if (this.dragCurrent) {
20156 this.dragCurrent = null;
20159 this._execOnAll("unreg", []);
20161 for (i in this.elementCache) {
20162 delete this.elementCache[i];
20165 this.elementCache = {};
20170 * A cache of DOM elements
20171 * @property elementCache
20178 * Get the wrapper for the DOM element specified
20179 * @method getElWrapper
20180 * @param {String} id the id of the element to get
20181 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
20183 * @deprecated This wrapper isn't that useful
20186 getElWrapper: function(id) {
20187 var oWrapper = this.elementCache[id];
20188 if (!oWrapper || !oWrapper.el) {
20189 oWrapper = this.elementCache[id] =
20190 new this.ElementWrapper(Roo.getDom(id));
20196 * Returns the actual DOM element
20197 * @method getElement
20198 * @param {String} id the id of the elment to get
20199 * @return {Object} The element
20200 * @deprecated use Roo.getDom instead
20203 getElement: function(id) {
20204 return Roo.getDom(id);
20208 * Returns the style property for the DOM element (i.e.,
20209 * document.getElById(id).style)
20211 * @param {String} id the id of the elment to get
20212 * @return {Object} The style property of the element
20213 * @deprecated use Roo.getDom instead
20216 getCss: function(id) {
20217 var el = Roo.getDom(id);
20218 return (el) ? el.style : null;
20222 * Inner class for cached elements
20223 * @class DragDropMgr.ElementWrapper
20228 ElementWrapper: function(el) {
20233 this.el = el || null;
20238 this.id = this.el && el.id;
20240 * A reference to the style property
20243 this.css = this.el && el.style;
20247 * Returns the X position of an html element
20249 * @param el the element for which to get the position
20250 * @return {int} the X coordinate
20252 * @deprecated use Roo.lib.Dom.getX instead
20255 getPosX: function(el) {
20256 return Roo.lib.Dom.getX(el);
20260 * Returns the Y position of an html element
20262 * @param el the element for which to get the position
20263 * @return {int} the Y coordinate
20264 * @deprecated use Roo.lib.Dom.getY instead
20267 getPosY: function(el) {
20268 return Roo.lib.Dom.getY(el);
20272 * Swap two nodes. In IE, we use the native method, for others we
20273 * emulate the IE behavior
20275 * @param n1 the first node to swap
20276 * @param n2 the other node to swap
20279 swapNode: function(n1, n2) {
20283 var p = n2.parentNode;
20284 var s = n2.nextSibling;
20287 p.insertBefore(n1, n2);
20288 } else if (n2 == n1.nextSibling) {
20289 p.insertBefore(n2, n1);
20291 n1.parentNode.replaceChild(n2, n1);
20292 p.insertBefore(n1, s);
20298 * Returns the current scroll position
20299 * @method getScroll
20303 getScroll: function () {
20304 var t, l, dde=document.documentElement, db=document.body;
20305 if (dde && (dde.scrollTop || dde.scrollLeft)) {
20307 l = dde.scrollLeft;
20314 return { top: t, left: l };
20318 * Returns the specified element style property
20320 * @param {HTMLElement} el the element
20321 * @param {string} styleProp the style property
20322 * @return {string} The value of the style property
20323 * @deprecated use Roo.lib.Dom.getStyle
20326 getStyle: function(el, styleProp) {
20327 return Roo.fly(el).getStyle(styleProp);
20331 * Gets the scrollTop
20332 * @method getScrollTop
20333 * @return {int} the document's scrollTop
20336 getScrollTop: function () { return this.getScroll().top; },
20339 * Gets the scrollLeft
20340 * @method getScrollLeft
20341 * @return {int} the document's scrollTop
20344 getScrollLeft: function () { return this.getScroll().left; },
20347 * Sets the x/y position of an element to the location of the
20350 * @param {HTMLElement} moveEl The element to move
20351 * @param {HTMLElement} targetEl The position reference element
20354 moveToEl: function (moveEl, targetEl) {
20355 var aCoord = Roo.lib.Dom.getXY(targetEl);
20356 Roo.lib.Dom.setXY(moveEl, aCoord);
20360 * Numeric array sort function
20361 * @method numericSort
20364 numericSort: function(a, b) { return (a - b); },
20368 * @property _timeoutCount
20375 * Trying to make the load order less important. Without this we get
20376 * an error if this file is loaded before the Event Utility.
20377 * @method _addListeners
20381 _addListeners: function() {
20382 var DDM = Roo.dd.DDM;
20383 if ( Roo.lib.Event && document ) {
20386 if (DDM._timeoutCount > 2000) {
20388 setTimeout(DDM._addListeners, 10);
20389 if (document && document.body) {
20390 DDM._timeoutCount += 1;
20397 * Recursively searches the immediate parent and all child nodes for
20398 * the handle element in order to determine wheter or not it was
20400 * @method handleWasClicked
20401 * @param node the html element to inspect
20404 handleWasClicked: function(node, id) {
20405 if (this.isHandle(id, node.id)) {
20408 // check to see if this is a text node child of the one we want
20409 var p = node.parentNode;
20412 if (this.isHandle(id, p.id)) {
20427 // shorter alias, save a few bytes
20428 Roo.dd.DDM = Roo.dd.DragDropMgr;
20429 Roo.dd.DDM._addListeners();
20433 * Ext JS Library 1.1.1
20434 * Copyright(c) 2006-2007, Ext JS, LLC.
20436 * Originally Released Under LGPL - original licence link has changed is not relivant.
20439 * <script type="text/javascript">
20444 * A DragDrop implementation where the linked element follows the
20445 * mouse cursor during a drag.
20446 * @extends Roo.dd.DragDrop
20448 * @param {String} id the id of the linked element
20449 * @param {String} sGroup the group of related DragDrop items
20450 * @param {object} config an object containing configurable attributes
20451 * Valid properties for DD:
20454 Roo.dd.DD = function(id, sGroup, config) {
20456 this.init(id, sGroup, config);
20460 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
20463 * When set to true, the utility automatically tries to scroll the browser
20464 * window wehn a drag and drop element is dragged near the viewport boundary.
20465 * Defaults to true.
20472 * Sets the pointer offset to the distance between the linked element's top
20473 * left corner and the location the element was clicked
20474 * @method autoOffset
20475 * @param {int} iPageX the X coordinate of the click
20476 * @param {int} iPageY the Y coordinate of the click
20478 autoOffset: function(iPageX, iPageY) {
20479 var x = iPageX - this.startPageX;
20480 var y = iPageY - this.startPageY;
20481 this.setDelta(x, y);
20485 * Sets the pointer offset. You can call this directly to force the
20486 * offset to be in a particular location (e.g., pass in 0,0 to set it
20487 * to the center of the object)
20489 * @param {int} iDeltaX the distance from the left
20490 * @param {int} iDeltaY the distance from the top
20492 setDelta: function(iDeltaX, iDeltaY) {
20493 this.deltaX = iDeltaX;
20494 this.deltaY = iDeltaY;
20498 * Sets the drag element to the location of the mousedown or click event,
20499 * maintaining the cursor location relative to the location on the element
20500 * that was clicked. Override this if you want to place the element in a
20501 * location other than where the cursor is.
20502 * @method setDragElPos
20503 * @param {int} iPageX the X coordinate of the mousedown or drag event
20504 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20506 setDragElPos: function(iPageX, iPageY) {
20507 // the first time we do this, we are going to check to make sure
20508 // the element has css positioning
20510 var el = this.getDragEl();
20511 this.alignElWithMouse(el, iPageX, iPageY);
20515 * Sets the element to the location of the mousedown or click event,
20516 * maintaining the cursor location relative to the location on the element
20517 * that was clicked. Override this if you want to place the element in a
20518 * location other than where the cursor is.
20519 * @method alignElWithMouse
20520 * @param {HTMLElement} el the element to move
20521 * @param {int} iPageX the X coordinate of the mousedown or drag event
20522 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20524 alignElWithMouse: function(el, iPageX, iPageY) {
20525 var oCoord = this.getTargetCoord(iPageX, iPageY);
20526 var fly = el.dom ? el : Roo.fly(el);
20527 if (!this.deltaSetXY) {
20528 var aCoord = [oCoord.x, oCoord.y];
20530 var newLeft = fly.getLeft(true);
20531 var newTop = fly.getTop(true);
20532 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
20534 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
20537 this.cachePosition(oCoord.x, oCoord.y);
20538 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
20543 * Saves the most recent position so that we can reset the constraints and
20544 * tick marks on-demand. We need to know this so that we can calculate the
20545 * number of pixels the element is offset from its original position.
20546 * @method cachePosition
20547 * @param iPageX the current x position (optional, this just makes it so we
20548 * don't have to look it up again)
20549 * @param iPageY the current y position (optional, this just makes it so we
20550 * don't have to look it up again)
20552 cachePosition: function(iPageX, iPageY) {
20554 this.lastPageX = iPageX;
20555 this.lastPageY = iPageY;
20557 var aCoord = Roo.lib.Dom.getXY(this.getEl());
20558 this.lastPageX = aCoord[0];
20559 this.lastPageY = aCoord[1];
20564 * Auto-scroll the window if the dragged object has been moved beyond the
20565 * visible window boundary.
20566 * @method autoScroll
20567 * @param {int} x the drag element's x position
20568 * @param {int} y the drag element's y position
20569 * @param {int} h the height of the drag element
20570 * @param {int} w the width of the drag element
20573 autoScroll: function(x, y, h, w) {
20576 // The client height
20577 var clientH = Roo.lib.Dom.getViewWidth();
20579 // The client width
20580 var clientW = Roo.lib.Dom.getViewHeight();
20582 // The amt scrolled down
20583 var st = this.DDM.getScrollTop();
20585 // The amt scrolled right
20586 var sl = this.DDM.getScrollLeft();
20588 // Location of the bottom of the element
20591 // Location of the right of the element
20594 // The distance from the cursor to the bottom of the visible area,
20595 // adjusted so that we don't scroll if the cursor is beyond the
20596 // element drag constraints
20597 var toBot = (clientH + st - y - this.deltaY);
20599 // The distance from the cursor to the right of the visible area
20600 var toRight = (clientW + sl - x - this.deltaX);
20603 // How close to the edge the cursor must be before we scroll
20604 // var thresh = (document.all) ? 100 : 40;
20607 // How many pixels to scroll per autoscroll op. This helps to reduce
20608 // clunky scrolling. IE is more sensitive about this ... it needs this
20609 // value to be higher.
20610 var scrAmt = (document.all) ? 80 : 30;
20612 // Scroll down if we are near the bottom of the visible page and the
20613 // obj extends below the crease
20614 if ( bot > clientH && toBot < thresh ) {
20615 window.scrollTo(sl, st + scrAmt);
20618 // Scroll up if the window is scrolled down and the top of the object
20619 // goes above the top border
20620 if ( y < st && st > 0 && y - st < thresh ) {
20621 window.scrollTo(sl, st - scrAmt);
20624 // Scroll right if the obj is beyond the right border and the cursor is
20625 // near the border.
20626 if ( right > clientW && toRight < thresh ) {
20627 window.scrollTo(sl + scrAmt, st);
20630 // Scroll left if the window has been scrolled to the right and the obj
20631 // extends past the left border
20632 if ( x < sl && sl > 0 && x - sl < thresh ) {
20633 window.scrollTo(sl - scrAmt, st);
20639 * Finds the location the element should be placed if we want to move
20640 * it to where the mouse location less the click offset would place us.
20641 * @method getTargetCoord
20642 * @param {int} iPageX the X coordinate of the click
20643 * @param {int} iPageY the Y coordinate of the click
20644 * @return an object that contains the coordinates (Object.x and Object.y)
20647 getTargetCoord: function(iPageX, iPageY) {
20650 var x = iPageX - this.deltaX;
20651 var y = iPageY - this.deltaY;
20653 if (this.constrainX) {
20654 if (x < this.minX) { x = this.minX; }
20655 if (x > this.maxX) { x = this.maxX; }
20658 if (this.constrainY) {
20659 if (y < this.minY) { y = this.minY; }
20660 if (y > this.maxY) { y = this.maxY; }
20663 x = this.getTick(x, this.xTicks);
20664 y = this.getTick(y, this.yTicks);
20671 * Sets up config options specific to this class. Overrides
20672 * Roo.dd.DragDrop, but all versions of this method through the
20673 * inheritance chain are called
20675 applyConfig: function() {
20676 Roo.dd.DD.superclass.applyConfig.call(this);
20677 this.scroll = (this.config.scroll !== false);
20681 * Event that fires prior to the onMouseDown event. Overrides
20684 b4MouseDown: function(e) {
20685 // this.resetConstraints();
20686 this.autoOffset(e.getPageX(),
20691 * Event that fires prior to the onDrag event. Overrides
20694 b4Drag: function(e) {
20695 this.setDragElPos(e.getPageX(),
20699 toString: function() {
20700 return ("DD " + this.id);
20703 //////////////////////////////////////////////////////////////////////////
20704 // Debugging ygDragDrop events that can be overridden
20705 //////////////////////////////////////////////////////////////////////////
20707 startDrag: function(x, y) {
20710 onDrag: function(e) {
20713 onDragEnter: function(e, id) {
20716 onDragOver: function(e, id) {
20719 onDragOut: function(e, id) {
20722 onDragDrop: function(e, id) {
20725 endDrag: function(e) {
20732 * Ext JS Library 1.1.1
20733 * Copyright(c) 2006-2007, Ext JS, LLC.
20735 * Originally Released Under LGPL - original licence link has changed is not relivant.
20738 * <script type="text/javascript">
20742 * @class Roo.dd.DDProxy
20743 * A DragDrop implementation that inserts an empty, bordered div into
20744 * the document that follows the cursor during drag operations. At the time of
20745 * the click, the frame div is resized to the dimensions of the linked html
20746 * element, and moved to the exact location of the linked element.
20748 * References to the "frame" element refer to the single proxy element that
20749 * was created to be dragged in place of all DDProxy elements on the
20752 * @extends Roo.dd.DD
20754 * @param {String} id the id of the linked html element
20755 * @param {String} sGroup the group of related DragDrop objects
20756 * @param {object} config an object containing configurable attributes
20757 * Valid properties for DDProxy in addition to those in DragDrop:
20758 * resizeFrame, centerFrame, dragElId
20760 Roo.dd.DDProxy = function(id, sGroup, config) {
20762 this.init(id, sGroup, config);
20768 * The default drag frame div id
20769 * @property Roo.dd.DDProxy.dragElId
20773 Roo.dd.DDProxy.dragElId = "ygddfdiv";
20775 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
20778 * By default we resize the drag frame to be the same size as the element
20779 * we want to drag (this is to get the frame effect). We can turn it off
20780 * if we want a different behavior.
20781 * @property resizeFrame
20787 * By default the frame is positioned exactly where the drag element is, so
20788 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
20789 * you do not have constraints on the obj is to have the drag frame centered
20790 * around the cursor. Set centerFrame to true for this effect.
20791 * @property centerFrame
20794 centerFrame: false,
20797 * Creates the proxy element if it does not yet exist
20798 * @method createFrame
20800 createFrame: function() {
20802 var body = document.body;
20804 if (!body || !body.firstChild) {
20805 setTimeout( function() { self.createFrame(); }, 50 );
20809 var div = this.getDragEl();
20812 div = document.createElement("div");
20813 div.id = this.dragElId;
20816 s.position = "absolute";
20817 s.visibility = "hidden";
20819 s.border = "2px solid #aaa";
20822 // appendChild can blow up IE if invoked prior to the window load event
20823 // while rendering a table. It is possible there are other scenarios
20824 // that would cause this to happen as well.
20825 body.insertBefore(div, body.firstChild);
20830 * Initialization for the drag frame element. Must be called in the
20831 * constructor of all subclasses
20832 * @method initFrame
20834 initFrame: function() {
20835 this.createFrame();
20838 applyConfig: function() {
20839 Roo.dd.DDProxy.superclass.applyConfig.call(this);
20841 this.resizeFrame = (this.config.resizeFrame !== false);
20842 this.centerFrame = (this.config.centerFrame);
20843 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
20847 * Resizes the drag frame to the dimensions of the clicked object, positions
20848 * it over the object, and finally displays it
20849 * @method showFrame
20850 * @param {int} iPageX X click position
20851 * @param {int} iPageY Y click position
20854 showFrame: function(iPageX, iPageY) {
20855 var el = this.getEl();
20856 var dragEl = this.getDragEl();
20857 var s = dragEl.style;
20859 this._resizeProxy();
20861 if (this.centerFrame) {
20862 this.setDelta( Math.round(parseInt(s.width, 10)/2),
20863 Math.round(parseInt(s.height, 10)/2) );
20866 this.setDragElPos(iPageX, iPageY);
20868 Roo.fly(dragEl).show();
20872 * The proxy is automatically resized to the dimensions of the linked
20873 * element when a drag is initiated, unless resizeFrame is set to false
20874 * @method _resizeProxy
20877 _resizeProxy: function() {
20878 if (this.resizeFrame) {
20879 var el = this.getEl();
20880 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
20884 // overrides Roo.dd.DragDrop
20885 b4MouseDown: function(e) {
20886 var x = e.getPageX();
20887 var y = e.getPageY();
20888 this.autoOffset(x, y);
20889 this.setDragElPos(x, y);
20892 // overrides Roo.dd.DragDrop
20893 b4StartDrag: function(x, y) {
20894 // show the drag frame
20895 this.showFrame(x, y);
20898 // overrides Roo.dd.DragDrop
20899 b4EndDrag: function(e) {
20900 Roo.fly(this.getDragEl()).hide();
20903 // overrides Roo.dd.DragDrop
20904 // By default we try to move the element to the last location of the frame.
20905 // This is so that the default behavior mirrors that of Roo.dd.DD.
20906 endDrag: function(e) {
20908 var lel = this.getEl();
20909 var del = this.getDragEl();
20911 // Show the drag frame briefly so we can get its position
20912 del.style.visibility = "";
20915 // Hide the linked element before the move to get around a Safari
20917 lel.style.visibility = "hidden";
20918 Roo.dd.DDM.moveToEl(lel, del);
20919 del.style.visibility = "hidden";
20920 lel.style.visibility = "";
20925 beforeMove : function(){
20929 afterDrag : function(){
20933 toString: function() {
20934 return ("DDProxy " + this.id);
20940 * Ext JS Library 1.1.1
20941 * Copyright(c) 2006-2007, Ext JS, LLC.
20943 * Originally Released Under LGPL - original licence link has changed is not relivant.
20946 * <script type="text/javascript">
20950 * @class Roo.dd.DDTarget
20951 * A DragDrop implementation that does not move, but can be a drop
20952 * target. You would get the same result by simply omitting implementation
20953 * for the event callbacks, but this way we reduce the processing cost of the
20954 * event listener and the callbacks.
20955 * @extends Roo.dd.DragDrop
20957 * @param {String} id the id of the element that is a drop target
20958 * @param {String} sGroup the group of related DragDrop objects
20959 * @param {object} config an object containing configurable attributes
20960 * Valid properties for DDTarget in addition to those in
20964 Roo.dd.DDTarget = function(id, sGroup, config) {
20966 this.initTarget(id, sGroup, config);
20968 if (config.listeners || config.events) {
20969 Roo.dd.DragDrop.superclass.constructor.call(this, {
20970 listeners : config.listeners || {},
20971 events : config.events || {}
20976 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
20977 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
20978 toString: function() {
20979 return ("DDTarget " + this.id);
20984 * Ext JS Library 1.1.1
20985 * Copyright(c) 2006-2007, Ext JS, LLC.
20987 * Originally Released Under LGPL - original licence link has changed is not relivant.
20990 * <script type="text/javascript">
20995 * @class Roo.dd.ScrollManager
20996 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
20997 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
21000 Roo.dd.ScrollManager = function(){
21001 var ddm = Roo.dd.DragDropMgr;
21008 var onStop = function(e){
21013 var triggerRefresh = function(){
21014 if(ddm.dragCurrent){
21015 ddm.refreshCache(ddm.dragCurrent.groups);
21019 var doScroll = function(){
21020 if(ddm.dragCurrent){
21021 var dds = Roo.dd.ScrollManager;
21023 if(proc.el.scroll(proc.dir, dds.increment)){
21027 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
21032 var clearProc = function(){
21034 clearInterval(proc.id);
21041 var startProc = function(el, dir){
21042 Roo.log('scroll startproc');
21046 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
21049 var onFire = function(e, isDrop){
21051 if(isDrop || !ddm.dragCurrent){ return; }
21052 var dds = Roo.dd.ScrollManager;
21053 if(!dragEl || dragEl != ddm.dragCurrent){
21054 dragEl = ddm.dragCurrent;
21055 // refresh regions on drag start
21056 dds.refreshCache();
21059 var xy = Roo.lib.Event.getXY(e);
21060 var pt = new Roo.lib.Point(xy[0], xy[1]);
21061 for(var id in els){
21062 var el = els[id], r = el._region;
21063 if(r && r.contains(pt) && el.isScrollable()){
21064 if(r.bottom - pt.y <= dds.thresh){
21066 startProc(el, "down");
21069 }else if(r.right - pt.x <= dds.thresh){
21071 startProc(el, "left");
21074 }else if(pt.y - r.top <= dds.thresh){
21076 startProc(el, "up");
21079 }else if(pt.x - r.left <= dds.thresh){
21081 startProc(el, "right");
21090 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
21091 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
21095 * Registers new overflow element(s) to auto scroll
21096 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
21098 register : function(el){
21099 if(el instanceof Array){
21100 for(var i = 0, len = el.length; i < len; i++) {
21101 this.register(el[i]);
21107 Roo.dd.ScrollManager.els = els;
21111 * Unregisters overflow element(s) so they are no longer scrolled
21112 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
21114 unregister : function(el){
21115 if(el instanceof Array){
21116 for(var i = 0, len = el.length; i < len; i++) {
21117 this.unregister(el[i]);
21126 * The number of pixels from the edge of a container the pointer needs to be to
21127 * trigger scrolling (defaults to 25)
21133 * The number of pixels to scroll in each scroll increment (defaults to 50)
21139 * The frequency of scrolls in milliseconds (defaults to 500)
21145 * True to animate the scroll (defaults to true)
21151 * The animation duration in seconds -
21152 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
21158 * Manually trigger a cache refresh.
21160 refreshCache : function(){
21161 for(var id in els){
21162 if(typeof els[id] == 'object'){ // for people extending the object prototype
21163 els[id]._region = els[id].getRegion();
21170 * Ext JS Library 1.1.1
21171 * Copyright(c) 2006-2007, Ext JS, LLC.
21173 * Originally Released Under LGPL - original licence link has changed is not relivant.
21176 * <script type="text/javascript">
21181 * @class Roo.dd.Registry
21182 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
21183 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
21186 Roo.dd.Registry = function(){
21189 var autoIdSeed = 0;
21191 var getId = function(el, autogen){
21192 if(typeof el == "string"){
21196 if(!id && autogen !== false){
21197 id = "roodd-" + (++autoIdSeed);
21205 * Register a drag drop element
21206 * @param {String|HTMLElement} element The id or DOM node to register
21207 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
21208 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
21209 * knows how to interpret, plus there are some specific properties known to the Registry that should be
21210 * populated in the data object (if applicable):
21212 Value Description<br />
21213 --------- ------------------------------------------<br />
21214 handles Array of DOM nodes that trigger dragging<br />
21215 for the element being registered<br />
21216 isHandle True if the element passed in triggers<br />
21217 dragging itself, else false
21220 register : function(el, data){
21222 if(typeof el == "string"){
21223 el = document.getElementById(el);
21226 elements[getId(el)] = data;
21227 if(data.isHandle !== false){
21228 handles[data.ddel.id] = data;
21231 var hs = data.handles;
21232 for(var i = 0, len = hs.length; i < len; i++){
21233 handles[getId(hs[i])] = data;
21239 * Unregister a drag drop element
21240 * @param {String|HTMLElement} element The id or DOM node to unregister
21242 unregister : function(el){
21243 var id = getId(el, false);
21244 var data = elements[id];
21246 delete elements[id];
21248 var hs = data.handles;
21249 for(var i = 0, len = hs.length; i < len; i++){
21250 delete handles[getId(hs[i], false)];
21257 * Returns the handle registered for a DOM Node by id
21258 * @param {String|HTMLElement} id The DOM node or id to look up
21259 * @return {Object} handle The custom handle data
21261 getHandle : function(id){
21262 if(typeof id != "string"){ // must be element?
21265 return handles[id];
21269 * Returns the handle that is registered for the DOM node that is the target of the event
21270 * @param {Event} e The event
21271 * @return {Object} handle The custom handle data
21273 getHandleFromEvent : function(e){
21274 var t = Roo.lib.Event.getTarget(e);
21275 return t ? handles[t.id] : null;
21279 * Returns a custom data object that is registered for a DOM node by id
21280 * @param {String|HTMLElement} id The DOM node or id to look up
21281 * @return {Object} data The custom data
21283 getTarget : function(id){
21284 if(typeof id != "string"){ // must be element?
21287 return elements[id];
21291 * Returns a custom data object that is registered for the DOM node that is the target of the event
21292 * @param {Event} e The event
21293 * @return {Object} data The custom data
21295 getTargetFromEvent : function(e){
21296 var t = Roo.lib.Event.getTarget(e);
21297 return t ? elements[t.id] || handles[t.id] : null;
21302 * Ext JS Library 1.1.1
21303 * Copyright(c) 2006-2007, Ext JS, LLC.
21305 * Originally Released Under LGPL - original licence link has changed is not relivant.
21308 * <script type="text/javascript">
21313 * @class Roo.dd.StatusProxy
21314 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
21315 * default drag proxy used by all Roo.dd components.
21317 * @param {Object} config
21319 Roo.dd.StatusProxy = function(config){
21320 Roo.apply(this, config);
21321 this.id = this.id || Roo.id();
21322 this.el = new Roo.Layer({
21324 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
21325 {tag: "div", cls: "x-dd-drop-icon"},
21326 {tag: "div", cls: "x-dd-drag-ghost"}
21329 shadow: !config || config.shadow !== false
21331 this.ghost = Roo.get(this.el.dom.childNodes[1]);
21332 this.dropStatus = this.dropNotAllowed;
21335 Roo.dd.StatusProxy.prototype = {
21337 * @cfg {String} dropAllowed
21338 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
21340 dropAllowed : "x-dd-drop-ok",
21342 * @cfg {String} dropNotAllowed
21343 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
21345 dropNotAllowed : "x-dd-drop-nodrop",
21348 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
21349 * over the current target element.
21350 * @param {String} cssClass The css class for the new drop status indicator image
21352 setStatus : function(cssClass){
21353 cssClass = cssClass || this.dropNotAllowed;
21354 if(this.dropStatus != cssClass){
21355 this.el.replaceClass(this.dropStatus, cssClass);
21356 this.dropStatus = cssClass;
21361 * Resets the status indicator to the default dropNotAllowed value
21362 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
21364 reset : function(clearGhost){
21365 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
21366 this.dropStatus = this.dropNotAllowed;
21368 this.ghost.update("");
21373 * Updates the contents of the ghost element
21374 * @param {String} html The html that will replace the current innerHTML of the ghost element
21376 update : function(html){
21377 if(typeof html == "string"){
21378 this.ghost.update(html);
21380 this.ghost.update("");
21381 html.style.margin = "0";
21382 this.ghost.dom.appendChild(html);
21384 // ensure float = none set?? cant remember why though.
21385 var el = this.ghost.dom.firstChild;
21387 Roo.fly(el).setStyle('float', 'none');
21392 * Returns the underlying proxy {@link Roo.Layer}
21393 * @return {Roo.Layer} el
21395 getEl : function(){
21400 * Returns the ghost element
21401 * @return {Roo.Element} el
21403 getGhost : function(){
21409 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
21411 hide : function(clear){
21419 * Stops the repair animation if it's currently running
21422 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
21428 * Displays this proxy
21435 * Force the Layer to sync its shadow and shim positions to the element
21442 * Causes the proxy to return to its position of origin via an animation. Should be called after an
21443 * invalid drop operation by the item being dragged.
21444 * @param {Array} xy The XY position of the element ([x, y])
21445 * @param {Function} callback The function to call after the repair is complete
21446 * @param {Object} scope The scope in which to execute the callback
21448 repair : function(xy, callback, scope){
21449 this.callback = callback;
21450 this.scope = scope;
21451 if(xy && this.animRepair !== false){
21452 this.el.addClass("x-dd-drag-repair");
21453 this.el.hideUnders(true);
21454 this.anim = this.el.shift({
21455 duration: this.repairDuration || .5,
21459 callback: this.afterRepair,
21463 this.afterRepair();
21468 afterRepair : function(){
21470 if(typeof this.callback == "function"){
21471 this.callback.call(this.scope || this);
21473 this.callback = null;
21478 * Ext JS Library 1.1.1
21479 * Copyright(c) 2006-2007, Ext JS, LLC.
21481 * Originally Released Under LGPL - original licence link has changed is not relivant.
21484 * <script type="text/javascript">
21488 * @class Roo.dd.DragSource
21489 * @extends Roo.dd.DDProxy
21490 * A simple class that provides the basic implementation needed to make any element draggable.
21492 * @param {String/HTMLElement/Element} el The container element
21493 * @param {Object} config
21495 Roo.dd.DragSource = function(el, config){
21496 this.el = Roo.get(el);
21497 this.dragData = {};
21499 Roo.apply(this, config);
21502 this.proxy = new Roo.dd.StatusProxy();
21505 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
21506 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
21508 this.dragging = false;
21511 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
21513 * @cfg {String} dropAllowed
21514 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21516 dropAllowed : "x-dd-drop-ok",
21518 * @cfg {String} dropNotAllowed
21519 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21521 dropNotAllowed : "x-dd-drop-nodrop",
21524 * Returns the data object associated with this drag source
21525 * @return {Object} data An object containing arbitrary data
21527 getDragData : function(e){
21528 return this.dragData;
21532 onDragEnter : function(e, id){
21533 var target = Roo.dd.DragDropMgr.getDDById(id);
21534 this.cachedTarget = target;
21535 if(this.beforeDragEnter(target, e, id) !== false){
21536 if(target.isNotifyTarget){
21537 var status = target.notifyEnter(this, e, this.dragData);
21538 this.proxy.setStatus(status);
21540 this.proxy.setStatus(this.dropAllowed);
21543 if(this.afterDragEnter){
21545 * An empty function by default, but provided so that you can perform a custom action
21546 * when the dragged item enters the drop target by providing an implementation.
21547 * @param {Roo.dd.DragDrop} target The drop target
21548 * @param {Event} e The event object
21549 * @param {String} id The id of the dragged element
21550 * @method afterDragEnter
21552 this.afterDragEnter(target, e, id);
21558 * An empty function by default, but provided so that you can perform a custom action
21559 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
21560 * @param {Roo.dd.DragDrop} target The drop target
21561 * @param {Event} e The event object
21562 * @param {String} id The id of the dragged element
21563 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21565 beforeDragEnter : function(target, e, id){
21570 alignElWithMouse: function() {
21571 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
21576 onDragOver : function(e, id){
21577 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21578 if(this.beforeDragOver(target, e, id) !== false){
21579 if(target.isNotifyTarget){
21580 var status = target.notifyOver(this, e, this.dragData);
21581 this.proxy.setStatus(status);
21584 if(this.afterDragOver){
21586 * An empty function by default, but provided so that you can perform a custom action
21587 * while the dragged item is over the drop target by providing an implementation.
21588 * @param {Roo.dd.DragDrop} target The drop target
21589 * @param {Event} e The event object
21590 * @param {String} id The id of the dragged element
21591 * @method afterDragOver
21593 this.afterDragOver(target, e, id);
21599 * An empty function by default, but provided so that you can perform a custom action
21600 * while the dragged item is over the drop target and optionally cancel the onDragOver.
21601 * @param {Roo.dd.DragDrop} target The drop target
21602 * @param {Event} e The event object
21603 * @param {String} id The id of the dragged element
21604 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21606 beforeDragOver : function(target, e, id){
21611 onDragOut : function(e, id){
21612 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21613 if(this.beforeDragOut(target, e, id) !== false){
21614 if(target.isNotifyTarget){
21615 target.notifyOut(this, e, this.dragData);
21617 this.proxy.reset();
21618 if(this.afterDragOut){
21620 * An empty function by default, but provided so that you can perform a custom action
21621 * after the dragged item is dragged out of the target without dropping.
21622 * @param {Roo.dd.DragDrop} target The drop target
21623 * @param {Event} e The event object
21624 * @param {String} id The id of the dragged element
21625 * @method afterDragOut
21627 this.afterDragOut(target, e, id);
21630 this.cachedTarget = null;
21634 * An empty function by default, but provided so that you can perform a custom action before the dragged
21635 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
21636 * @param {Roo.dd.DragDrop} target The drop target
21637 * @param {Event} e The event object
21638 * @param {String} id The id of the dragged element
21639 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21641 beforeDragOut : function(target, e, id){
21646 onDragDrop : function(e, id){
21647 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21648 if(this.beforeDragDrop(target, e, id) !== false){
21649 if(target.isNotifyTarget){
21650 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
21651 this.onValidDrop(target, e, id);
21653 this.onInvalidDrop(target, e, id);
21656 this.onValidDrop(target, e, id);
21659 if(this.afterDragDrop){
21661 * An empty function by default, but provided so that you can perform a custom action
21662 * after a valid drag drop has occurred by providing an implementation.
21663 * @param {Roo.dd.DragDrop} target The drop target
21664 * @param {Event} e The event object
21665 * @param {String} id The id of the dropped element
21666 * @method afterDragDrop
21668 this.afterDragDrop(target, e, id);
21671 delete this.cachedTarget;
21675 * An empty function by default, but provided so that you can perform a custom action before the dragged
21676 * item is dropped onto the target and optionally cancel the onDragDrop.
21677 * @param {Roo.dd.DragDrop} target The drop target
21678 * @param {Event} e The event object
21679 * @param {String} id The id of the dragged element
21680 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
21682 beforeDragDrop : function(target, e, id){
21687 onValidDrop : function(target, e, id){
21689 if(this.afterValidDrop){
21691 * An empty function by default, but provided so that you can perform a custom action
21692 * after a valid drop has occurred by providing an implementation.
21693 * @param {Object} target The target DD
21694 * @param {Event} e The event object
21695 * @param {String} id The id of the dropped element
21696 * @method afterInvalidDrop
21698 this.afterValidDrop(target, e, id);
21703 getRepairXY : function(e, data){
21704 return this.el.getXY();
21708 onInvalidDrop : function(target, e, id){
21709 this.beforeInvalidDrop(target, e, id);
21710 if(this.cachedTarget){
21711 if(this.cachedTarget.isNotifyTarget){
21712 this.cachedTarget.notifyOut(this, e, this.dragData);
21714 this.cacheTarget = null;
21716 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
21718 if(this.afterInvalidDrop){
21720 * An empty function by default, but provided so that you can perform a custom action
21721 * after an invalid drop has occurred by providing an implementation.
21722 * @param {Event} e The event object
21723 * @param {String} id The id of the dropped element
21724 * @method afterInvalidDrop
21726 this.afterInvalidDrop(e, id);
21731 afterRepair : function(){
21733 this.el.highlight(this.hlColor || "c3daf9");
21735 this.dragging = false;
21739 * An empty function by default, but provided so that you can perform a custom action after an invalid
21740 * drop has occurred.
21741 * @param {Roo.dd.DragDrop} target The drop target
21742 * @param {Event} e The event object
21743 * @param {String} id The id of the dragged element
21744 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
21746 beforeInvalidDrop : function(target, e, id){
21751 handleMouseDown : function(e){
21752 if(this.dragging) {
21755 var data = this.getDragData(e);
21756 if(data && this.onBeforeDrag(data, e) !== false){
21757 this.dragData = data;
21759 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
21764 * An empty function by default, but provided so that you can perform a custom action before the initial
21765 * drag event begins and optionally cancel it.
21766 * @param {Object} data An object containing arbitrary data to be shared with drop targets
21767 * @param {Event} e The event object
21768 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21770 onBeforeDrag : function(data, e){
21775 * An empty function by default, but provided so that you can perform a custom action once the initial
21776 * drag event has begun. The drag cannot be canceled from this function.
21777 * @param {Number} x The x position of the click on the dragged object
21778 * @param {Number} y The y position of the click on the dragged object
21780 onStartDrag : Roo.emptyFn,
21782 // private - YUI override
21783 startDrag : function(x, y){
21784 this.proxy.reset();
21785 this.dragging = true;
21786 this.proxy.update("");
21787 this.onInitDrag(x, y);
21792 onInitDrag : function(x, y){
21793 var clone = this.el.dom.cloneNode(true);
21794 clone.id = Roo.id(); // prevent duplicate ids
21795 this.proxy.update(clone);
21796 this.onStartDrag(x, y);
21801 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
21802 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
21804 getProxy : function(){
21809 * Hides the drag source's {@link Roo.dd.StatusProxy}
21811 hideProxy : function(){
21813 this.proxy.reset(true);
21814 this.dragging = false;
21818 triggerCacheRefresh : function(){
21819 Roo.dd.DDM.refreshCache(this.groups);
21822 // private - override to prevent hiding
21823 b4EndDrag: function(e) {
21826 // private - override to prevent moving
21827 endDrag : function(e){
21828 this.onEndDrag(this.dragData, e);
21832 onEndDrag : function(data, e){
21835 // private - pin to cursor
21836 autoOffset : function(x, y) {
21837 this.setDelta(-12, -20);
21841 * Ext JS Library 1.1.1
21842 * Copyright(c) 2006-2007, Ext JS, LLC.
21844 * Originally Released Under LGPL - original licence link has changed is not relivant.
21847 * <script type="text/javascript">
21852 * @class Roo.dd.DropTarget
21853 * @extends Roo.dd.DDTarget
21854 * A simple class that provides the basic implementation needed to make any element a drop target that can have
21855 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
21857 * @param {String/HTMLElement/Element} el The container element
21858 * @param {Object} config
21860 Roo.dd.DropTarget = function(el, config){
21861 this.el = Roo.get(el);
21863 var listeners = false; ;
21864 if (config && config.listeners) {
21865 listeners= config.listeners;
21866 delete config.listeners;
21868 Roo.apply(this, config);
21870 if(this.containerScroll){
21871 Roo.dd.ScrollManager.register(this.el);
21875 * @scope Roo.dd.DropTarget
21880 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
21881 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
21882 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
21884 * IMPORTANT : it should set this.overClass and this.dropAllowed
21886 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21887 * @param {Event} e The event
21888 * @param {Object} data An object containing arbitrary data supplied by the drag source
21894 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
21895 * This method will be called on every mouse movement while the drag source is over the drop target.
21896 * This default implementation simply returns the dropAllowed config value.
21898 * IMPORTANT : it should set this.dropAllowed
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 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
21909 * out of the target without dropping. This default implementation simply removes the CSS class specified by
21910 * overClass (if any) from the drop element.
21912 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21913 * @param {Event} e The event
21914 * @param {Object} data An object containing arbitrary data supplied by the drag source
21920 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
21921 * been dropped on it. This method has no default implementation and returns false, so you must provide an
21922 * implementation that does something to process the drop event and returns true so that the drag source's
21923 * repair action does not run.
21925 * IMPORTANT : it should set this.success
21927 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21928 * @param {Event} e The event
21929 * @param {Object} data An object containing arbitrary data supplied by the drag source
21935 Roo.dd.DropTarget.superclass.constructor.call( this,
21937 this.ddGroup || this.group,
21940 listeners : listeners || {}
21948 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
21950 * @cfg {String} overClass
21951 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
21954 * @cfg {String} ddGroup
21955 * The drag drop group to handle drop events for
21959 * @cfg {String} dropAllowed
21960 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21962 dropAllowed : "x-dd-drop-ok",
21964 * @cfg {String} dropNotAllowed
21965 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21967 dropNotAllowed : "x-dd-drop-nodrop",
21969 * @cfg {boolean} success
21970 * set this after drop listener..
21974 * @cfg {boolean|String} valid true/false or string (ok-add/ok-sub/ok/nodrop)
21975 * if the drop point is valid for over/enter..
21982 isNotifyTarget : true,
21987 notifyEnter : function(dd, e, data)
21990 this.fireEvent('enter', dd, e, data);
21991 if(this.overClass){
21992 this.el.addClass(this.overClass);
21994 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
21995 this.valid ? this.dropAllowed : this.dropNotAllowed
22002 notifyOver : function(dd, e, data)
22005 this.fireEvent('over', dd, e, data);
22006 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
22007 this.valid ? this.dropAllowed : this.dropNotAllowed
22014 notifyOut : function(dd, e, data)
22016 this.fireEvent('out', dd, e, data);
22017 if(this.overClass){
22018 this.el.removeClass(this.overClass);
22025 notifyDrop : function(dd, e, data)
22027 this.success = false;
22028 this.fireEvent('drop', dd, e, data);
22029 return this.success;
22033 * Ext JS Library 1.1.1
22034 * Copyright(c) 2006-2007, Ext JS, LLC.
22036 * Originally Released Under LGPL - original licence link has changed is not relivant.
22039 * <script type="text/javascript">
22044 * @class Roo.dd.DragZone
22045 * @extends Roo.dd.DragSource
22046 * This class provides a container DD instance that proxies for multiple child node sources.<br />
22047 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
22049 * @param {String/HTMLElement/Element} el The container element
22050 * @param {Object} config
22052 Roo.dd.DragZone = function(el, config){
22053 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
22054 if(this.containerScroll){
22055 Roo.dd.ScrollManager.register(this.el);
22059 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
22061 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
22062 * for auto scrolling during drag operations.
22065 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
22066 * method after a failed drop (defaults to "c3daf9" - light blue)
22070 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
22071 * for a valid target to drag based on the mouse down. Override this method
22072 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
22073 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
22074 * @param {EventObject} e The mouse down event
22075 * @return {Object} The dragData
22077 getDragData : function(e){
22078 return Roo.dd.Registry.getHandleFromEvent(e);
22082 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
22083 * this.dragData.ddel
22084 * @param {Number} x The x position of the click on the dragged object
22085 * @param {Number} y The y position of the click on the dragged object
22086 * @return {Boolean} true to continue the drag, false to cancel
22088 onInitDrag : function(x, y){
22089 this.proxy.update(this.dragData.ddel.cloneNode(true));
22090 this.onStartDrag(x, y);
22095 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
22097 afterRepair : function(){
22099 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
22101 this.dragging = false;
22105 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
22106 * the XY of this.dragData.ddel
22107 * @param {EventObject} e The mouse up event
22108 * @return {Array} The xy location (e.g. [100, 200])
22110 getRepairXY : function(e){
22111 return Roo.Element.fly(this.dragData.ddel).getXY();
22115 * Ext JS Library 1.1.1
22116 * Copyright(c) 2006-2007, Ext JS, LLC.
22118 * Originally Released Under LGPL - original licence link has changed is not relivant.
22121 * <script type="text/javascript">
22124 * @class Roo.dd.DropZone
22125 * @extends Roo.dd.DropTarget
22126 * This class provides a container DD instance that proxies for multiple child node targets.<br />
22127 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
22129 * @param {String/HTMLElement/Element} el The container element
22130 * @param {Object} config
22132 Roo.dd.DropZone = function(el, config){
22133 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
22136 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
22138 * Returns a custom data object associated with the DOM node that is the target of the event. By default
22139 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
22140 * provide your own custom lookup.
22141 * @param {Event} e The event
22142 * @return {Object} data The custom data
22144 getTargetFromEvent : function(e){
22145 return Roo.dd.Registry.getTargetFromEvent(e);
22149 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
22150 * that it has registered. This method has no default implementation and should be overridden to provide
22151 * node-specific processing if necessary.
22152 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22153 * {@link #getTargetFromEvent} for this node)
22154 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22155 * @param {Event} e The event
22156 * @param {Object} data An object containing arbitrary data supplied by the drag source
22158 onNodeEnter : function(n, dd, e, data){
22163 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
22164 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
22165 * overridden to provide the proper feedback.
22166 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22167 * {@link #getTargetFromEvent} for this node)
22168 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22169 * @param {Event} e The event
22170 * @param {Object} data An object containing arbitrary data supplied by the drag source
22171 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22172 * underlying {@link Roo.dd.StatusProxy} can be updated
22174 onNodeOver : function(n, dd, e, data){
22175 return this.dropAllowed;
22179 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
22180 * the drop node without dropping. This method has no default implementation and should be overridden to provide
22181 * node-specific processing if necessary.
22182 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22183 * {@link #getTargetFromEvent} for this node)
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
22188 onNodeOut : function(n, dd, e, data){
22193 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
22194 * the drop node. The default implementation returns false, so it should be overridden to provide the
22195 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
22196 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22197 * {@link #getTargetFromEvent} for this node)
22198 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22199 * @param {Event} e The event
22200 * @param {Object} data An object containing arbitrary data supplied by the drag source
22201 * @return {Boolean} True if the drop was valid, else false
22203 onNodeDrop : function(n, dd, e, data){
22208 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
22209 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
22210 * it should be overridden to provide the proper feedback if necessary.
22211 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22212 * @param {Event} e The event
22213 * @param {Object} data An object containing arbitrary data supplied by the drag source
22214 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22215 * underlying {@link Roo.dd.StatusProxy} can be updated
22217 onContainerOver : function(dd, e, data){
22218 return this.dropNotAllowed;
22222 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
22223 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
22224 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
22225 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
22226 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22227 * @param {Event} e The event
22228 * @param {Object} data An object containing arbitrary data supplied by the drag source
22229 * @return {Boolean} True if the drop was valid, else false
22231 onContainerDrop : function(dd, e, data){
22236 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
22237 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
22238 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
22239 * you should override this method and provide a custom implementation.
22240 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22241 * @param {Event} e The event
22242 * @param {Object} data An object containing arbitrary data supplied by the drag source
22243 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22244 * underlying {@link Roo.dd.StatusProxy} can be updated
22246 notifyEnter : function(dd, e, data){
22247 return this.dropNotAllowed;
22251 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
22252 * This method will be called on every mouse movement while the drag source is over the drop zone.
22253 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
22254 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
22255 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
22256 * registered node, it will call {@link #onContainerOver}.
22257 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22258 * @param {Event} e The event
22259 * @param {Object} data An object containing arbitrary data supplied by the drag source
22260 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22261 * underlying {@link Roo.dd.StatusProxy} can be updated
22263 notifyOver : function(dd, e, data){
22264 var n = this.getTargetFromEvent(e);
22265 if(!n){ // not over valid drop target
22266 if(this.lastOverNode){
22267 this.onNodeOut(this.lastOverNode, dd, e, data);
22268 this.lastOverNode = null;
22270 return this.onContainerOver(dd, e, data);
22272 if(this.lastOverNode != n){
22273 if(this.lastOverNode){
22274 this.onNodeOut(this.lastOverNode, dd, e, data);
22276 this.onNodeEnter(n, dd, e, data);
22277 this.lastOverNode = n;
22279 return this.onNodeOver(n, dd, e, data);
22283 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
22284 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
22285 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
22286 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
22287 * @param {Event} e The event
22288 * @param {Object} data An object containing arbitrary data supplied by the drag zone
22290 notifyOut : function(dd, e, data){
22291 if(this.lastOverNode){
22292 this.onNodeOut(this.lastOverNode, dd, e, data);
22293 this.lastOverNode = null;
22298 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
22299 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
22300 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
22301 * otherwise it will call {@link #onContainerDrop}.
22302 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22303 * @param {Event} e The event
22304 * @param {Object} data An object containing arbitrary data supplied by the drag source
22305 * @return {Boolean} True if the drop was valid, else false
22307 notifyDrop : function(dd, e, data){
22308 if(this.lastOverNode){
22309 this.onNodeOut(this.lastOverNode, dd, e, data);
22310 this.lastOverNode = null;
22312 var n = this.getTargetFromEvent(e);
22314 this.onNodeDrop(n, dd, e, data) :
22315 this.onContainerDrop(dd, e, data);
22319 triggerCacheRefresh : function(){
22320 Roo.dd.DDM.refreshCache(this.groups);