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 isAndroid = /android/.test(ua),
68 isTouch = (function() {
70 if (ua.indexOf('chrome') != -1 && ua.indexOf('android') == -1) {
71 window.addEventListener('touchstart', function __set_has_touch__ () {
73 window.removeEventListener('touchstart', __set_has_touch__);
75 return false; // no touch on chrome!?
77 document.createEvent("TouchEvent");
84 // remove css image flicker
87 document.execCommand("BackgroundImageCache", false, true);
93 * True if the browser is in strict mode
98 * True if the page is running over SSL
103 * True when the document is fully initialized and ready for action
108 * Turn on debugging output (currently only the factory uses this)
115 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
118 enableGarbageCollector : true,
121 * True to automatically purge event listeners after uncaching an element (defaults to false).
122 * Note: this only happens if enableGarbageCollector is true.
125 enableListenerCollection:false,
128 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
129 * the IE insecure content warning (defaults to javascript:false).
132 SSL_SECURE_URL : "javascript:false",
135 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
136 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
139 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
141 emptyFn : function(){},
144 * Copies all the properties of config to obj if they don't already exist.
145 * @param {Object} obj The receiver of the properties
146 * @param {Object} config The source of the properties
147 * @return {Object} returns obj
149 applyIf : function(o, c){
152 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
159 * Applies event listeners to elements by selectors when the document is ready.
160 * The event name is specified with an @ suffix.
163 // add a listener for click on all anchors in element with id foo
164 '#foo a@click' : function(e, t){
168 // add the same listener to multiple selectors (separated by comma BEFORE the @)
169 '#foo a, #bar span.some-class@mouseover' : function(){
174 * @param {Object} obj The list of behaviors to apply
176 addBehaviors : function(o){
178 Roo.onReady(function(){
183 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
185 var parts = b.split('@');
186 if(parts[1]){ // for Object prototype breakers
189 cache[s] = Roo.select(s);
191 cache[s].on(parts[1], o[b]);
198 * Generates unique ids. If the element already has an id, it is unchanged
199 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
200 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
201 * @return {String} The generated Id.
203 id : function(el, prefix){
204 prefix = prefix || "roo-gen";
206 var id = prefix + (++idSeed);
207 return el ? (el.id ? el.id : (el.id = id)) : id;
212 * Extends one class with another class and optionally overrides members with the passed literal. This class
213 * also adds the function "override()" to the class that can be used to override
214 * members on an instance.
215 * @param {Object} subclass The class inheriting the functionality
216 * @param {Object} superclass The class being extended
217 * @param {Object} overrides (optional) A literal with members
222 var io = function(o){
227 return function(sb, sp, overrides){
228 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
231 sb = function(){sp.apply(this, arguments);};
233 var F = function(){}, sbp, spp = sp.prototype;
235 sbp = sb.prototype = new F();
239 if(spp.constructor == Object.prototype.constructor){
244 sb.override = function(o){
248 Roo.override(sb, overrides);
254 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
256 Roo.override(MyClass, {
257 newMethod1: function(){
260 newMethod2: function(foo){
265 * @param {Object} origclass The class to override
266 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
267 * containing one or more methods.
270 override : function(origclass, overrides){
272 var p = origclass.prototype;
273 for(var method in overrides){
274 p[method] = overrides[method];
279 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
281 Roo.namespace('Company', 'Company.data');
282 Company.Widget = function() { ... }
283 Company.data.CustomStore = function(config) { ... }
285 * @param {String} namespace1
286 * @param {String} namespace2
287 * @param {String} etc
290 namespace : function(){
291 var a=arguments, o=null, i, j, d, rt;
292 for (i=0; i<a.length; ++i) {
296 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
297 for (j=1; j<d.length; ++j) {
298 o[d[j]]=o[d[j]] || {};
304 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
306 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
307 Roo.factory(conf, Roo.data);
309 * @param {String} classname
310 * @param {String} namespace (optional)
314 factory : function(c, ns)
316 // no xtype, no ns or c.xns - or forced off by c.xns
317 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
320 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
321 if (c.constructor == ns[c.xtype]) {// already created...
325 if (Roo.debug) { Roo.log("Roo.Factory(" + c.xtype + ")"); }
326 var ret = new ns[c.xtype](c);
330 c.xns = false; // prevent recursion..
334 * Logs to console if it can.
336 * @param {String|Object} string
341 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
348 * 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.
352 urlEncode : function(o){
358 var ov = o[key], k = Roo.encodeURIComponent(key);
359 var type = typeof ov;
360 if(type == 'undefined'){
362 }else if(type != "function" && type != "object"){
363 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
364 }else if(ov instanceof Array){
366 for(var i = 0, len = ov.length; i < len; i++) {
367 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
378 * Safe version of encodeURIComponent
379 * @param {String} data
383 encodeURIComponent : function (data)
386 return encodeURIComponent(data);
387 } catch(e) {} // should be an uri encode error.
389 if (data == '' || data == null){
392 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
393 function nibble_to_hex(nibble){
394 var chars = '0123456789ABCDEF';
395 return chars.charAt(nibble);
397 data = data.toString();
399 for(var i=0; i<data.length; i++){
400 var c = data.charCodeAt(i);
401 var bs = new Array();
404 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
405 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
406 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
407 bs[3] = 0x80 | (c & 0x3F);
408 }else if (c > 0x800){
410 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
411 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
412 bs[2] = 0x80 | (c & 0x3F);
415 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
416 bs[1] = 0x80 | (c & 0x3F);
421 for(var j=0; j<bs.length; j++){
423 var hex = nibble_to_hex((b & 0xF0) >>> 4)
424 + nibble_to_hex(b &0x0F);
433 * 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]}.
434 * @param {String} string
435 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
436 * @return {Object} A literal with members
438 urlDecode : function(string, overwrite){
439 if(!string || !string.length){
443 var pairs = string.split('&');
444 var pair, name, value;
445 for(var i = 0, len = pairs.length; i < len; i++){
446 pair = pairs[i].split('=');
447 name = decodeURIComponent(pair[0]);
448 value = decodeURIComponent(pair[1]);
449 if(overwrite !== true){
450 if(typeof obj[name] == "undefined"){
452 }else if(typeof obj[name] == "string"){
453 obj[name] = [obj[name]];
454 obj[name].push(value);
456 obj[name].push(value);
466 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
467 * passed array is not really an array, your function is called once with it.
468 * The supplied function is called with (Object item, Number index, Array allItems).
469 * @param {Array/NodeList/Mixed} array
470 * @param {Function} fn
471 * @param {Object} scope
473 each : function(array, fn, scope){
474 if(typeof array.length == "undefined" || typeof array == "string"){
477 for(var i = 0, len = array.length; i < len; i++){
478 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
483 combine : function(){
484 var as = arguments, l = as.length, r = [];
485 for(var i = 0; i < l; i++){
487 if(a instanceof Array){
489 }else if(a.length !== undefined && !a.substr){
490 r = r.concat(Array.prototype.slice.call(a, 0));
499 * Escapes the passed string for use in a regular expression
500 * @param {String} str
503 escapeRe : function(s) {
504 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
508 callback : function(cb, scope, args, delay){
509 if(typeof cb == "function"){
511 cb.defer(delay, scope, args || []);
513 cb.apply(scope, args || []);
519 * Return the dom node for the passed string (id), dom node, or Roo.Element
520 * @param {String/HTMLElement/Roo.Element} el
521 * @return HTMLElement
523 getDom : function(el){
527 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
531 * Shorthand for {@link Roo.ComponentMgr#get}
533 * @return Roo.Component
535 getCmp : function(id){
536 return Roo.ComponentMgr.get(id);
539 num : function(v, defaultValue){
540 if(typeof v != 'number'){
546 destroy : function(){
547 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
551 as.removeAllListeners();
555 if(typeof as.purgeListeners == 'function'){
558 if(typeof as.destroy == 'function'){
565 // inpired by a similar function in mootools library
567 * Returns the type of object that is passed in. If the object passed in is null or undefined it
568 * return false otherwise it returns one of the following values:<ul>
569 * <li><b>string</b>: If the object passed is a string</li>
570 * <li><b>number</b>: If the object passed is a number</li>
571 * <li><b>boolean</b>: If the object passed is a boolean value</li>
572 * <li><b>function</b>: If the object passed is a function reference</li>
573 * <li><b>object</b>: If the object passed is an object</li>
574 * <li><b>array</b>: If the object passed is an array</li>
575 * <li><b>regexp</b>: If the object passed is a regular expression</li>
576 * <li><b>element</b>: If the object passed is a DOM Element</li>
577 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
578 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
579 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
580 * @param {Mixed} object
584 if(o === undefined || o === null){
591 if(t == 'object' && o.nodeName) {
593 case 1: return 'element';
594 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
597 if(t == 'object' || t == 'function') {
598 switch(o.constructor) {
599 case Array: return 'array';
600 case RegExp: return 'regexp';
602 if(typeof o.length == 'number' && typeof o.item == 'function') {
610 * Returns true if the passed value is null, undefined or an empty string (optional).
611 * @param {Mixed} value The value to test
612 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
615 isEmpty : function(v, allowBlank){
616 return v === null || v === undefined || (!allowBlank ? v === '' : false);
624 isFirefox : isFirefox,
634 isBorderBox : isBorderBox,
636 isWindows : isWindows,
644 isAndroid : isAndroid,
649 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
650 * you may want to set this to true.
653 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
658 * Selects a single element as a Roo Element
659 * This is about as close as you can get to jQuery's $('do crazy stuff')
660 * @param {String} selector The selector/xpath query
661 * @param {Node} root (optional) The start of the query (defaults to document).
662 * @return {Roo.Element}
664 selectNode : function(selector, root)
666 var node = Roo.DomQuery.selectNode(selector,root);
667 return node ? Roo.get(node) : new Roo.Element(false);
675 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
676 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout",
679 "Roo.bootstrap.dash");
682 * Ext JS Library 1.1.1
683 * Copyright(c) 2006-2007, Ext JS, LLC.
685 * Originally Released Under LGPL - original licence link has changed is not relivant.
688 * <script type="text/javascript">
692 // wrappedn so fnCleanup is not in global scope...
694 function fnCleanUp() {
695 var p = Function.prototype;
696 delete p.createSequence;
698 delete p.createDelegate;
699 delete p.createCallback;
700 delete p.createInterceptor;
702 window.detachEvent("onunload", fnCleanUp);
704 window.attachEvent("onunload", fnCleanUp);
711 * These functions are available on every Function object (any JavaScript function).
713 Roo.apply(Function.prototype, {
715 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
716 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
717 * Will create a function that is bound to those 2 args.
718 * @return {Function} The new function
720 createCallback : function(/*args...*/){
721 // make args available, in function below
722 var args = arguments;
725 return method.apply(window, args);
730 * Creates a delegate (callback) that sets the scope to obj.
731 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
732 * Will create a function that is automatically scoped to this.
733 * @param {Object} obj (optional) The object for which the scope is set
734 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
735 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
736 * if a number the args are inserted at the specified position
737 * @return {Function} The new function
739 createDelegate : function(obj, args, appendArgs){
742 var callArgs = args || arguments;
743 if(appendArgs === true){
744 callArgs = Array.prototype.slice.call(arguments, 0);
745 callArgs = callArgs.concat(args);
746 }else if(typeof appendArgs == "number"){
747 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
748 var applyArgs = [appendArgs, 0].concat(args); // create method call params
749 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
751 return method.apply(obj || window, callArgs);
756 * Calls this function after the number of millseconds specified.
757 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
758 * @param {Object} obj (optional) The object for which the scope is set
759 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
760 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
761 * if a number the args are inserted at the specified position
762 * @return {Number} The timeout id that can be used with clearTimeout
764 defer : function(millis, obj, args, appendArgs){
765 var fn = this.createDelegate(obj, args, appendArgs);
767 return setTimeout(fn, millis);
773 * Create a combined function call sequence of the original function + the passed function.
774 * The resulting function returns the results of the original function.
775 * The passed fcn is called with the parameters of the original function
776 * @param {Function} fcn The function to sequence
777 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
778 * @return {Function} The new function
780 createSequence : function(fcn, scope){
781 if(typeof fcn != "function"){
786 var retval = method.apply(this || window, arguments);
787 fcn.apply(scope || this || window, arguments);
793 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
794 * The resulting function returns the results of the original function.
795 * The passed fcn is called with the parameters of the original function.
797 * @param {Function} fcn The function to call before the original
798 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
799 * @return {Function} The new function
801 createInterceptor : function(fcn, scope){
802 if(typeof fcn != "function"){
809 if(fcn.apply(scope || this || window, arguments) === false){
812 return method.apply(this || window, arguments);
818 * Ext JS Library 1.1.1
819 * Copyright(c) 2006-2007, Ext JS, LLC.
821 * Originally Released Under LGPL - original licence link has changed is not relivant.
824 * <script type="text/javascript">
827 Roo.applyIf(String, {
832 * Escapes the passed string for ' and \
833 * @param {String} string The string to escape
834 * @return {String} The escaped string
837 escape : function(string) {
838 return string.replace(/('|\\)/g, "\\$1");
842 * Pads the left side of a string with a specified character. This is especially useful
843 * for normalizing number and date strings. Example usage:
845 var s = String.leftPad('123', 5, '0');
846 // s now contains the string: '00123'
848 * @param {String} string The original string
849 * @param {Number} size The total length of the output string
850 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
851 * @return {String} The padded string
854 leftPad : function (val, size, ch) {
855 var result = new String(val);
856 if(ch === null || ch === undefined || ch === '') {
859 while (result.length < size) {
860 result = ch + result;
866 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
867 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
869 var cls = 'my-class', text = 'Some text';
870 var s = String.format('<div class="{0}">{1}</div>', cls, text);
871 // s now contains the string: '<div class="my-class">Some text</div>'
873 * @param {String} string The tokenized string to be formatted
874 * @param {String} value1 The value to replace token {0}
875 * @param {String} value2 Etc...
876 * @return {String} The formatted string
879 format : function(format){
880 var args = Array.prototype.slice.call(arguments, 1);
881 return format.replace(/\{(\d+)\}/g, function(m, i){
882 return Roo.util.Format.htmlEncode(args[i]);
888 * Utility function that allows you to easily switch a string between two alternating values. The passed value
889 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
890 * they are already different, the first value passed in is returned. Note that this method returns the new value
891 * but does not change the current string.
893 // alternate sort directions
894 sort = sort.toggle('ASC', 'DESC');
896 // instead of conditional logic:
897 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
899 * @param {String} value The value to compare to the current string
900 * @param {String} other The new value to use if the string already equals the first value passed in
901 * @return {String} The new value
904 String.prototype.toggle = function(value, other){
905 return this == value ? other : value;
908 * Ext JS Library 1.1.1
909 * Copyright(c) 2006-2007, Ext JS, LLC.
911 * Originally Released Under LGPL - original licence link has changed is not relivant.
914 * <script type="text/javascript">
920 Roo.applyIf(Number.prototype, {
922 * Checks whether or not the current number is within a desired range. If the number is already within the
923 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
924 * exceeded. Note that this method returns the constrained value but does not change the current number.
925 * @param {Number} min The minimum number in the range
926 * @param {Number} max The maximum number in the range
927 * @return {Number} The constrained value if outside the range, otherwise the current value
929 constrain : function(min, max){
930 return Math.min(Math.max(this, min), max);
934 * Ext JS Library 1.1.1
935 * Copyright(c) 2006-2007, Ext JS, LLC.
937 * Originally Released Under LGPL - original licence link has changed is not relivant.
940 * <script type="text/javascript">
945 Roo.applyIf(Array.prototype, {
948 * Checks whether or not the specified object exists in the array.
949 * @param {Object} o The object to check for
950 * @return {Number} The index of o in the array (or -1 if it is not found)
952 indexOf : function(o){
953 for (var i = 0, len = this.length; i < len; i++){
954 if(this[i] == o) { return i; }
960 * Removes the specified object from the array. If the object is not found nothing happens.
961 * @param {Object} o The object to remove
963 remove : function(o){
964 var index = this.indexOf(o);
966 this.splice(index, 1);
970 * Map (JS 1.6 compatibility)
971 * @param {Function} function to call
975 var len = this.length >>> 0;
976 if (typeof fun != "function") {
977 throw new TypeError();
979 var res = new Array(len);
980 var thisp = arguments[1];
981 for (var i = 0; i < len; i++)
984 res[i] = fun.call(thisp, this[i], i, this);
997 * Ext JS Library 1.1.1
998 * Copyright(c) 2006-2007, Ext JS, LLC.
1000 * Originally Released Under LGPL - original licence link has changed is not relivant.
1003 * <script type="text/javascript">
1009 * The date parsing and format syntax is a subset of
1010 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
1011 * supported will provide results equivalent to their PHP versions.
1013 * Following is the list of all currently supported formats:
1016 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
1018 Format Output Description
1019 ------ ---------- --------------------------------------------------------------
1020 d 10 Day of the month, 2 digits with leading zeros
1021 D Wed A textual representation of a day, three letters
1022 j 10 Day of the month without leading zeros
1023 l Wednesday A full textual representation of the day of the week
1024 S th English ordinal day of month suffix, 2 chars (use with j)
1025 w 3 Numeric representation of the day of the week
1026 z 9 The julian date, or day of the year (0-365)
1027 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
1028 F January A full textual representation of the month
1029 m 01 Numeric representation of a month, with leading zeros
1030 M Jan Month name abbreviation, three letters
1031 n 1 Numeric representation of a month, without leading zeros
1032 t 31 Number of days in the given month
1033 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1034 Y 2007 A full numeric representation of a year, 4 digits
1035 y 07 A two digit representation of a year
1036 a pm Lowercase Ante meridiem and Post meridiem
1037 A PM Uppercase Ante meridiem and Post meridiem
1038 g 3 12-hour format of an hour without leading zeros
1039 G 15 24-hour format of an hour without leading zeros
1040 h 03 12-hour format of an hour with leading zeros
1041 H 15 24-hour format of an hour with leading zeros
1042 i 05 Minutes with leading zeros
1043 s 01 Seconds, with leading zeros
1044 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1045 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1046 T CST Timezone setting of the machine running the code
1047 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1050 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1052 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1053 document.write(dt.format('Y-m-d')); //2007-01-10
1054 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1055 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
1058 * Here are some standard date/time patterns that you might find helpful. They
1059 * are not part of the source of Date.js, but to use them you can simply copy this
1060 * block of code into any script that is included after Date.js and they will also become
1061 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1064 ISO8601Long:"Y-m-d H:i:s",
1065 ISO8601Short:"Y-m-d",
1067 LongDate: "l, F d, Y",
1068 FullDateTime: "l, F d, Y g:i:s A",
1071 LongTime: "g:i:s A",
1072 SortableDateTime: "Y-m-d\\TH:i:s",
1073 UniversalSortableDateTime: "Y-m-d H:i:sO",
1080 var dt = new Date();
1081 document.write(dt.format(Date.patterns.ShortDate));
1086 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1087 * They generate precompiled functions from date formats instead of parsing and
1088 * processing the pattern every time you format a date. These functions are available
1089 * on every Date object (any javascript function).
1091 * The original article and download are here:
1092 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1099 Returns the number of milliseconds between this date and date
1100 @param {Date} date (optional) Defaults to now
1101 @return {Number} The diff in milliseconds
1102 @member Date getElapsed
1104 Date.prototype.getElapsed = function(date) {
1105 return Math.abs((date || new Date()).getTime()-this.getTime());
1107 // was in date file..
1111 Date.parseFunctions = {count:0};
1113 Date.parseRegexes = [];
1115 Date.formatFunctions = {count:0};
1118 Date.prototype.dateFormat = function(format) {
1119 if (Date.formatFunctions[format] == null) {
1120 Date.createNewFormat(format);
1122 var func = Date.formatFunctions[format];
1123 return this[func]();
1128 * Formats a date given the supplied format string
1129 * @param {String} format The format string
1130 * @return {String} The formatted date
1133 Date.prototype.format = Date.prototype.dateFormat;
1136 Date.createNewFormat = function(format) {
1137 var funcName = "format" + Date.formatFunctions.count++;
1138 Date.formatFunctions[format] = funcName;
1139 var code = "Date.prototype." + funcName + " = function(){return ";
1140 var special = false;
1142 for (var i = 0; i < format.length; ++i) {
1143 ch = format.charAt(i);
1144 if (!special && ch == "\\") {
1149 code += "'" + String.escape(ch) + "' + ";
1152 code += Date.getFormatCode(ch);
1155 /** eval:var:zzzzzzzzzzzzz */
1156 eval(code.substring(0, code.length - 3) + ";}");
1160 Date.getFormatCode = function(character) {
1161 switch (character) {
1163 return "String.leftPad(this.getDate(), 2, '0') + ";
1165 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1167 return "this.getDate() + ";
1169 return "Date.dayNames[this.getDay()] + ";
1171 return "this.getSuffix() + ";
1173 return "this.getDay() + ";
1175 return "this.getDayOfYear() + ";
1177 return "this.getWeekOfYear() + ";
1179 return "Date.monthNames[this.getMonth()] + ";
1181 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1183 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1185 return "(this.getMonth() + 1) + ";
1187 return "this.getDaysInMonth() + ";
1189 return "(this.isLeapYear() ? 1 : 0) + ";
1191 return "this.getFullYear() + ";
1193 return "('' + this.getFullYear()).substring(2, 4) + ";
1195 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1197 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1199 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1201 return "this.getHours() + ";
1203 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1205 return "String.leftPad(this.getHours(), 2, '0') + ";
1207 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1209 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1211 return "this.getGMTOffset() + ";
1213 return "this.getGMTColonOffset() + ";
1215 return "this.getTimezone() + ";
1217 return "(this.getTimezoneOffset() * -60) + ";
1219 return "'" + String.escape(character) + "' + ";
1224 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1225 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1226 * the date format that is not specified will default to the current date value for that part. Time parts can also
1227 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1228 * string or the parse operation will fail.
1231 //dt = Fri May 25 2007 (current date)
1232 var dt = new Date();
1234 //dt = Thu May 25 2006 (today's month/day in 2006)
1235 dt = Date.parseDate("2006", "Y");
1237 //dt = Sun Jan 15 2006 (all date parts specified)
1238 dt = Date.parseDate("2006-1-15", "Y-m-d");
1240 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1241 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1243 * @param {String} input The unparsed date as a string
1244 * @param {String} format The format the date is in
1245 * @return {Date} The parsed date
1248 Date.parseDate = function(input, format) {
1249 if (Date.parseFunctions[format] == null) {
1250 Date.createParser(format);
1252 var func = Date.parseFunctions[format];
1253 return Date[func](input);
1259 Date.createParser = function(format) {
1260 var funcName = "parse" + Date.parseFunctions.count++;
1261 var regexNum = Date.parseRegexes.length;
1262 var currentGroup = 1;
1263 Date.parseFunctions[format] = funcName;
1265 var code = "Date." + funcName + " = function(input){\n"
1266 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1267 + "var d = new Date();\n"
1268 + "y = d.getFullYear();\n"
1269 + "m = d.getMonth();\n"
1270 + "d = d.getDate();\n"
1271 + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
1272 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1273 + "if (results && results.length > 0) {";
1276 var special = false;
1278 for (var i = 0; i < format.length; ++i) {
1279 ch = format.charAt(i);
1280 if (!special && ch == "\\") {
1285 regex += String.escape(ch);
1288 var obj = Date.formatCodeToRegex(ch, currentGroup);
1289 currentGroup += obj.g;
1291 if (obj.g && obj.c) {
1297 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1298 + "{v = new Date(y, m, d, h, i, s);}\n"
1299 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1300 + "{v = new Date(y, m, d, h, i);}\n"
1301 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1302 + "{v = new Date(y, m, d, h);}\n"
1303 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1304 + "{v = new Date(y, m, d);}\n"
1305 + "else if (y >= 0 && m >= 0)\n"
1306 + "{v = new Date(y, m);}\n"
1307 + "else if (y >= 0)\n"
1308 + "{v = new Date(y);}\n"
1309 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1310 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1311 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1314 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1315 /** eval:var:zzzzzzzzzzzzz */
1320 Date.formatCodeToRegex = function(character, currentGroup) {
1321 switch (character) {
1325 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1328 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1329 s:"(\\d{1,2})"}; // day of month without leading zeroes
1332 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1333 s:"(\\d{2})"}; // day of month with leading zeroes
1337 s:"(?:" + Date.dayNames.join("|") + ")"};
1341 s:"(?:st|nd|rd|th)"};
1356 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1357 s:"(" + Date.monthNames.join("|") + ")"};
1360 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1361 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1364 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1365 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1368 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1369 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1380 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1384 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1385 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1389 c:"if (results[" + currentGroup + "] == 'am') {\n"
1390 + "if (h == 12) { h = 0; }\n"
1391 + "} else { if (h < 12) { h += 12; }}",
1395 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1396 + "if (h == 12) { h = 0; }\n"
1397 + "} else { if (h < 12) { h += 12; }}",
1402 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1403 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1407 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1408 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1411 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1415 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1420 "o = results[", currentGroup, "];\n",
1421 "var sn = o.substring(0,1);\n", // get + / - sign
1422 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1423 "var mn = o.substring(3,5) % 60;\n", // get minutes
1424 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1425 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1427 s:"([+\-]\\d{2,4})"};
1433 "o = results[", currentGroup, "];\n",
1434 "var sn = o.substring(0,1);\n",
1435 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1436 "var mn = o.substring(4,6) % 60;\n",
1437 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1438 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1444 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1447 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1448 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1449 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1453 s:String.escape(character)};
1458 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1459 * @return {String} The abbreviated timezone name (e.g. 'CST')
1461 Date.prototype.getTimezone = function() {
1462 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1466 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1467 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1469 Date.prototype.getGMTOffset = function() {
1470 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1471 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1472 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1476 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1477 * @return {String} 2-characters representing hours and 2-characters representing minutes
1478 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1480 Date.prototype.getGMTColonOffset = function() {
1481 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1482 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1484 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1488 * Get the numeric day number of the year, adjusted for leap year.
1489 * @return {Number} 0 through 364 (365 in leap years)
1491 Date.prototype.getDayOfYear = function() {
1493 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1494 for (var i = 0; i < this.getMonth(); ++i) {
1495 num += Date.daysInMonth[i];
1497 return num + this.getDate() - 1;
1501 * Get the string representation of the numeric week number of the year
1502 * (equivalent to the format specifier 'W').
1503 * @return {String} '00' through '52'
1505 Date.prototype.getWeekOfYear = function() {
1506 // Skip to Thursday of this week
1507 var now = this.getDayOfYear() + (4 - this.getDay());
1508 // Find the first Thursday of the year
1509 var jan1 = new Date(this.getFullYear(), 0, 1);
1510 var then = (7 - jan1.getDay() + 4);
1511 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1515 * Whether or not the current date is in a leap year.
1516 * @return {Boolean} True if the current date is in a leap year, else false
1518 Date.prototype.isLeapYear = function() {
1519 var year = this.getFullYear();
1520 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1524 * Get the first day of the current month, adjusted for leap year. The returned value
1525 * is the numeric day index within the week (0-6) which can be used in conjunction with
1526 * the {@link #monthNames} array to retrieve the textual day name.
1529 var dt = new Date('1/10/2007');
1530 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1532 * @return {Number} The day number (0-6)
1534 Date.prototype.getFirstDayOfMonth = function() {
1535 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1536 return (day < 0) ? (day + 7) : day;
1540 * Get the last day of the current month, adjusted for leap year. The returned value
1541 * is the numeric day index within the week (0-6) which can be used in conjunction with
1542 * the {@link #monthNames} array to retrieve the textual day name.
1545 var dt = new Date('1/10/2007');
1546 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1548 * @return {Number} The day number (0-6)
1550 Date.prototype.getLastDayOfMonth = function() {
1551 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1552 return (day < 0) ? (day + 7) : day;
1557 * Get the first date of this date's month
1560 Date.prototype.getFirstDateOfMonth = function() {
1561 return new Date(this.getFullYear(), this.getMonth(), 1);
1565 * Get the last date of this date's month
1568 Date.prototype.getLastDateOfMonth = function() {
1569 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1572 * Get the number of days in the current month, adjusted for leap year.
1573 * @return {Number} The number of days in the month
1575 Date.prototype.getDaysInMonth = function() {
1576 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1577 return Date.daysInMonth[this.getMonth()];
1581 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1582 * @return {String} 'st, 'nd', 'rd' or 'th'
1584 Date.prototype.getSuffix = function() {
1585 switch (this.getDate()) {
1602 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1605 * An array of textual month names.
1606 * Override these values for international dates, for example...
1607 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1626 * An array of textual day names.
1627 * Override these values for international dates, for example...
1628 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1644 Date.monthNumbers = {
1659 * Creates and returns a new Date instance with the exact same date value as the called instance.
1660 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1661 * variable will also be changed. When the intention is to create a new variable that will not
1662 * modify the original instance, you should create a clone.
1664 * Example of correctly cloning a date:
1667 var orig = new Date('10/1/2006');
1670 document.write(orig); //returns 'Thu Oct 05 2006'!
1673 var orig = new Date('10/1/2006');
1674 var copy = orig.clone();
1676 document.write(orig); //returns 'Thu Oct 01 2006'
1678 * @return {Date} The new Date instance
1680 Date.prototype.clone = function() {
1681 return new Date(this.getTime());
1685 * Clears any time information from this date
1686 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1687 @return {Date} this or the clone
1689 Date.prototype.clearTime = function(clone){
1691 return this.clone().clearTime();
1696 this.setMilliseconds(0);
1701 // safari setMonth is broken -- check that this is only donw once...
1702 if(Roo.isSafari && typeof(Date.brokenSetMonth) == 'undefined'){
1703 Date.brokenSetMonth = Date.prototype.setMonth;
1704 Date.prototype.setMonth = function(num){
1706 var n = Math.ceil(-num);
1707 var back_year = Math.ceil(n/12);
1708 var month = (n % 12) ? 12 - n % 12 : 0 ;
1709 this.setFullYear(this.getFullYear() - back_year);
1710 return Date.brokenSetMonth.call(this, month);
1712 return Date.brokenSetMonth.apply(this, arguments);
1717 /** Date interval constant
1721 /** Date interval constant
1725 /** Date interval constant
1729 /** Date interval constant
1733 /** Date interval constant
1737 /** Date interval constant
1741 /** Date interval constant
1747 * Provides a convenient method of performing basic date arithmetic. This method
1748 * does not modify the Date instance being called - it creates and returns
1749 * a new Date instance containing the resulting date value.
1754 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1755 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1757 //Negative values will subtract correctly:
1758 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1759 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1761 //You can even chain several calls together in one line!
1762 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1763 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1766 * @param {String} interval A valid date interval enum value
1767 * @param {Number} value The amount to add to the current date
1768 * @return {Date} The new Date instance
1770 Date.prototype.add = function(interval, value){
1771 var d = this.clone();
1772 if (!interval || value === 0) { return d; }
1773 switch(interval.toLowerCase()){
1775 d.setMilliseconds(this.getMilliseconds() + value);
1778 d.setSeconds(this.getSeconds() + value);
1781 d.setMinutes(this.getMinutes() + value);
1784 d.setHours(this.getHours() + value);
1787 d.setDate(this.getDate() + value);
1790 var day = this.getDate();
1792 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1795 d.setMonth(this.getMonth() + value);
1798 d.setFullYear(this.getFullYear() + value);
1805 * Ext JS Library 1.1.1
1806 * Copyright(c) 2006-2007, Ext JS, LLC.
1808 * Originally Released Under LGPL - original licence link has changed is not relivant.
1811 * <script type="text/javascript">
1815 * @class Roo.lib.Dom
1818 * Dom utils (from YIU afaik)
1823 * Get the view width
1824 * @param {Boolean} full True will get the full document, otherwise it's the view width
1825 * @return {Number} The width
1828 getViewWidth : function(full) {
1829 return full ? this.getDocumentWidth() : this.getViewportWidth();
1832 * Get the view height
1833 * @param {Boolean} full True will get the full document, otherwise it's the view height
1834 * @return {Number} The height
1836 getViewHeight : function(full) {
1837 return full ? this.getDocumentHeight() : this.getViewportHeight();
1840 getDocumentHeight: function() {
1841 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1842 return Math.max(scrollHeight, this.getViewportHeight());
1845 getDocumentWidth: function() {
1846 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1847 return Math.max(scrollWidth, this.getViewportWidth());
1850 getViewportHeight: function() {
1851 var height = self.innerHeight;
1852 var mode = document.compatMode;
1854 if ((mode || Roo.isIE) && !Roo.isOpera) {
1855 height = (mode == "CSS1Compat") ?
1856 document.documentElement.clientHeight :
1857 document.body.clientHeight;
1863 getViewportWidth: function() {
1864 var width = self.innerWidth;
1865 var mode = document.compatMode;
1867 if (mode || Roo.isIE) {
1868 width = (mode == "CSS1Compat") ?
1869 document.documentElement.clientWidth :
1870 document.body.clientWidth;
1875 isAncestor : function(p, c) {
1882 if (p.contains && !Roo.isSafari) {
1883 return p.contains(c);
1884 } else if (p.compareDocumentPosition) {
1885 return !!(p.compareDocumentPosition(c) & 16);
1887 var parent = c.parentNode;
1892 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1895 parent = parent.parentNode;
1901 getRegion : function(el) {
1902 return Roo.lib.Region.getRegion(el);
1905 getY : function(el) {
1906 return this.getXY(el)[1];
1909 getX : function(el) {
1910 return this.getXY(el)[0];
1913 getXY : function(el) {
1914 var p, pe, b, scroll, bd = document.body;
1915 el = Roo.getDom(el);
1916 var fly = Roo.lib.AnimBase.fly;
1917 if (el.getBoundingClientRect) {
1918 b = el.getBoundingClientRect();
1919 scroll = fly(document).getScroll();
1920 return [b.left + scroll.left, b.top + scroll.top];
1926 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1933 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1940 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1941 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1948 if (p != el && pe.getStyle('overflow') != 'visible') {
1956 if (Roo.isSafari && hasAbsolute) {
1961 if (Roo.isGecko && !hasAbsolute) {
1963 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1964 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1968 while (p && p != bd) {
1969 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1981 setXY : function(el, xy) {
1982 el = Roo.fly(el, '_setXY');
1984 var pts = el.translatePoints(xy);
1985 if (xy[0] !== false) {
1986 el.dom.style.left = pts.left + "px";
1988 if (xy[1] !== false) {
1989 el.dom.style.top = pts.top + "px";
1993 setX : function(el, x) {
1994 this.setXY(el, [x, false]);
1997 setY : function(el, y) {
1998 this.setXY(el, [false, y]);
2002 * Portions of this file are based on pieces of Yahoo User Interface Library
2003 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2004 * YUI licensed under the BSD License:
2005 * http://developer.yahoo.net/yui/license.txt
2006 * <script type="text/javascript">
2010 Roo.lib.Event = function() {
2011 var loadComplete = false;
2013 var unloadListeners = [];
2015 var onAvailStack = [];
2017 var lastError = null;
2030 startInterval: function() {
2031 if (!this._interval) {
2033 var callback = function() {
2034 self._tryPreloadAttach();
2036 this._interval = setInterval(callback, this.POLL_INTERVAL);
2041 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2042 onAvailStack.push({ id: p_id,
2045 override: p_override,
2046 checkReady: false });
2048 retryCount = this.POLL_RETRYS;
2049 this.startInterval();
2053 addListener: function(el, eventName, fn) {
2054 el = Roo.getDom(el);
2059 if ("unload" == eventName) {
2060 unloadListeners[unloadListeners.length] =
2061 [el, eventName, fn];
2065 var wrappedFn = function(e) {
2066 return fn(Roo.lib.Event.getEvent(e));
2069 var li = [el, eventName, fn, wrappedFn];
2071 var index = listeners.length;
2072 listeners[index] = li;
2074 this.doAdd(el, eventName, wrappedFn, false);
2080 removeListener: function(el, eventName, fn) {
2083 el = Roo.getDom(el);
2086 return this.purgeElement(el, false, eventName);
2090 if ("unload" == eventName) {
2092 for (i = 0,len = unloadListeners.length; i < len; i++) {
2093 var li = unloadListeners[i];
2096 li[1] == eventName &&
2098 unloadListeners.splice(i, 1);
2106 var cacheItem = null;
2109 var index = arguments[3];
2111 if ("undefined" == typeof index) {
2112 index = this._getCacheIndex(el, eventName, fn);
2116 cacheItem = listeners[index];
2119 if (!el || !cacheItem) {
2123 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2125 delete listeners[index][this.WFN];
2126 delete listeners[index][this.FN];
2127 listeners.splice(index, 1);
2134 getTarget: function(ev, resolveTextNode) {
2135 ev = ev.browserEvent || ev;
2136 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2137 var t = ev.target || ev.srcElement;
2138 return this.resolveTextNode(t);
2142 resolveTextNode: function(node) {
2143 if (Roo.isSafari && node && 3 == node.nodeType) {
2144 return node.parentNode;
2151 getPageX: function(ev) {
2152 ev = ev.browserEvent || ev;
2153 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2155 if (!x && 0 !== x) {
2156 x = ev.clientX || 0;
2159 x += this.getScroll()[1];
2167 getPageY: function(ev) {
2168 ev = ev.browserEvent || ev;
2169 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2171 if (!y && 0 !== y) {
2172 y = ev.clientY || 0;
2175 y += this.getScroll()[0];
2184 getXY: function(ev) {
2185 ev = ev.browserEvent || ev;
2186 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2187 return [this.getPageX(ev), this.getPageY(ev)];
2191 getRelatedTarget: function(ev) {
2192 ev = ev.browserEvent || ev;
2193 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2194 var t = ev.relatedTarget;
2196 if (ev.type == "mouseout") {
2198 } else if (ev.type == "mouseover") {
2203 return this.resolveTextNode(t);
2207 getTime: function(ev) {
2208 ev = ev.browserEvent || ev;
2209 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2211 var t = new Date().getTime();
2215 this.lastError = ex;
2224 stopEvent: function(ev) {
2225 this.stopPropagation(ev);
2226 this.preventDefault(ev);
2230 stopPropagation: function(ev) {
2231 ev = ev.browserEvent || ev;
2232 if (ev.stopPropagation) {
2233 ev.stopPropagation();
2235 ev.cancelBubble = true;
2240 preventDefault: function(ev) {
2241 ev = ev.browserEvent || ev;
2242 if(ev.preventDefault) {
2243 ev.preventDefault();
2245 ev.returnValue = false;
2250 getEvent: function(e) {
2251 var ev = e || window.event;
2253 var c = this.getEvent.caller;
2255 ev = c.arguments[0];
2256 if (ev && Event == ev.constructor) {
2266 getCharCode: function(ev) {
2267 ev = ev.browserEvent || ev;
2268 return ev.charCode || ev.keyCode || 0;
2272 _getCacheIndex: function(el, eventName, fn) {
2273 for (var i = 0,len = listeners.length; i < len; ++i) {
2274 var li = listeners[i];
2276 li[this.FN] == fn &&
2277 li[this.EL] == el &&
2278 li[this.TYPE] == eventName) {
2290 getEl: function(id) {
2291 return document.getElementById(id);
2295 clearCache: function() {
2299 _load: function(e) {
2300 loadComplete = true;
2301 var EU = Roo.lib.Event;
2305 EU.doRemove(window, "load", EU._load);
2310 _tryPreloadAttach: function() {
2319 var tryAgain = !loadComplete;
2321 tryAgain = (retryCount > 0);
2326 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2327 var item = onAvailStack[i];
2329 var el = this.getEl(item.id);
2332 if (!item.checkReady ||
2335 (document && document.body)) {
2338 if (item.override) {
2339 if (item.override === true) {
2342 scope = item.override;
2345 item.fn.call(scope, item.obj);
2346 onAvailStack[i] = null;
2349 notAvail.push(item);
2354 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2358 this.startInterval();
2360 clearInterval(this._interval);
2361 this._interval = null;
2364 this.locked = false;
2371 purgeElement: function(el, recurse, eventName) {
2372 var elListeners = this.getListeners(el, eventName);
2374 for (var i = 0,len = elListeners.length; i < len; ++i) {
2375 var l = elListeners[i];
2376 this.removeListener(el, l.type, l.fn);
2380 if (recurse && el && el.childNodes) {
2381 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2382 this.purgeElement(el.childNodes[i], recurse, eventName);
2388 getListeners: function(el, eventName) {
2389 var results = [], searchLists;
2391 searchLists = [listeners, unloadListeners];
2392 } else if (eventName == "unload") {
2393 searchLists = [unloadListeners];
2395 searchLists = [listeners];
2398 for (var j = 0; j < searchLists.length; ++j) {
2399 var searchList = searchLists[j];
2400 if (searchList && searchList.length > 0) {
2401 for (var i = 0,len = searchList.length; i < len; ++i) {
2402 var l = searchList[i];
2403 if (l && l[this.EL] === el &&
2404 (!eventName || eventName === l[this.TYPE])) {
2409 adjust: l[this.ADJ_SCOPE],
2417 return (results.length) ? results : null;
2421 _unload: function(e) {
2423 var EU = Roo.lib.Event, i, j, l, len, index;
2425 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2426 l = unloadListeners[i];
2429 if (l[EU.ADJ_SCOPE]) {
2430 if (l[EU.ADJ_SCOPE] === true) {
2433 scope = l[EU.ADJ_SCOPE];
2436 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2437 unloadListeners[i] = null;
2443 unloadListeners = null;
2445 if (listeners && listeners.length > 0) {
2446 j = listeners.length;
2449 l = listeners[index];
2451 EU.removeListener(l[EU.EL], l[EU.TYPE],
2461 EU.doRemove(window, "unload", EU._unload);
2466 getScroll: function() {
2467 var dd = document.documentElement, db = document.body;
2468 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2469 return [dd.scrollTop, dd.scrollLeft];
2471 return [db.scrollTop, db.scrollLeft];
2478 doAdd: function () {
2479 if (window.addEventListener) {
2480 return function(el, eventName, fn, capture) {
2481 el.addEventListener(eventName, fn, (capture));
2483 } else if (window.attachEvent) {
2484 return function(el, eventName, fn, capture) {
2485 el.attachEvent("on" + eventName, fn);
2494 doRemove: function() {
2495 if (window.removeEventListener) {
2496 return function (el, eventName, fn, capture) {
2497 el.removeEventListener(eventName, fn, (capture));
2499 } else if (window.detachEvent) {
2500 return function (el, eventName, fn) {
2501 el.detachEvent("on" + eventName, fn);
2513 var E = Roo.lib.Event;
2514 E.on = E.addListener;
2515 E.un = E.removeListener;
2517 if (document && document.body) {
2520 E.doAdd(window, "load", E._load);
2522 E.doAdd(window, "unload", E._unload);
2523 E._tryPreloadAttach();
2527 * Portions of this file are based on pieces of Yahoo User Interface Library
2528 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2529 * YUI licensed under the BSD License:
2530 * http://developer.yahoo.net/yui/license.txt
2531 * <script type="text/javascript">
2537 * @class Roo.lib.Ajax
2544 request : function(method, uri, cb, data, options) {
2546 var hs = options.headers;
2549 if(hs.hasOwnProperty(h)){
2550 this.initHeader(h, hs[h], false);
2554 if(options.xmlData){
2555 this.initHeader('Content-Type', 'text/xml', false);
2557 data = options.xmlData;
2561 return this.asyncRequest(method, uri, cb, data);
2564 serializeForm : function(form) {
2565 if(typeof form == 'string') {
2566 form = (document.getElementById(form) || document.forms[form]);
2569 var el, name, val, disabled, data = '', hasSubmit = false;
2570 for (var i = 0; i < form.elements.length; i++) {
2571 el = form.elements[i];
2572 disabled = form.elements[i].disabled;
2573 name = form.elements[i].name;
2574 val = form.elements[i].value;
2576 if (!disabled && name){
2580 case 'select-multiple':
2581 for (var j = 0; j < el.options.length; j++) {
2582 if (el.options[j].selected) {
2584 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2587 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2595 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2608 if(hasSubmit == false) {
2609 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2614 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2619 data = data.substr(0, data.length - 1);
2627 useDefaultHeader:true,
2629 defaultPostHeader:'application/x-www-form-urlencoded',
2631 useDefaultXhrHeader:true,
2633 defaultXhrHeader:'XMLHttpRequest',
2635 hasDefaultHeaders:true,
2647 setProgId:function(id)
2649 this.activeX.unshift(id);
2652 setDefaultPostHeader:function(b)
2654 this.useDefaultHeader = b;
2657 setDefaultXhrHeader:function(b)
2659 this.useDefaultXhrHeader = b;
2662 setPollingInterval:function(i)
2664 if (typeof i == 'number' && isFinite(i)) {
2665 this.pollInterval = i;
2669 createXhrObject:function(transactionId)
2675 http = new XMLHttpRequest();
2677 obj = { conn:http, tId:transactionId };
2681 for (var i = 0; i < this.activeX.length; ++i) {
2685 http = new ActiveXObject(this.activeX[i]);
2687 obj = { conn:http, tId:transactionId };
2700 getConnectionObject:function()
2703 var tId = this.transactionId;
2707 o = this.createXhrObject(tId);
2709 this.transactionId++;
2720 asyncRequest:function(method, uri, callback, postData)
2722 var o = this.getConnectionObject();
2728 o.conn.open(method, uri, true);
2730 if (this.useDefaultXhrHeader) {
2731 if (!this.defaultHeaders['X-Requested-With']) {
2732 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2736 if(postData && this.useDefaultHeader){
2737 this.initHeader('Content-Type', this.defaultPostHeader);
2740 if (this.hasDefaultHeaders || this.hasHeaders) {
2744 this.handleReadyState(o, callback);
2745 o.conn.send(postData || null);
2751 handleReadyState:function(o, callback)
2755 if (callback && callback.timeout) {
2757 this.timeout[o.tId] = window.setTimeout(function() {
2758 oConn.abort(o, callback, true);
2759 }, callback.timeout);
2762 this.poll[o.tId] = window.setInterval(
2764 if (o.conn && o.conn.readyState == 4) {
2765 window.clearInterval(oConn.poll[o.tId]);
2766 delete oConn.poll[o.tId];
2768 if(callback && callback.timeout) {
2769 window.clearTimeout(oConn.timeout[o.tId]);
2770 delete oConn.timeout[o.tId];
2773 oConn.handleTransactionResponse(o, callback);
2776 , this.pollInterval);
2779 handleTransactionResponse:function(o, callback, isAbort)
2783 this.releaseObject(o);
2787 var httpStatus, responseObject;
2791 if (o.conn.status !== undefined && o.conn.status != 0) {
2792 httpStatus = o.conn.status;
2804 if (httpStatus >= 200 && httpStatus < 300) {
2805 responseObject = this.createResponseObject(o, callback.argument);
2806 if (callback.success) {
2807 if (!callback.scope) {
2808 callback.success(responseObject);
2813 callback.success.apply(callback.scope, [responseObject]);
2818 switch (httpStatus) {
2826 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2827 if (callback.failure) {
2828 if (!callback.scope) {
2829 callback.failure(responseObject);
2832 callback.failure.apply(callback.scope, [responseObject]);
2837 responseObject = this.createResponseObject(o, callback.argument);
2838 if (callback.failure) {
2839 if (!callback.scope) {
2840 callback.failure(responseObject);
2843 callback.failure.apply(callback.scope, [responseObject]);
2849 this.releaseObject(o);
2850 responseObject = null;
2853 createResponseObject:function(o, callbackArg)
2860 var headerStr = o.conn.getAllResponseHeaders();
2861 var header = headerStr.split('\n');
2862 for (var i = 0; i < header.length; i++) {
2863 var delimitPos = header[i].indexOf(':');
2864 if (delimitPos != -1) {
2865 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2873 obj.status = o.conn.status;
2874 obj.statusText = o.conn.statusText;
2875 obj.getResponseHeader = headerObj;
2876 obj.getAllResponseHeaders = headerStr;
2877 obj.responseText = o.conn.responseText;
2878 obj.responseXML = o.conn.responseXML;
2880 if (typeof callbackArg !== undefined) {
2881 obj.argument = callbackArg;
2887 createExceptionObject:function(tId, callbackArg, isAbort)
2890 var COMM_ERROR = 'communication failure';
2891 var ABORT_CODE = -1;
2892 var ABORT_ERROR = 'transaction aborted';
2898 obj.status = ABORT_CODE;
2899 obj.statusText = ABORT_ERROR;
2902 obj.status = COMM_CODE;
2903 obj.statusText = COMM_ERROR;
2907 obj.argument = callbackArg;
2913 initHeader:function(label, value, isDefault)
2915 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2917 if (headerObj[label] === undefined) {
2918 headerObj[label] = value;
2923 headerObj[label] = value + "," + headerObj[label];
2927 this.hasDefaultHeaders = true;
2930 this.hasHeaders = true;
2935 setHeader:function(o)
2937 if (this.hasDefaultHeaders) {
2938 for (var prop in this.defaultHeaders) {
2939 if (this.defaultHeaders.hasOwnProperty(prop)) {
2940 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2945 if (this.hasHeaders) {
2946 for (var prop in this.headers) {
2947 if (this.headers.hasOwnProperty(prop)) {
2948 o.conn.setRequestHeader(prop, this.headers[prop]);
2952 this.hasHeaders = false;
2956 resetDefaultHeaders:function() {
2957 delete this.defaultHeaders;
2958 this.defaultHeaders = {};
2959 this.hasDefaultHeaders = false;
2962 abort:function(o, callback, isTimeout)
2964 if(this.isCallInProgress(o)) {
2966 window.clearInterval(this.poll[o.tId]);
2967 delete this.poll[o.tId];
2969 delete this.timeout[o.tId];
2972 this.handleTransactionResponse(o, callback, true);
2982 isCallInProgress:function(o)
2985 return o.conn.readyState != 4 && o.conn.readyState != 0;
2994 releaseObject:function(o)
3003 'MSXML2.XMLHTTP.3.0',
3011 * Portions of this file are based on pieces of Yahoo User Interface Library
3012 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3013 * YUI licensed under the BSD License:
3014 * http://developer.yahoo.net/yui/license.txt
3015 * <script type="text/javascript">
3019 Roo.lib.Region = function(t, r, b, l) {
3029 Roo.lib.Region.prototype = {
3030 contains : function(region) {
3031 return ( region.left >= this.left &&
3032 region.right <= this.right &&
3033 region.top >= this.top &&
3034 region.bottom <= this.bottom );
3038 getArea : function() {
3039 return ( (this.bottom - this.top) * (this.right - this.left) );
3042 intersect : function(region) {
3043 var t = Math.max(this.top, region.top);
3044 var r = Math.min(this.right, region.right);
3045 var b = Math.min(this.bottom, region.bottom);
3046 var l = Math.max(this.left, region.left);
3048 if (b >= t && r >= l) {
3049 return new Roo.lib.Region(t, r, b, l);
3054 union : function(region) {
3055 var t = Math.min(this.top, region.top);
3056 var r = Math.max(this.right, region.right);
3057 var b = Math.max(this.bottom, region.bottom);
3058 var l = Math.min(this.left, region.left);
3060 return new Roo.lib.Region(t, r, b, l);
3063 adjust : function(t, l, b, r) {
3072 Roo.lib.Region.getRegion = function(el) {
3073 var p = Roo.lib.Dom.getXY(el);
3076 var r = p[0] + el.offsetWidth;
3077 var b = p[1] + el.offsetHeight;
3080 return new Roo.lib.Region(t, r, b, l);
3083 * Portions of this file are based on pieces of Yahoo User Interface Library
3084 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3085 * YUI licensed under the BSD License:
3086 * http://developer.yahoo.net/yui/license.txt
3087 * <script type="text/javascript">
3090 //@@dep Roo.lib.Region
3093 Roo.lib.Point = function(x, y) {
3094 if (x instanceof Array) {
3098 this.x = this.right = this.left = this[0] = x;
3099 this.y = this.top = this.bottom = this[1] = y;
3102 Roo.lib.Point.prototype = new Roo.lib.Region();
3104 * Portions of this file are based on pieces of Yahoo User Interface Library
3105 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3106 * YUI licensed under the BSD License:
3107 * http://developer.yahoo.net/yui/license.txt
3108 * <script type="text/javascript">
3115 scroll : function(el, args, duration, easing, cb, scope) {
3116 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3119 motion : function(el, args, duration, easing, cb, scope) {
3120 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3123 color : function(el, args, duration, easing, cb, scope) {
3124 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3127 run : function(el, args, duration, easing, cb, scope, type) {
3128 type = type || Roo.lib.AnimBase;
3129 if (typeof easing == "string") {
3130 easing = Roo.lib.Easing[easing];
3132 var anim = new type(el, args, duration, easing);
3133 anim.animateX(function() {
3134 Roo.callback(cb, scope);
3140 * Portions of this file are based on pieces of Yahoo User Interface Library
3141 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3142 * YUI licensed under the BSD License:
3143 * http://developer.yahoo.net/yui/license.txt
3144 * <script type="text/javascript">
3152 if (!libFlyweight) {
3153 libFlyweight = new Roo.Element.Flyweight();
3155 libFlyweight.dom = el;
3156 return libFlyweight;
3159 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3163 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3165 this.init(el, attributes, duration, method);
3169 Roo.lib.AnimBase.fly = fly;
3173 Roo.lib.AnimBase.prototype = {
3175 toString: function() {
3176 var el = this.getEl();
3177 var id = el.id || el.tagName;
3178 return ("Anim " + id);
3182 noNegatives: /width|height|opacity|padding/i,
3183 offsetAttribute: /^((width|height)|(top|left))$/,
3184 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3185 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3189 doMethod: function(attr, start, end) {
3190 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3194 setAttribute: function(attr, val, unit) {
3195 if (this.patterns.noNegatives.test(attr)) {
3196 val = (val > 0) ? val : 0;
3199 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3203 getAttribute: function(attr) {
3204 var el = this.getEl();
3205 var val = fly(el).getStyle(attr);
3207 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3208 return parseFloat(val);
3211 var a = this.patterns.offsetAttribute.exec(attr) || [];
3212 var pos = !!( a[3] );
3213 var box = !!( a[2] );
3216 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3217 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3226 getDefaultUnit: function(attr) {
3227 if (this.patterns.defaultUnit.test(attr)) {
3234 animateX : function(callback, scope) {
3235 var f = function() {
3236 this.onComplete.removeListener(f);
3237 if (typeof callback == "function") {
3238 callback.call(scope || this, this);
3241 this.onComplete.addListener(f, this);
3246 setRuntimeAttribute: function(attr) {
3249 var attributes = this.attributes;
3251 this.runtimeAttributes[attr] = {};
3253 var isset = function(prop) {
3254 return (typeof prop !== 'undefined');
3257 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3261 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3264 if (isset(attributes[attr]['to'])) {
3265 end = attributes[attr]['to'];
3266 } else if (isset(attributes[attr]['by'])) {
3267 if (start.constructor == Array) {
3269 for (var i = 0, len = start.length; i < len; ++i) {
3270 end[i] = start[i] + attributes[attr]['by'][i];
3273 end = start + attributes[attr]['by'];
3277 this.runtimeAttributes[attr].start = start;
3278 this.runtimeAttributes[attr].end = end;
3281 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3285 init: function(el, attributes, duration, method) {
3287 var isAnimated = false;
3290 var startTime = null;
3293 var actualFrames = 0;
3296 el = Roo.getDom(el);
3299 this.attributes = attributes || {};
3302 this.duration = duration || 1;
3305 this.method = method || Roo.lib.Easing.easeNone;
3308 this.useSeconds = true;
3311 this.currentFrame = 0;
3314 this.totalFrames = Roo.lib.AnimMgr.fps;
3317 this.getEl = function() {
3322 this.isAnimated = function() {
3327 this.getStartTime = function() {
3331 this.runtimeAttributes = {};
3334 this.animate = function() {
3335 if (this.isAnimated()) {
3339 this.currentFrame = 0;
3341 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3343 Roo.lib.AnimMgr.registerElement(this);
3347 this.stop = function(finish) {
3349 this.currentFrame = this.totalFrames;
3350 this._onTween.fire();
3352 Roo.lib.AnimMgr.stop(this);
3355 var onStart = function() {
3356 this.onStart.fire();
3358 this.runtimeAttributes = {};
3359 for (var attr in this.attributes) {
3360 this.setRuntimeAttribute(attr);
3365 startTime = new Date();
3369 var onTween = function() {
3371 duration: new Date() - this.getStartTime(),
3372 currentFrame: this.currentFrame
3375 data.toString = function() {
3377 'duration: ' + data.duration +
3378 ', currentFrame: ' + data.currentFrame
3382 this.onTween.fire(data);
3384 var runtimeAttributes = this.runtimeAttributes;
3386 for (var attr in runtimeAttributes) {
3387 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3393 var onComplete = function() {
3394 var actual_duration = (new Date() - startTime) / 1000 ;
3397 duration: actual_duration,
3398 frames: actualFrames,
3399 fps: actualFrames / actual_duration
3402 data.toString = function() {
3404 'duration: ' + data.duration +
3405 ', frames: ' + data.frames +
3406 ', fps: ' + data.fps
3412 this.onComplete.fire(data);
3416 this._onStart = new Roo.util.Event(this);
3417 this.onStart = new Roo.util.Event(this);
3418 this.onTween = new Roo.util.Event(this);
3419 this._onTween = new Roo.util.Event(this);
3420 this.onComplete = new Roo.util.Event(this);
3421 this._onComplete = new Roo.util.Event(this);
3422 this._onStart.addListener(onStart);
3423 this._onTween.addListener(onTween);
3424 this._onComplete.addListener(onComplete);
3429 * Portions of this file are based on pieces of Yahoo User Interface Library
3430 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3431 * YUI licensed under the BSD License:
3432 * http://developer.yahoo.net/yui/license.txt
3433 * <script type="text/javascript">
3437 Roo.lib.AnimMgr = new function() {
3454 this.registerElement = function(tween) {
3455 queue[queue.length] = tween;
3457 tween._onStart.fire();
3462 this.unRegister = function(tween, index) {
3463 tween._onComplete.fire();
3464 index = index || getIndex(tween);
3466 queue.splice(index, 1);
3470 if (tweenCount <= 0) {
3476 this.start = function() {
3477 if (thread === null) {
3478 thread = setInterval(this.run, this.delay);
3483 this.stop = function(tween) {
3485 clearInterval(thread);
3487 for (var i = 0, len = queue.length; i < len; ++i) {
3488 if (queue[0].isAnimated()) {
3489 this.unRegister(queue[0], 0);
3498 this.unRegister(tween);
3503 this.run = function() {
3504 for (var i = 0, len = queue.length; i < len; ++i) {
3505 var tween = queue[i];
3506 if (!tween || !tween.isAnimated()) {
3510 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3512 tween.currentFrame += 1;
3514 if (tween.useSeconds) {
3515 correctFrame(tween);
3517 tween._onTween.fire();
3520 Roo.lib.AnimMgr.stop(tween, i);
3525 var getIndex = function(anim) {
3526 for (var i = 0, len = queue.length; i < len; ++i) {
3527 if (queue[i] == anim) {
3535 var correctFrame = function(tween) {
3536 var frames = tween.totalFrames;
3537 var frame = tween.currentFrame;
3538 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3539 var elapsed = (new Date() - tween.getStartTime());
3542 if (elapsed < tween.duration * 1000) {
3543 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3545 tweak = frames - (frame + 1);
3547 if (tweak > 0 && isFinite(tweak)) {
3548 if (tween.currentFrame + tweak >= frames) {
3549 tweak = frames - (frame + 1);
3552 tween.currentFrame += tweak;
3558 * Portions of this file are based on pieces of Yahoo User Interface Library
3559 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3560 * YUI licensed under the BSD License:
3561 * http://developer.yahoo.net/yui/license.txt
3562 * <script type="text/javascript">
3565 Roo.lib.Bezier = new function() {
3567 this.getPosition = function(points, t) {
3568 var n = points.length;
3571 for (var i = 0; i < n; ++i) {
3572 tmp[i] = [points[i][0], points[i][1]];
3575 for (var j = 1; j < n; ++j) {
3576 for (i = 0; i < n - j; ++i) {
3577 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3578 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3582 return [ tmp[0][0], tmp[0][1] ];
3586 * Portions of this file are based on pieces of Yahoo User Interface Library
3587 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3588 * YUI licensed under the BSD License:
3589 * http://developer.yahoo.net/yui/license.txt
3590 * <script type="text/javascript">
3595 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3596 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3599 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3601 var fly = Roo.lib.AnimBase.fly;
3603 var superclass = Y.ColorAnim.superclass;
3604 var proto = Y.ColorAnim.prototype;
3606 proto.toString = function() {
3607 var el = this.getEl();
3608 var id = el.id || el.tagName;
3609 return ("ColorAnim " + id);
3612 proto.patterns.color = /color$/i;
3613 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3614 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3615 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3616 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3619 proto.parseColor = function(s) {
3620 if (s.length == 3) {
3624 var c = this.patterns.hex.exec(s);
3625 if (c && c.length == 4) {
3626 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3629 c = this.patterns.rgb.exec(s);
3630 if (c && c.length == 4) {
3631 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3634 c = this.patterns.hex3.exec(s);
3635 if (c && c.length == 4) {
3636 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3641 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3642 proto.getAttribute = function(attr) {
3643 var el = this.getEl();
3644 if (this.patterns.color.test(attr)) {
3645 var val = fly(el).getStyle(attr);
3647 if (this.patterns.transparent.test(val)) {
3648 var parent = el.parentNode;
3649 val = fly(parent).getStyle(attr);
3651 while (parent && this.patterns.transparent.test(val)) {
3652 parent = parent.parentNode;
3653 val = fly(parent).getStyle(attr);
3654 if (parent.tagName.toUpperCase() == 'HTML') {
3660 val = superclass.getAttribute.call(this, attr);
3665 proto.getAttribute = function(attr) {
3666 var el = this.getEl();
3667 if (this.patterns.color.test(attr)) {
3668 var val = fly(el).getStyle(attr);
3670 if (this.patterns.transparent.test(val)) {
3671 var parent = el.parentNode;
3672 val = fly(parent).getStyle(attr);
3674 while (parent && this.patterns.transparent.test(val)) {
3675 parent = parent.parentNode;
3676 val = fly(parent).getStyle(attr);
3677 if (parent.tagName.toUpperCase() == 'HTML') {
3683 val = superclass.getAttribute.call(this, attr);
3689 proto.doMethod = function(attr, start, end) {
3692 if (this.patterns.color.test(attr)) {
3694 for (var i = 0, len = start.length; i < len; ++i) {
3695 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3698 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3701 val = superclass.doMethod.call(this, attr, start, end);
3707 proto.setRuntimeAttribute = function(attr) {
3708 superclass.setRuntimeAttribute.call(this, attr);
3710 if (this.patterns.color.test(attr)) {
3711 var attributes = this.attributes;
3712 var start = this.parseColor(this.runtimeAttributes[attr].start);
3713 var end = this.parseColor(this.runtimeAttributes[attr].end);
3715 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3716 end = this.parseColor(attributes[attr].by);
3718 for (var i = 0, len = start.length; i < len; ++i) {
3719 end[i] = start[i] + end[i];
3723 this.runtimeAttributes[attr].start = start;
3724 this.runtimeAttributes[attr].end = end;
3730 * Portions of this file are based on pieces of Yahoo User Interface Library
3731 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3732 * YUI licensed under the BSD License:
3733 * http://developer.yahoo.net/yui/license.txt
3734 * <script type="text/javascript">
3740 easeNone: function (t, b, c, d) {
3741 return c * t / d + b;
3745 easeIn: function (t, b, c, d) {
3746 return c * (t /= d) * t + b;
3750 easeOut: function (t, b, c, d) {
3751 return -c * (t /= d) * (t - 2) + b;
3755 easeBoth: function (t, b, c, d) {
3756 if ((t /= d / 2) < 1) {
3757 return c / 2 * t * t + b;
3760 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3764 easeInStrong: function (t, b, c, d) {
3765 return c * (t /= d) * t * t * t + b;
3769 easeOutStrong: function (t, b, c, d) {
3770 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3774 easeBothStrong: function (t, b, c, d) {
3775 if ((t /= d / 2) < 1) {
3776 return c / 2 * t * t * t * t + b;
3779 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3784 elasticIn: function (t, b, c, d, a, p) {
3788 if ((t /= d) == 1) {
3795 if (!a || a < Math.abs(c)) {
3800 var s = p / (2 * Math.PI) * Math.asin(c / a);
3803 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3807 elasticOut: function (t, b, c, d, a, p) {
3811 if ((t /= d) == 1) {
3818 if (!a || a < Math.abs(c)) {
3823 var s = p / (2 * Math.PI) * Math.asin(c / a);
3826 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3830 elasticBoth: function (t, b, c, d, a, p) {
3835 if ((t /= d / 2) == 2) {
3843 if (!a || a < Math.abs(c)) {
3848 var s = p / (2 * Math.PI) * Math.asin(c / a);
3852 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3853 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3855 return a * Math.pow(2, -10 * (t -= 1)) *
3856 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3861 backIn: function (t, b, c, d, s) {
3862 if (typeof s == 'undefined') {
3865 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3869 backOut: function (t, b, c, d, s) {
3870 if (typeof s == 'undefined') {
3873 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3877 backBoth: function (t, b, c, d, s) {
3878 if (typeof s == 'undefined') {
3882 if ((t /= d / 2 ) < 1) {
3883 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3885 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3889 bounceIn: function (t, b, c, d) {
3890 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3894 bounceOut: function (t, b, c, d) {
3895 if ((t /= d) < (1 / 2.75)) {
3896 return c * (7.5625 * t * t) + b;
3897 } else if (t < (2 / 2.75)) {
3898 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3899 } else if (t < (2.5 / 2.75)) {
3900 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3902 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3906 bounceBoth: function (t, b, c, d) {
3908 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3910 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3913 * Portions of this file are based on pieces of Yahoo User Interface Library
3914 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3915 * YUI licensed under the BSD License:
3916 * http://developer.yahoo.net/yui/license.txt
3917 * <script type="text/javascript">
3921 Roo.lib.Motion = function(el, attributes, duration, method) {
3923 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3927 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3931 var superclass = Y.Motion.superclass;
3932 var proto = Y.Motion.prototype;
3934 proto.toString = function() {
3935 var el = this.getEl();
3936 var id = el.id || el.tagName;
3937 return ("Motion " + id);
3940 proto.patterns.points = /^points$/i;
3942 proto.setAttribute = function(attr, val, unit) {
3943 if (this.patterns.points.test(attr)) {
3944 unit = unit || 'px';
3945 superclass.setAttribute.call(this, 'left', val[0], unit);
3946 superclass.setAttribute.call(this, 'top', val[1], unit);
3948 superclass.setAttribute.call(this, attr, val, unit);
3952 proto.getAttribute = function(attr) {
3953 if (this.patterns.points.test(attr)) {
3955 superclass.getAttribute.call(this, 'left'),
3956 superclass.getAttribute.call(this, 'top')
3959 val = superclass.getAttribute.call(this, attr);
3965 proto.doMethod = function(attr, start, end) {
3968 if (this.patterns.points.test(attr)) {
3969 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3970 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3972 val = superclass.doMethod.call(this, attr, start, end);
3977 proto.setRuntimeAttribute = function(attr) {
3978 if (this.patterns.points.test(attr)) {
3979 var el = this.getEl();
3980 var attributes = this.attributes;
3982 var control = attributes['points']['control'] || [];
3986 if (control.length > 0 && !(control[0] instanceof Array)) {
3987 control = [control];
3990 for (i = 0,len = control.length; i < len; ++i) {
3991 tmp[i] = control[i];
3996 Roo.fly(el).position();
3998 if (isset(attributes['points']['from'])) {
3999 Roo.lib.Dom.setXY(el, attributes['points']['from']);
4002 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
4005 start = this.getAttribute('points');
4008 if (isset(attributes['points']['to'])) {
4009 end = translateValues.call(this, attributes['points']['to'], start);
4011 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4012 for (i = 0,len = control.length; i < len; ++i) {
4013 control[i] = translateValues.call(this, control[i], start);
4017 } else if (isset(attributes['points']['by'])) {
4018 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
4020 for (i = 0,len = control.length; i < len; ++i) {
4021 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
4025 this.runtimeAttributes[attr] = [start];
4027 if (control.length > 0) {
4028 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4031 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4034 superclass.setRuntimeAttribute.call(this, attr);
4038 var translateValues = function(val, start) {
4039 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4040 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4045 var isset = function(prop) {
4046 return (typeof prop !== 'undefined');
4050 * Portions of this file are based on pieces of Yahoo User Interface Library
4051 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4052 * YUI licensed under the BSD License:
4053 * http://developer.yahoo.net/yui/license.txt
4054 * <script type="text/javascript">
4058 Roo.lib.Scroll = function(el, attributes, duration, method) {
4060 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4064 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4068 var superclass = Y.Scroll.superclass;
4069 var proto = Y.Scroll.prototype;
4071 proto.toString = function() {
4072 var el = this.getEl();
4073 var id = el.id || el.tagName;
4074 return ("Scroll " + id);
4077 proto.doMethod = function(attr, start, end) {
4080 if (attr == 'scroll') {
4082 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4083 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4087 val = superclass.doMethod.call(this, attr, start, end);
4092 proto.getAttribute = function(attr) {
4094 var el = this.getEl();
4096 if (attr == 'scroll') {
4097 val = [ el.scrollLeft, el.scrollTop ];
4099 val = superclass.getAttribute.call(this, attr);
4105 proto.setAttribute = function(attr, val, unit) {
4106 var el = this.getEl();
4108 if (attr == 'scroll') {
4109 el.scrollLeft = val[0];
4110 el.scrollTop = val[1];
4112 superclass.setAttribute.call(this, attr, val, unit);
4118 * Ext JS Library 1.1.1
4119 * Copyright(c) 2006-2007, Ext JS, LLC.
4121 * Originally Released Under LGPL - original licence link has changed is not relivant.
4124 * <script type="text/javascript">
4128 // nasty IE9 hack - what a pile of crap that is..
4130 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4131 Range.prototype.createContextualFragment = function (html) {
4132 var doc = window.document;
4133 var container = doc.createElement("div");
4134 container.innerHTML = html;
4135 var frag = doc.createDocumentFragment(), n;
4136 while ((n = container.firstChild)) {
4137 frag.appendChild(n);
4144 * @class Roo.DomHelper
4145 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4146 * 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>.
4149 Roo.DomHelper = function(){
4150 var tempTableEl = null;
4151 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4152 var tableRe = /^table|tbody|tr|td$/i;
4154 // build as innerHTML where available
4156 var createHtml = function(o){
4157 if(typeof o == 'string'){
4166 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") { continue; }
4167 if(attr == "style"){
4169 if(typeof s == "function"){
4172 if(typeof s == "string"){
4173 b += ' style="' + s + '"';
4174 }else if(typeof s == "object"){
4177 if(typeof s[key] != "function"){
4178 b += key + ":" + s[key] + ";";
4185 b += ' class="' + o["cls"] + '"';
4186 }else if(attr == "htmlFor"){
4187 b += ' for="' + o["htmlFor"] + '"';
4189 b += " " + attr + '="' + o[attr] + '"';
4193 if(emptyTags.test(o.tag)){
4197 var cn = o.children || o.cn;
4199 //http://bugs.kde.org/show_bug.cgi?id=71506
4200 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4201 for(var i = 0, len = cn.length; i < len; i++) {
4202 b += createHtml(cn[i], b);
4205 b += createHtml(cn, b);
4211 b += "</" + o.tag + ">";
4218 var createDom = function(o, parentNode){
4220 // defininition craeted..
4222 if (o.ns && o.ns != 'html') {
4224 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4225 xmlns[o.ns] = o.xmlns;
4228 if (typeof(xmlns[o.ns]) == 'undefined') {
4229 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4235 if (typeof(o) == 'string') {
4236 return parentNode.appendChild(document.createTextNode(o));
4238 o.tag = o.tag || div;
4239 if (o.ns && Roo.isIE) {
4241 o.tag = o.ns + ':' + o.tag;
4244 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4245 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4248 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4249 attr == "style" || typeof o[attr] == "function") { continue; }
4251 if(attr=="cls" && Roo.isIE){
4252 el.className = o["cls"];
4254 if(useSet) { el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);}
4260 Roo.DomHelper.applyStyles(el, o.style);
4261 var cn = o.children || o.cn;
4263 //http://bugs.kde.org/show_bug.cgi?id=71506
4264 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4265 for(var i = 0, len = cn.length; i < len; i++) {
4266 createDom(cn[i], el);
4273 el.innerHTML = o.html;
4276 parentNode.appendChild(el);
4281 var ieTable = function(depth, s, h, e){
4282 tempTableEl.innerHTML = [s, h, e].join('');
4283 var i = -1, el = tempTableEl;
4290 // kill repeat to save bytes
4294 tbe = '</tbody>'+te,
4300 * Nasty code for IE's broken table implementation
4302 var insertIntoTable = function(tag, where, el, html){
4304 tempTableEl = document.createElement('div');
4309 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4312 if(where == 'beforebegin'){
4316 before = el.nextSibling;
4319 node = ieTable(4, trs, html, tre);
4321 else if(tag == 'tr'){
4322 if(where == 'beforebegin'){
4325 node = ieTable(3, tbs, html, tbe);
4326 } else if(where == 'afterend'){
4327 before = el.nextSibling;
4329 node = ieTable(3, tbs, html, tbe);
4330 } else{ // INTO a TR
4331 if(where == 'afterbegin'){
4332 before = el.firstChild;
4334 node = ieTable(4, trs, html, tre);
4336 } else if(tag == 'tbody'){
4337 if(where == 'beforebegin'){
4340 node = ieTable(2, ts, html, te);
4341 } else if(where == 'afterend'){
4342 before = el.nextSibling;
4344 node = ieTable(2, ts, html, te);
4346 if(where == 'afterbegin'){
4347 before = el.firstChild;
4349 node = ieTable(3, tbs, html, tbe);
4352 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4355 if(where == 'afterbegin'){
4356 before = el.firstChild;
4358 node = ieTable(2, ts, html, te);
4360 el.insertBefore(node, before);
4365 /** True to force the use of DOM instead of html fragments @type Boolean */
4369 * Returns the markup for the passed Element(s) config
4370 * @param {Object} o The Dom object spec (and children)
4373 markup : function(o){
4374 return createHtml(o);
4378 * Applies a style specification to an element
4379 * @param {String/HTMLElement} el The element to apply styles to
4380 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4381 * a function which returns such a specification.
4383 applyStyles : function(el, styles){
4386 if(typeof styles == "string"){
4387 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4389 while ((matches = re.exec(styles)) != null){
4390 el.setStyle(matches[1], matches[2]);
4392 }else if (typeof styles == "object"){
4393 for (var style in styles){
4394 el.setStyle(style, styles[style]);
4396 }else if (typeof styles == "function"){
4397 Roo.DomHelper.applyStyles(el, styles.call());
4403 * Inserts an HTML fragment into the Dom
4404 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4405 * @param {HTMLElement} el The context element
4406 * @param {String} html The HTML fragmenet
4407 * @return {HTMLElement} The new node
4409 insertHtml : function(where, el, html){
4410 where = where.toLowerCase();
4411 if(el.insertAdjacentHTML){
4412 if(tableRe.test(el.tagName)){
4414 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4420 el.insertAdjacentHTML('BeforeBegin', html);
4421 return el.previousSibling;
4423 el.insertAdjacentHTML('AfterBegin', html);
4424 return el.firstChild;
4426 el.insertAdjacentHTML('BeforeEnd', html);
4427 return el.lastChild;
4429 el.insertAdjacentHTML('AfterEnd', html);
4430 return el.nextSibling;
4432 throw 'Illegal insertion point -> "' + where + '"';
4434 var range = el.ownerDocument.createRange();
4438 range.setStartBefore(el);
4439 frag = range.createContextualFragment(html);
4440 el.parentNode.insertBefore(frag, el);
4441 return el.previousSibling;
4444 range.setStartBefore(el.firstChild);
4445 frag = range.createContextualFragment(html);
4446 el.insertBefore(frag, el.firstChild);
4447 return el.firstChild;
4449 el.innerHTML = html;
4450 return el.firstChild;
4454 range.setStartAfter(el.lastChild);
4455 frag = range.createContextualFragment(html);
4456 el.appendChild(frag);
4457 return el.lastChild;
4459 el.innerHTML = html;
4460 return el.lastChild;
4463 range.setStartAfter(el);
4464 frag = range.createContextualFragment(html);
4465 el.parentNode.insertBefore(frag, el.nextSibling);
4466 return el.nextSibling;
4468 throw 'Illegal insertion point -> "' + where + '"';
4472 * Creates new Dom element(s) and inserts them before el
4473 * @param {String/HTMLElement/Element} el The context element
4474 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4475 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4476 * @return {HTMLElement/Roo.Element} The new node
4478 insertBefore : function(el, o, returnElement){
4479 return this.doInsert(el, o, returnElement, "beforeBegin");
4483 * Creates new Dom element(s) and inserts them after el
4484 * @param {String/HTMLElement/Element} el The context element
4485 * @param {Object} o The Dom object spec (and children)
4486 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4487 * @return {HTMLElement/Roo.Element} The new node
4489 insertAfter : function(el, o, returnElement){
4490 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4494 * Creates new Dom element(s) and inserts them as the first child of el
4495 * @param {String/HTMLElement/Element} el The context element
4496 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4497 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4498 * @return {HTMLElement/Roo.Element} The new node
4500 insertFirst : function(el, o, returnElement){
4501 return this.doInsert(el, o, returnElement, "afterBegin");
4505 doInsert : function(el, o, returnElement, pos, sibling){
4506 el = Roo.getDom(el);
4508 if(this.useDom || o.ns){
4509 newNode = createDom(o, null);
4510 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4512 var html = createHtml(o);
4513 newNode = this.insertHtml(pos, el, html);
4515 return returnElement ? Roo.get(newNode, true) : newNode;
4519 * Creates new Dom element(s) and appends them to el
4520 * @param {String/HTMLElement/Element} el The context element
4521 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4522 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4523 * @return {HTMLElement/Roo.Element} The new node
4525 append : function(el, o, returnElement){
4526 el = Roo.getDom(el);
4528 if(this.useDom || o.ns){
4529 newNode = createDom(o, null);
4530 el.appendChild(newNode);
4532 var html = createHtml(o);
4533 newNode = this.insertHtml("beforeEnd", el, html);
4535 return returnElement ? Roo.get(newNode, true) : newNode;
4539 * Creates new Dom element(s) and overwrites the contents of el with them
4540 * @param {String/HTMLElement/Element} el The context element
4541 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4542 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4543 * @return {HTMLElement/Roo.Element} The new node
4545 overwrite : function(el, o, returnElement){
4546 el = Roo.getDom(el);
4549 while (el.childNodes.length) {
4550 el.removeChild(el.firstChild);
4554 el.innerHTML = createHtml(o);
4557 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4561 * Creates a new Roo.DomHelper.Template from the Dom object spec
4562 * @param {Object} o The Dom object spec (and children)
4563 * @return {Roo.DomHelper.Template} The new template
4565 createTemplate : function(o){
4566 var html = createHtml(o);
4567 return new Roo.Template(html);
4573 * Ext JS Library 1.1.1
4574 * Copyright(c) 2006-2007, Ext JS, LLC.
4576 * Originally Released Under LGPL - original licence link has changed is not relivant.
4579 * <script type="text/javascript">
4583 * @class Roo.Template
4584 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4585 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4588 var t = new Roo.Template({
4589 html : '<div name="{id}">' +
4590 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4592 myformat: function (value, allValues) {
4593 return 'XX' + value;
4596 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4598 * For more information see this blog post with examples:
4599 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4600 - Create Elements using DOM, HTML fragments and Templates</a>.
4602 * @param {Object} cfg - Configuration object.
4604 Roo.Template = function(cfg){
4606 if(cfg instanceof Array){
4608 }else if(arguments.length > 1){
4609 cfg = Array.prototype.join.call(arguments, "");
4613 if (typeof(cfg) == 'object') {
4624 Roo.Template.prototype = {
4627 * @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..
4628 * it should be fixed so that template is observable...
4632 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4636 * Returns an HTML fragment of this template with the specified values applied.
4637 * @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'})
4638 * @return {String} The HTML fragment
4640 applyTemplate : function(values){
4644 return this.compiled(values);
4646 var useF = this.disableFormats !== true;
4647 var fm = Roo.util.Format, tpl = this;
4648 var fn = function(m, name, format, args){
4650 if(format.substr(0, 5) == "this."){
4651 return tpl.call(format.substr(5), values[name], values);
4654 // quoted values are required for strings in compiled templates,
4655 // but for non compiled we need to strip them
4656 // quoted reversed for jsmin
4657 var re = /^\s*['"](.*)["']\s*$/;
4658 args = args.split(',');
4659 for(var i = 0, len = args.length; i < len; i++){
4660 args[i] = args[i].replace(re, "$1");
4662 args = [values[name]].concat(args);
4664 args = [values[name]];
4666 return fm[format].apply(fm, args);
4669 return values[name] !== undefined ? values[name] : "";
4672 return this.html.replace(this.re, fn);
4690 this.loading = true;
4691 this.compiled = false;
4693 var cx = new Roo.data.Connection();
4697 success : function (response) {
4699 _t.html = response.responseText;
4703 failure : function(response) {
4704 Roo.log("Template failed to load from " + _t.url);
4711 * Sets the HTML used as the template and optionally compiles it.
4712 * @param {String} html
4713 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4714 * @return {Roo.Template} this
4716 set : function(html, compile){
4718 this.compiled = null;
4726 * True to disable format functions (defaults to false)
4729 disableFormats : false,
4732 * The regular expression used to match template variables
4736 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4739 * Compiles the template into an internal function, eliminating the RegEx overhead.
4740 * @return {Roo.Template} this
4742 compile : function(){
4743 var fm = Roo.util.Format;
4744 var useF = this.disableFormats !== true;
4745 var sep = Roo.isGecko ? "+" : ",";
4746 var fn = function(m, name, format, args){
4748 args = args ? ',' + args : "";
4749 if(format.substr(0, 5) != "this."){
4750 format = "fm." + format + '(';
4752 format = 'this.call("'+ format.substr(5) + '", ';
4756 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4758 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4761 // branched to use + in gecko and [].join() in others
4763 body = "this.compiled = function(values){ return '" +
4764 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4767 body = ["this.compiled = function(values){ return ['"];
4768 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4769 body.push("'].join('');};");
4770 body = body.join('');
4780 // private function used to call members
4781 call : function(fnName, value, allValues){
4782 return this[fnName](value, allValues);
4786 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4787 * @param {String/HTMLElement/Roo.Element} el The context element
4788 * @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'})
4789 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4790 * @return {HTMLElement/Roo.Element} The new node or Element
4792 insertFirst: function(el, values, returnElement){
4793 return this.doInsert('afterBegin', el, values, returnElement);
4797 * Applies the supplied values to the template and inserts the new node(s) before el.
4798 * @param {String/HTMLElement/Roo.Element} el The context element
4799 * @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'})
4800 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4801 * @return {HTMLElement/Roo.Element} The new node or Element
4803 insertBefore: function(el, values, returnElement){
4804 return this.doInsert('beforeBegin', el, values, returnElement);
4808 * Applies the supplied values to the template and inserts the new node(s) after el.
4809 * @param {String/HTMLElement/Roo.Element} el The context element
4810 * @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'})
4811 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4812 * @return {HTMLElement/Roo.Element} The new node or Element
4814 insertAfter : function(el, values, returnElement){
4815 return this.doInsert('afterEnd', el, values, returnElement);
4819 * Applies the supplied values to the template and appends the new node(s) to el.
4820 * @param {String/HTMLElement/Roo.Element} el The context element
4821 * @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'})
4822 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4823 * @return {HTMLElement/Roo.Element} The new node or Element
4825 append : function(el, values, returnElement){
4826 return this.doInsert('beforeEnd', el, values, returnElement);
4829 doInsert : function(where, el, values, returnEl){
4830 el = Roo.getDom(el);
4831 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4832 return returnEl ? Roo.get(newNode, true) : newNode;
4836 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4837 * @param {String/HTMLElement/Roo.Element} el The context element
4838 * @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'})
4839 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4840 * @return {HTMLElement/Roo.Element} The new node or Element
4842 overwrite : function(el, values, returnElement){
4843 el = Roo.getDom(el);
4844 el.innerHTML = this.applyTemplate(values);
4845 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4849 * Alias for {@link #applyTemplate}
4852 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4855 Roo.DomHelper.Template = Roo.Template;
4858 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4859 * @param {String/HTMLElement} el A DOM element or its id
4860 * @returns {Roo.Template} The created template
4863 Roo.Template.from = function(el){
4864 el = Roo.getDom(el);
4865 return new Roo.Template(el.value || el.innerHTML);
4868 * Ext JS Library 1.1.1
4869 * Copyright(c) 2006-2007, Ext JS, LLC.
4871 * Originally Released Under LGPL - original licence link has changed is not relivant.
4874 * <script type="text/javascript">
4879 * This is code is also distributed under MIT license for use
4880 * with jQuery and prototype JavaScript libraries.
4883 * @class Roo.DomQuery
4884 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).
4886 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>
4889 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.
4891 <h4>Element Selectors:</h4>
4893 <li> <b>*</b> any element</li>
4894 <li> <b>E</b> an element with the tag E</li>
4895 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4896 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4897 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4898 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4900 <h4>Attribute Selectors:</h4>
4901 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4903 <li> <b>E[foo]</b> has an attribute "foo"</li>
4904 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4905 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4906 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4907 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4908 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4909 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4911 <h4>Pseudo Classes:</h4>
4913 <li> <b>E:first-child</b> E is the first child of its parent</li>
4914 <li> <b>E:last-child</b> E is the last child of its parent</li>
4915 <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>
4916 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4917 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4918 <li> <b>E:only-child</b> E is the only child of its parent</li>
4919 <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>
4920 <li> <b>E:first</b> the first E in the resultset</li>
4921 <li> <b>E:last</b> the last E in the resultset</li>
4922 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4923 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4924 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4925 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4926 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4927 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4928 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4929 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4930 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4932 <h4>CSS Value Selectors:</h4>
4934 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4935 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4936 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4937 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4938 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4939 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4943 Roo.DomQuery = function(){
4944 var cache = {}, simpleCache = {}, valueCache = {};
4945 var nonSpace = /\S/;
4946 var trimRe = /^\s+|\s+$/g;
4947 var tplRe = /\{(\d+)\}/g;
4948 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4949 var tagTokenRe = /^(#)?([\w-\*]+)/;
4950 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4952 function child(p, index){
4954 var n = p.firstChild;
4956 if(n.nodeType == 1){
4967 while((n = n.nextSibling) && n.nodeType != 1);
4972 while((n = n.previousSibling) && n.nodeType != 1);
4976 function children(d){
4977 var n = d.firstChild, ni = -1;
4979 var nx = n.nextSibling;
4980 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4990 function byClassName(c, a, v){
4994 var r = [], ri = -1, cn;
4995 for(var i = 0, ci; ci = c[i]; i++){
4996 if((' '+ci.className+' ').indexOf(v) != -1){
5003 function attrValue(n, attr){
5004 if(!n.tagName && typeof n.length != "undefined"){
5013 if(attr == "class" || attr == "className"){
5016 return n.getAttribute(attr) || n[attr];
5020 function getNodes(ns, mode, tagName){
5021 var result = [], ri = -1, cs;
5025 tagName = tagName || "*";
5026 if(typeof ns.getElementsByTagName != "undefined"){
5030 for(var i = 0, ni; ni = ns[i]; i++){
5031 cs = ni.getElementsByTagName(tagName);
5032 for(var j = 0, ci; ci = cs[j]; j++){
5036 }else if(mode == "/" || mode == ">"){
5037 var utag = tagName.toUpperCase();
5038 for(var i = 0, ni, cn; ni = ns[i]; i++){
5039 cn = ni.children || ni.childNodes;
5040 for(var j = 0, cj; cj = cn[j]; j++){
5041 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5046 }else if(mode == "+"){
5047 var utag = tagName.toUpperCase();
5048 for(var i = 0, n; n = ns[i]; i++){
5049 while((n = n.nextSibling) && n.nodeType != 1);
5050 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5054 }else if(mode == "~"){
5055 for(var i = 0, n; n = ns[i]; i++){
5056 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5065 function concat(a, b){
5069 for(var i = 0, l = b.length; i < l; i++){
5075 function byTag(cs, tagName){
5076 if(cs.tagName || cs == document){
5082 var r = [], ri = -1;
5083 tagName = tagName.toLowerCase();
5084 for(var i = 0, ci; ci = cs[i]; i++){
5085 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5092 function byId(cs, attr, id){
5093 if(cs.tagName || cs == document){
5099 var r = [], ri = -1;
5100 for(var i = 0,ci; ci = cs[i]; i++){
5101 if(ci && ci.id == id){
5109 function byAttribute(cs, attr, value, op, custom){
5110 var r = [], ri = -1, st = custom=="{";
5111 var f = Roo.DomQuery.operators[op];
5112 for(var i = 0, ci; ci = cs[i]; i++){
5115 a = Roo.DomQuery.getStyle(ci, attr);
5117 else if(attr == "class" || attr == "className"){
5119 }else if(attr == "for"){
5121 }else if(attr == "href"){
5122 a = ci.getAttribute("href", 2);
5124 a = ci.getAttribute(attr);
5126 if((f && f(a, value)) || (!f && a)){
5133 function byPseudo(cs, name, value){
5134 return Roo.DomQuery.pseudos[name](cs, value);
5137 // This is for IE MSXML which does not support expandos.
5138 // IE runs the same speed using setAttribute, however FF slows way down
5139 // and Safari completely fails so they need to continue to use expandos.
5140 var isIE = window.ActiveXObject ? true : false;
5142 // this eval is stop the compressor from
5143 // renaming the variable to something shorter
5145 /** eval:var:batch */
5150 function nodupIEXml(cs){
5152 cs[0].setAttribute("_nodup", d);
5154 for(var i = 1, len = cs.length; i < len; i++){
5156 if(!c.getAttribute("_nodup") != d){
5157 c.setAttribute("_nodup", d);
5161 for(var i = 0, len = cs.length; i < len; i++){
5162 cs[i].removeAttribute("_nodup");
5171 var len = cs.length, c, i, r = cs, cj, ri = -1;
5172 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5175 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5176 return nodupIEXml(cs);
5180 for(i = 1; c = cs[i]; i++){
5185 for(var j = 0; j < i; j++){
5188 for(j = i+1; cj = cs[j]; j++){
5200 function quickDiffIEXml(c1, c2){
5202 for(var i = 0, len = c1.length; i < len; i++){
5203 c1[i].setAttribute("_qdiff", d);
5206 for(var i = 0, len = c2.length; i < len; i++){
5207 if(c2[i].getAttribute("_qdiff") != d){
5208 r[r.length] = c2[i];
5211 for(var i = 0, len = c1.length; i < len; i++){
5212 c1[i].removeAttribute("_qdiff");
5217 function quickDiff(c1, c2){
5218 var len1 = c1.length;
5222 if(isIE && c1[0].selectSingleNode){
5223 return quickDiffIEXml(c1, c2);
5226 for(var i = 0; i < len1; i++){
5230 for(var i = 0, len = c2.length; i < len; i++){
5231 if(c2[i]._qdiff != d){
5232 r[r.length] = c2[i];
5238 function quickId(ns, mode, root, id){
5240 var d = root.ownerDocument || root;
5241 return d.getElementById(id);
5243 ns = getNodes(ns, mode, "*");
5244 return byId(ns, null, id);
5248 getStyle : function(el, name){
5249 return Roo.fly(el).getStyle(name);
5252 * Compiles a selector/xpath query into a reusable function. The returned function
5253 * takes one parameter "root" (optional), which is the context node from where the query should start.
5254 * @param {String} selector The selector/xpath query
5255 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5256 * @return {Function}
5258 compile : function(path, type){
5259 type = type || "select";
5261 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5262 var q = path, mode, lq;
5263 var tk = Roo.DomQuery.matchers;
5264 var tklen = tk.length;
5267 // accept leading mode switch
5268 var lmode = q.match(modeRe);
5269 if(lmode && lmode[1]){
5270 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5271 q = q.replace(lmode[1], "");
5273 // strip leading slashes
5274 while(path.substr(0, 1)=="/"){
5275 path = path.substr(1);
5278 while(q && lq != q){
5280 var tm = q.match(tagTokenRe);
5281 if(type == "select"){
5284 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5286 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5288 q = q.replace(tm[0], "");
5289 }else if(q.substr(0, 1) != '@'){
5290 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5295 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5297 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5299 q = q.replace(tm[0], "");
5302 while(!(mm = q.match(modeRe))){
5303 var matched = false;
5304 for(var j = 0; j < tklen; j++){
5306 var m = q.match(t.re);
5308 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5311 q = q.replace(m[0], "");
5316 // prevent infinite loop on bad selector
5318 throw 'Error parsing selector, parsing failed at "' + q + '"';
5322 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5323 q = q.replace(mm[1], "");
5326 fn[fn.length] = "return nodup(n);\n}";
5329 * list of variables that need from compression as they are used by eval.
5339 * eval:var:byClassName
5341 * eval:var:byAttribute
5342 * eval:var:attrValue
5350 * Selects a group of elements.
5351 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5352 * @param {Node} root (optional) The start of the query (defaults to document).
5355 select : function(path, root, type){
5356 if(!root || root == document){
5359 if(typeof root == "string"){
5360 root = document.getElementById(root);
5362 var paths = path.split(",");
5364 for(var i = 0, len = paths.length; i < len; i++){
5365 var p = paths[i].replace(trimRe, "");
5367 cache[p] = Roo.DomQuery.compile(p);
5369 throw p + " is not a valid selector";
5372 var result = cache[p](root);
5373 if(result && result != document){
5374 results = results.concat(result);
5377 if(paths.length > 1){
5378 return nodup(results);
5384 * Selects a single element.
5385 * @param {String} selector The selector/xpath query
5386 * @param {Node} root (optional) The start of the query (defaults to document).
5389 selectNode : function(path, root){
5390 return Roo.DomQuery.select(path, root)[0];
5394 * Selects the value of a node, optionally replacing null with the defaultValue.
5395 * @param {String} selector The selector/xpath query
5396 * @param {Node} root (optional) The start of the query (defaults to document).
5397 * @param {String} defaultValue
5399 selectValue : function(path, root, defaultValue){
5400 path = path.replace(trimRe, "");
5401 if(!valueCache[path]){
5402 valueCache[path] = Roo.DomQuery.compile(path, "select");
5404 var n = valueCache[path](root);
5405 n = n[0] ? n[0] : n;
5406 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5407 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5411 * Selects the value of a node, parsing integers and floats.
5412 * @param {String} selector The selector/xpath query
5413 * @param {Node} root (optional) The start of the query (defaults to document).
5414 * @param {Number} defaultValue
5417 selectNumber : function(path, root, defaultValue){
5418 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5419 return parseFloat(v);
5423 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5424 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5425 * @param {String} selector The simple selector to test
5428 is : function(el, ss){
5429 if(typeof el == "string"){
5430 el = document.getElementById(el);
5432 var isArray = (el instanceof Array);
5433 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5434 return isArray ? (result.length == el.length) : (result.length > 0);
5438 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5439 * @param {Array} el An array of elements to filter
5440 * @param {String} selector The simple selector to test
5441 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5442 * the selector instead of the ones that match
5445 filter : function(els, ss, nonMatches){
5446 ss = ss.replace(trimRe, "");
5447 if(!simpleCache[ss]){
5448 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5450 var result = simpleCache[ss](els);
5451 return nonMatches ? quickDiff(result, els) : result;
5455 * Collection of matching regular expressions and code snippets.
5459 select: 'n = byClassName(n, null, " {1} ");'
5461 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5462 select: 'n = byPseudo(n, "{1}", "{2}");'
5464 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5465 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5468 select: 'n = byId(n, null, "{1}");'
5471 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5476 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5477 * 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, > <.
5480 "=" : function(a, v){
5483 "!=" : function(a, v){
5486 "^=" : function(a, v){
5487 return a && a.substr(0, v.length) == v;
5489 "$=" : function(a, v){
5490 return a && a.substr(a.length-v.length) == v;
5492 "*=" : function(a, v){
5493 return a && a.indexOf(v) !== -1;
5495 "%=" : function(a, v){
5496 return (a % v) == 0;
5498 "|=" : function(a, v){
5499 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5501 "~=" : function(a, v){
5502 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5507 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5508 * and the argument (if any) supplied in the selector.
5511 "first-child" : function(c){
5512 var r = [], ri = -1, n;
5513 for(var i = 0, ci; ci = n = c[i]; i++){
5514 while((n = n.previousSibling) && n.nodeType != 1);
5522 "last-child" : function(c){
5523 var r = [], ri = -1, n;
5524 for(var i = 0, ci; ci = n = c[i]; i++){
5525 while((n = n.nextSibling) && n.nodeType != 1);
5533 "nth-child" : function(c, a) {
5534 var r = [], ri = -1;
5535 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5536 var f = (m[1] || 1) - 0, l = m[2] - 0;
5537 for(var i = 0, n; n = c[i]; i++){
5538 var pn = n.parentNode;
5539 if (batch != pn._batch) {
5541 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5542 if(cn.nodeType == 1){
5549 if (l == 0 || n.nodeIndex == l){
5552 } else if ((n.nodeIndex + l) % f == 0){
5560 "only-child" : function(c){
5561 var r = [], ri = -1;;
5562 for(var i = 0, ci; ci = c[i]; i++){
5563 if(!prev(ci) && !next(ci)){
5570 "empty" : function(c){
5571 var r = [], ri = -1;
5572 for(var i = 0, ci; ci = c[i]; i++){
5573 var cns = ci.childNodes, j = 0, cn, empty = true;
5576 if(cn.nodeType == 1 || cn.nodeType == 3){
5588 "contains" : function(c, v){
5589 var r = [], ri = -1;
5590 for(var i = 0, ci; ci = c[i]; i++){
5591 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5598 "nodeValue" : function(c, v){
5599 var r = [], ri = -1;
5600 for(var i = 0, ci; ci = c[i]; i++){
5601 if(ci.firstChild && ci.firstChild.nodeValue == v){
5608 "checked" : function(c){
5609 var r = [], ri = -1;
5610 for(var i = 0, ci; ci = c[i]; i++){
5611 if(ci.checked == true){
5618 "not" : function(c, ss){
5619 return Roo.DomQuery.filter(c, ss, true);
5622 "odd" : function(c){
5623 return this["nth-child"](c, "odd");
5626 "even" : function(c){
5627 return this["nth-child"](c, "even");
5630 "nth" : function(c, a){
5631 return c[a-1] || [];
5634 "first" : function(c){
5638 "last" : function(c){
5639 return c[c.length-1] || [];
5642 "has" : function(c, ss){
5643 var s = Roo.DomQuery.select;
5644 var r = [], ri = -1;
5645 for(var i = 0, ci; ci = c[i]; i++){
5646 if(s(ss, ci).length > 0){
5653 "next" : function(c, ss){
5654 var is = Roo.DomQuery.is;
5655 var r = [], ri = -1;
5656 for(var i = 0, ci; ci = c[i]; i++){
5665 "prev" : function(c, ss){
5666 var is = Roo.DomQuery.is;
5667 var r = [], ri = -1;
5668 for(var i = 0, ci; ci = c[i]; i++){
5681 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5682 * @param {String} path The selector/xpath query
5683 * @param {Node} root (optional) The start of the query (defaults to document).
5688 Roo.query = Roo.DomQuery.select;
5691 * Ext JS Library 1.1.1
5692 * Copyright(c) 2006-2007, Ext JS, LLC.
5694 * Originally Released Under LGPL - original licence link has changed is not relivant.
5697 * <script type="text/javascript">
5701 * @class Roo.util.Observable
5702 * Base class that provides a common interface for publishing events. Subclasses are expected to
5703 * to have a property "events" with all the events defined.<br>
5706 Employee = function(name){
5713 Roo.extend(Employee, Roo.util.Observable);
5715 * @param {Object} config properties to use (incuding events / listeners)
5718 Roo.util.Observable = function(cfg){
5721 this.addEvents(cfg.events || {});
5723 delete cfg.events; // make sure
5726 Roo.apply(this, cfg);
5729 this.on(this.listeners);
5730 delete this.listeners;
5733 Roo.util.Observable.prototype = {
5735 * @cfg {Object} listeners list of events and functions to call for this object,
5739 'click' : function(e) {
5749 * Fires the specified event with the passed parameters (minus the event name).
5750 * @param {String} eventName
5751 * @param {Object...} args Variable number of parameters are passed to handlers
5752 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5754 fireEvent : function(){
5755 var ce = this.events[arguments[0].toLowerCase()];
5756 if(typeof ce == "object"){
5757 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5764 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5767 * Appends an event handler to this component
5768 * @param {String} eventName The type of event to listen for
5769 * @param {Function} handler The method the event invokes
5770 * @param {Object} scope (optional) The scope in which to execute the handler
5771 * function. The handler function's "this" context.
5772 * @param {Object} options (optional) An object containing handler configuration
5773 * properties. This may contain any of the following properties:<ul>
5774 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5775 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5776 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5777 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5778 * by the specified number of milliseconds. If the event fires again within that time, the original
5779 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5782 * <b>Combining Options</b><br>
5783 * Using the options argument, it is possible to combine different types of listeners:<br>
5785 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5787 el.on('click', this.onClick, this, {
5794 * <b>Attaching multiple handlers in 1 call</b><br>
5795 * The method also allows for a single argument to be passed which is a config object containing properties
5796 * which specify multiple handlers.
5805 fn: this.onMouseOver,
5809 fn: this.onMouseOut,
5815 * Or a shorthand syntax which passes the same scope object to all handlers:
5818 'click': this.onClick,
5819 'mouseover': this.onMouseOver,
5820 'mouseout': this.onMouseOut,
5825 addListener : function(eventName, fn, scope, o){
5826 if(typeof eventName == "object"){
5829 if(this.filterOptRe.test(e)){
5832 if(typeof o[e] == "function"){
5834 this.addListener(e, o[e], o.scope, o);
5836 // individual options
5837 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5842 o = (!o || typeof o == "boolean") ? {} : o;
5843 eventName = eventName.toLowerCase();
5844 var ce = this.events[eventName] || true;
5845 if(typeof ce == "boolean"){
5846 ce = new Roo.util.Event(this, eventName);
5847 this.events[eventName] = ce;
5849 ce.addListener(fn, scope, o);
5853 * Removes a listener
5854 * @param {String} eventName The type of event to listen for
5855 * @param {Function} handler The handler to remove
5856 * @param {Object} scope (optional) The scope (this object) for the handler
5858 removeListener : function(eventName, fn, scope){
5859 var ce = this.events[eventName.toLowerCase()];
5860 if(typeof ce == "object"){
5861 ce.removeListener(fn, scope);
5866 * Removes all listeners for this object
5868 purgeListeners : function(){
5869 for(var evt in this.events){
5870 if(typeof this.events[evt] == "object"){
5871 this.events[evt].clearListeners();
5876 relayEvents : function(o, events){
5877 var createHandler = function(ename){
5879 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5882 for(var i = 0, len = events.length; i < len; i++){
5883 var ename = events[i];
5884 if(!this.events[ename]){ this.events[ename] = true; };
5885 o.on(ename, createHandler(ename), this);
5890 * Used to define events on this Observable
5891 * @param {Object} object The object with the events defined
5893 addEvents : function(o){
5897 Roo.applyIf(this.events, o);
5901 * Checks to see if this object has any listeners for a specified event
5902 * @param {String} eventName The name of the event to check for
5903 * @return {Boolean} True if the event is being listened for, else false
5905 hasListener : function(eventName){
5906 var e = this.events[eventName];
5907 return typeof e == "object" && e.listeners.length > 0;
5911 * Appends an event handler to this element (shorthand for addListener)
5912 * @param {String} eventName The type of event to listen for
5913 * @param {Function} handler The method the event invokes
5914 * @param {Object} scope (optional) The scope in which to execute the handler
5915 * function. The handler function's "this" context.
5916 * @param {Object} options (optional)
5919 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5921 * Removes a listener (shorthand for removeListener)
5922 * @param {String} eventName The type of event to listen for
5923 * @param {Function} handler The handler to remove
5924 * @param {Object} scope (optional) The scope (this object) for the handler
5927 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5930 * Starts capture on the specified Observable. All events will be passed
5931 * to the supplied function with the event name + standard signature of the event
5932 * <b>before</b> the event is fired. If the supplied function returns false,
5933 * the event will not fire.
5934 * @param {Observable} o The Observable to capture
5935 * @param {Function} fn The function to call
5936 * @param {Object} scope (optional) The scope (this object) for the fn
5939 Roo.util.Observable.capture = function(o, fn, scope){
5940 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5944 * Removes <b>all</b> added captures from the Observable.
5945 * @param {Observable} o The Observable to release
5948 Roo.util.Observable.releaseCapture = function(o){
5949 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5954 var createBuffered = function(h, o, scope){
5955 var task = new Roo.util.DelayedTask();
5957 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5961 var createSingle = function(h, e, fn, scope){
5963 e.removeListener(fn, scope);
5964 return h.apply(scope, arguments);
5968 var createDelayed = function(h, o, scope){
5970 var args = Array.prototype.slice.call(arguments, 0);
5971 setTimeout(function(){
5972 h.apply(scope, args);
5977 Roo.util.Event = function(obj, name){
5980 this.listeners = [];
5983 Roo.util.Event.prototype = {
5984 addListener : function(fn, scope, options){
5985 var o = options || {};
5986 scope = scope || this.obj;
5987 if(!this.isListening(fn, scope)){
5988 var l = {fn: fn, scope: scope, options: o};
5991 h = createDelayed(h, o, scope);
5994 h = createSingle(h, this, fn, scope);
5997 h = createBuffered(h, o, scope);
6000 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
6001 this.listeners.push(l);
6003 this.listeners = this.listeners.slice(0);
6004 this.listeners.push(l);
6009 findListener : function(fn, scope){
6010 scope = scope || this.obj;
6011 var ls = this.listeners;
6012 for(var i = 0, len = ls.length; i < len; i++){
6014 if(l.fn == fn && l.scope == scope){
6021 isListening : function(fn, scope){
6022 return this.findListener(fn, scope) != -1;
6025 removeListener : function(fn, scope){
6027 if((index = this.findListener(fn, scope)) != -1){
6029 this.listeners.splice(index, 1);
6031 this.listeners = this.listeners.slice(0);
6032 this.listeners.splice(index, 1);
6039 clearListeners : function(){
6040 this.listeners = [];
6044 var ls = this.listeners, scope, len = ls.length;
6047 var args = Array.prototype.slice.call(arguments, 0);
6048 for(var i = 0; i < len; i++){
6050 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6051 this.firing = false;
6055 this.firing = false;
6062 * Copyright(c) 2007-2017, Roo J Solutions Ltd
6069 * @class Roo.Document
6070 * @extends Roo.util.Observable
6071 * This is a convience class to wrap up the main document loading code.. , rather than adding Roo.onReady(......)
6073 * @param {Object} config the methods and properties of the 'base' class for the application.
6075 * Generic Page handler - implement this to start your app..
6078 * MyProject = new Roo.Document({
6080 'load' : true // your events..
6083 'ready' : function() {
6084 // fired on Roo.onReady()
6089 Roo.Document = function(cfg) {
6094 Roo.util.Observable.call(this,cfg);
6098 Roo.onReady(function() {
6099 _this.fireEvent('ready');
6105 Roo.extend(Roo.Document, Roo.util.Observable, {});/*
6107 * Ext JS Library 1.1.1
6108 * Copyright(c) 2006-2007, Ext JS, LLC.
6110 * Originally Released Under LGPL - original licence link has changed is not relivant.
6113 * <script type="text/javascript">
6117 * @class Roo.EventManager
6118 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6119 * several useful events directly.
6120 * See {@link Roo.EventObject} for more details on normalized event objects.
6123 Roo.EventManager = function(){
6124 var docReadyEvent, docReadyProcId, docReadyState = false;
6125 var resizeEvent, resizeTask, textEvent, textSize;
6126 var E = Roo.lib.Event;
6127 var D = Roo.lib.Dom;
6132 var fireDocReady = function(){
6134 docReadyState = true;
6137 clearInterval(docReadyProcId);
6139 if(Roo.isGecko || Roo.isOpera) {
6140 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6143 var defer = document.getElementById("ie-deferred-loader");
6145 defer.onreadystatechange = null;
6146 defer.parentNode.removeChild(defer);
6150 docReadyEvent.fire();
6151 docReadyEvent.clearListeners();
6156 var initDocReady = function(){
6157 docReadyEvent = new Roo.util.Event();
6158 if(Roo.isGecko || Roo.isOpera) {
6159 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6161 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6162 var defer = document.getElementById("ie-deferred-loader");
6163 defer.onreadystatechange = function(){
6164 if(this.readyState == "complete"){
6168 }else if(Roo.isSafari){
6169 docReadyProcId = setInterval(function(){
6170 var rs = document.readyState;
6171 if(rs == "complete") {
6176 // no matter what, make sure it fires on load
6177 E.on(window, "load", fireDocReady);
6180 var createBuffered = function(h, o){
6181 var task = new Roo.util.DelayedTask(h);
6183 // create new event object impl so new events don't wipe out properties
6184 e = new Roo.EventObjectImpl(e);
6185 task.delay(o.buffer, h, null, [e]);
6189 var createSingle = function(h, el, ename, fn){
6191 Roo.EventManager.removeListener(el, ename, fn);
6196 var createDelayed = function(h, o){
6198 // create new event object impl so new events don't wipe out properties
6199 e = new Roo.EventObjectImpl(e);
6200 setTimeout(function(){
6205 var transitionEndVal = false;
6207 var transitionEnd = function()
6209 if (transitionEndVal) {
6210 return transitionEndVal;
6212 var el = document.createElement('div');
6214 var transEndEventNames = {
6215 WebkitTransition : 'webkitTransitionEnd',
6216 MozTransition : 'transitionend',
6217 OTransition : 'oTransitionEnd otransitionend',
6218 transition : 'transitionend'
6221 for (var name in transEndEventNames) {
6222 if (el.style[name] !== undefined) {
6223 transitionEndVal = transEndEventNames[name];
6224 return transitionEndVal ;
6230 var listen = function(element, ename, opt, fn, scope){
6231 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6232 fn = fn || o.fn; scope = scope || o.scope;
6233 var el = Roo.getDom(element);
6237 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6240 if (ename == 'transitionend') {
6241 ename = transitionEnd();
6243 var h = function(e){
6244 e = Roo.EventObject.setEvent(e);
6247 t = e.getTarget(o.delegate, el);
6254 if(o.stopEvent === true){
6257 if(o.preventDefault === true){
6260 if(o.stopPropagation === true){
6261 e.stopPropagation();
6264 if(o.normalized === false){
6268 fn.call(scope || el, e, t, o);
6271 h = createDelayed(h, o);
6274 h = createSingle(h, el, ename, fn);
6277 h = createBuffered(h, o);
6279 fn._handlers = fn._handlers || [];
6282 fn._handlers.push([Roo.id(el), ename, h]);
6287 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6288 el.addEventListener("DOMMouseScroll", h, false);
6289 E.on(window, 'unload', function(){
6290 el.removeEventListener("DOMMouseScroll", h, false);
6293 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6294 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6299 var stopListening = function(el, ename, fn){
6300 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6302 for(var i = 0, len = hds.length; i < len; i++){
6304 if(h[0] == id && h[1] == ename){
6311 E.un(el, ename, hd);
6312 el = Roo.getDom(el);
6313 if(ename == "mousewheel" && el.addEventListener){
6314 el.removeEventListener("DOMMouseScroll", hd, false);
6316 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6317 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6321 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6328 * @scope Roo.EventManager
6333 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6334 * object with a Roo.EventObject
6335 * @param {Function} fn The method the event invokes
6336 * @param {Object} scope An object that becomes the scope of the handler
6337 * @param {boolean} override If true, the obj passed in becomes
6338 * the execution scope of the listener
6339 * @return {Function} The wrapped function
6342 wrap : function(fn, scope, override){
6344 Roo.EventObject.setEvent(e);
6345 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6350 * Appends an event handler to an element (shorthand for addListener)
6351 * @param {String/HTMLElement} element The html element or id to assign the
6352 * @param {String} eventName The type of event to listen for
6353 * @param {Function} handler The method the event invokes
6354 * @param {Object} scope (optional) The scope in which to execute the handler
6355 * function. The handler function's "this" context.
6356 * @param {Object} options (optional) An object containing handler configuration
6357 * properties. This may contain any of the following properties:<ul>
6358 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6359 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6360 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6361 * <li>preventDefault {Boolean} True to prevent the default action</li>
6362 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6363 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6364 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6365 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6366 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6367 * by the specified number of milliseconds. If the event fires again within that time, the original
6368 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6371 * <b>Combining Options</b><br>
6372 * Using the options argument, it is possible to combine different types of listeners:<br>
6374 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6376 el.on('click', this.onClick, this, {
6383 * <b>Attaching multiple handlers in 1 call</b><br>
6384 * The method also allows for a single argument to be passed which is a config object containing properties
6385 * which specify multiple handlers.
6395 fn: this.onMouseOver
6404 * Or a shorthand syntax:<br>
6407 'click' : this.onClick,
6408 'mouseover' : this.onMouseOver,
6409 'mouseout' : this.onMouseOut
6413 addListener : function(element, eventName, fn, scope, options){
6414 if(typeof eventName == "object"){
6420 if(typeof o[e] == "function"){
6422 listen(element, e, o, o[e], o.scope);
6424 // individual options
6425 listen(element, e, o[e]);
6430 return listen(element, eventName, options, fn, scope);
6434 * Removes an event handler
6436 * @param {String/HTMLElement} element The id or html element to remove the
6438 * @param {String} eventName The type of event
6439 * @param {Function} fn
6440 * @return {Boolean} True if a listener was actually removed
6442 removeListener : function(element, eventName, fn){
6443 return stopListening(element, eventName, fn);
6447 * Fires when the document is ready (before onload and before images are loaded). Can be
6448 * accessed shorthanded Roo.onReady().
6449 * @param {Function} fn The method the event invokes
6450 * @param {Object} scope An object that becomes the scope of the handler
6451 * @param {boolean} options
6453 onDocumentReady : function(fn, scope, options){
6454 if(docReadyState){ // if it already fired
6455 docReadyEvent.addListener(fn, scope, options);
6456 docReadyEvent.fire();
6457 docReadyEvent.clearListeners();
6463 docReadyEvent.addListener(fn, scope, options);
6467 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6468 * @param {Function} fn The method the event invokes
6469 * @param {Object} scope An object that becomes the scope of the handler
6470 * @param {boolean} options
6472 onWindowResize : function(fn, scope, options){
6474 resizeEvent = new Roo.util.Event();
6475 resizeTask = new Roo.util.DelayedTask(function(){
6476 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6478 E.on(window, "resize", function(){
6480 resizeTask.delay(50);
6482 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6486 resizeEvent.addListener(fn, scope, options);
6490 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6491 * @param {Function} fn The method the event invokes
6492 * @param {Object} scope An object that becomes the scope of the handler
6493 * @param {boolean} options
6495 onTextResize : function(fn, scope, options){
6497 textEvent = new Roo.util.Event();
6498 var textEl = new Roo.Element(document.createElement('div'));
6499 textEl.dom.className = 'x-text-resize';
6500 textEl.dom.innerHTML = 'X';
6501 textEl.appendTo(document.body);
6502 textSize = textEl.dom.offsetHeight;
6503 setInterval(function(){
6504 if(textEl.dom.offsetHeight != textSize){
6505 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6507 }, this.textResizeInterval);
6509 textEvent.addListener(fn, scope, options);
6513 * Removes the passed window resize listener.
6514 * @param {Function} fn The method the event invokes
6515 * @param {Object} scope The scope of handler
6517 removeResizeListener : function(fn, scope){
6519 resizeEvent.removeListener(fn, scope);
6524 fireResize : function(){
6526 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6530 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6534 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6536 textResizeInterval : 50
6541 * @scopeAlias pub=Roo.EventManager
6545 * Appends an event handler to an element (shorthand for addListener)
6546 * @param {String/HTMLElement} element The html element or id to assign the
6547 * @param {String} eventName The type of event to listen for
6548 * @param {Function} handler The method the event invokes
6549 * @param {Object} scope (optional) The scope in which to execute the handler
6550 * function. The handler function's "this" context.
6551 * @param {Object} options (optional) An object containing handler configuration
6552 * properties. This may contain any of the following properties:<ul>
6553 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6554 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6555 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6556 * <li>preventDefault {Boolean} True to prevent the default action</li>
6557 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6558 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6559 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6560 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6561 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6562 * by the specified number of milliseconds. If the event fires again within that time, the original
6563 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6566 * <b>Combining Options</b><br>
6567 * Using the options argument, it is possible to combine different types of listeners:<br>
6569 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6571 el.on('click', this.onClick, this, {
6578 * <b>Attaching multiple handlers in 1 call</b><br>
6579 * The method also allows for a single argument to be passed which is a config object containing properties
6580 * which specify multiple handlers.
6590 fn: this.onMouseOver
6599 * Or a shorthand syntax:<br>
6602 'click' : this.onClick,
6603 'mouseover' : this.onMouseOver,
6604 'mouseout' : this.onMouseOut
6608 pub.on = pub.addListener;
6609 pub.un = pub.removeListener;
6611 pub.stoppedMouseDownEvent = new Roo.util.Event();
6615 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6616 * @param {Function} fn The method the event invokes
6617 * @param {Object} scope An object that becomes the scope of the handler
6618 * @param {boolean} override If true, the obj passed in becomes
6619 * the execution scope of the listener
6623 Roo.onReady = Roo.EventManager.onDocumentReady;
6625 Roo.onReady(function(){
6626 var bd = Roo.get(document.body);
6631 : Roo.isIE11 ? "roo-ie11"
6632 : Roo.isGecko ? "roo-gecko"
6633 : Roo.isOpera ? "roo-opera"
6634 : Roo.isSafari ? "roo-safari" : ""];
6637 cls.push("roo-mac");
6640 cls.push("roo-linux");
6643 cls.push("roo-ios");
6646 cls.push("roo-touch");
6648 if(Roo.isBorderBox){
6649 cls.push('roo-border-box');
6651 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6652 var p = bd.dom.parentNode;
6654 p.className += ' roo-strict';
6657 bd.addClass(cls.join(' '));
6661 * @class Roo.EventObject
6662 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6663 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6666 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6668 var target = e.getTarget();
6671 var myDiv = Roo.get("myDiv");
6672 myDiv.on("click", handleClick);
6674 Roo.EventManager.on("myDiv", 'click', handleClick);
6675 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6679 Roo.EventObject = function(){
6681 var E = Roo.lib.Event;
6683 // safari keypress events for special keys return bad keycodes
6686 63235 : 39, // right
6689 63276 : 33, // page up
6690 63277 : 34, // page down
6691 63272 : 46, // delete
6696 // normalize button clicks
6697 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6698 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6700 Roo.EventObjectImpl = function(e){
6702 this.setEvent(e.browserEvent || e);
6705 Roo.EventObjectImpl.prototype = {
6707 * Used to fix doc tools.
6708 * @scope Roo.EventObject.prototype
6714 /** The normal browser event */
6715 browserEvent : null,
6716 /** The button pressed in a mouse event */
6718 /** True if the shift key was down during the event */
6720 /** True if the control key was down during the event */
6722 /** True if the alt key was down during the event */
6781 setEvent : function(e){
6782 if(e == this || (e && e.browserEvent)){ // already wrapped
6785 this.browserEvent = e;
6787 // normalize buttons
6788 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6789 if(e.type == 'click' && this.button == -1){
6793 this.shiftKey = e.shiftKey;
6794 // mac metaKey behaves like ctrlKey
6795 this.ctrlKey = e.ctrlKey || e.metaKey;
6796 this.altKey = e.altKey;
6797 // in getKey these will be normalized for the mac
6798 this.keyCode = e.keyCode;
6799 // keyup warnings on firefox.
6800 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6801 // cache the target for the delayed and or buffered events
6802 this.target = E.getTarget(e);
6804 this.xy = E.getXY(e);
6807 this.shiftKey = false;
6808 this.ctrlKey = false;
6809 this.altKey = false;
6819 * Stop the event (preventDefault and stopPropagation)
6821 stopEvent : function(){
6822 if(this.browserEvent){
6823 if(this.browserEvent.type == 'mousedown'){
6824 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6826 E.stopEvent(this.browserEvent);
6831 * Prevents the browsers default handling of the event.
6833 preventDefault : function(){
6834 if(this.browserEvent){
6835 E.preventDefault(this.browserEvent);
6840 isNavKeyPress : function(){
6841 var k = this.keyCode;
6842 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6843 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6846 isSpecialKey : function(){
6847 var k = this.keyCode;
6848 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6849 (k == 16) || (k == 17) ||
6850 (k >= 18 && k <= 20) ||
6851 (k >= 33 && k <= 35) ||
6852 (k >= 36 && k <= 39) ||
6853 (k >= 44 && k <= 45);
6856 * Cancels bubbling of the event.
6858 stopPropagation : function(){
6859 if(this.browserEvent){
6860 if(this.type == 'mousedown'){
6861 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6863 E.stopPropagation(this.browserEvent);
6868 * Gets the key code for the event.
6871 getCharCode : function(){
6872 return this.charCode || this.keyCode;
6876 * Returns a normalized keyCode for the event.
6877 * @return {Number} The key code
6879 getKey : function(){
6880 var k = this.keyCode || this.charCode;
6881 return Roo.isSafari ? (safariKeys[k] || k) : k;
6885 * Gets the x coordinate of the event.
6888 getPageX : function(){
6893 * Gets the y coordinate of the event.
6896 getPageY : function(){
6901 * Gets the time of the event.
6904 getTime : function(){
6905 if(this.browserEvent){
6906 return E.getTime(this.browserEvent);
6912 * Gets the page coordinates of the event.
6913 * @return {Array} The xy values like [x, y]
6920 * Gets the target for the event.
6921 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6922 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6923 search as a number or element (defaults to 10 || document.body)
6924 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6925 * @return {HTMLelement}
6927 getTarget : function(selector, maxDepth, returnEl){
6928 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6931 * Gets the related target.
6932 * @return {HTMLElement}
6934 getRelatedTarget : function(){
6935 if(this.browserEvent){
6936 return E.getRelatedTarget(this.browserEvent);
6942 * Normalizes mouse wheel delta across browsers
6943 * @return {Number} The delta
6945 getWheelDelta : function(){
6946 var e = this.browserEvent;
6948 if(e.wheelDelta){ /* IE/Opera. */
6949 delta = e.wheelDelta/120;
6950 }else if(e.detail){ /* Mozilla case. */
6951 delta = -e.detail/3;
6957 * Returns true if the control, meta, shift or alt key was pressed during this event.
6960 hasModifier : function(){
6961 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6965 * Returns true if the target of this event equals el or is a child of el
6966 * @param {String/HTMLElement/Element} el
6967 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6970 within : function(el, related){
6971 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6972 return t && Roo.fly(el).contains(t);
6975 getPoint : function(){
6976 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6980 return new Roo.EventObjectImpl();
6985 * Ext JS Library 1.1.1
6986 * Copyright(c) 2006-2007, Ext JS, LLC.
6988 * Originally Released Under LGPL - original licence link has changed is not relivant.
6991 * <script type="text/javascript">
6995 // was in Composite Element!??!?!
6998 var D = Roo.lib.Dom;
6999 var E = Roo.lib.Event;
7000 var A = Roo.lib.Anim;
7002 // local style camelizing for speed
7004 var camelRe = /(-[a-z])/gi;
7005 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
7006 var view = document.defaultView;
7009 * @class Roo.Element
7010 * Represents an Element in the DOM.<br><br>
7013 var el = Roo.get("my-div");
7016 var el = getEl("my-div");
7018 // or with a DOM element
7019 var el = Roo.get(myDivElement);
7021 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
7022 * each call instead of constructing a new one.<br><br>
7023 * <b>Animations</b><br />
7024 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
7025 * should either be a boolean (true) or an object literal with animation options. The animation options are:
7027 Option Default Description
7028 --------- -------- ---------------------------------------------
7029 duration .35 The duration of the animation in seconds
7030 easing easeOut The YUI easing method
7031 callback none A function to execute when the anim completes
7032 scope this The scope (this) of the callback function
7034 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
7035 * manipulate the animation. Here's an example:
7037 var el = Roo.get("my-div");
7042 // default animation
7043 el.setWidth(100, true);
7045 // animation with some options set
7052 // using the "anim" property to get the Anim object
7058 el.setWidth(100, opt);
7060 if(opt.anim.isAnimated()){
7064 * <b> Composite (Collections of) Elements</b><br />
7065 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
7066 * @constructor Create a new Element directly.
7067 * @param {String/HTMLElement} element
7068 * @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).
7070 Roo.Element = function(element, forceNew){
7071 var dom = typeof element == "string" ?
7072 document.getElementById(element) : element;
7073 if(!dom){ // invalid id/element
7077 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7078 return Roo.Element.cache[id];
7088 * The DOM element ID
7091 this.id = id || Roo.id(dom);
7094 var El = Roo.Element;
7098 * The element's default display mode (defaults to "")
7101 originalDisplay : "",
7105 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7111 * Sets the element's visibility mode. When setVisible() is called it
7112 * will use this to determine whether to set the visibility or the display property.
7113 * @param visMode Element.VISIBILITY or Element.DISPLAY
7114 * @return {Roo.Element} this
7116 setVisibilityMode : function(visMode){
7117 this.visibilityMode = visMode;
7121 * Convenience method for setVisibilityMode(Element.DISPLAY)
7122 * @param {String} display (optional) What to set display to when visible
7123 * @return {Roo.Element} this
7125 enableDisplayMode : function(display){
7126 this.setVisibilityMode(El.DISPLAY);
7127 if(typeof display != "undefined") { this.originalDisplay = display; }
7132 * 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)
7133 * @param {String} selector The simple selector to test
7134 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7135 search as a number or element (defaults to 10 || document.body)
7136 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7137 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7139 findParent : function(simpleSelector, maxDepth, returnEl){
7140 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7141 maxDepth = maxDepth || 50;
7142 if(typeof maxDepth != "number"){
7143 stopEl = Roo.getDom(maxDepth);
7146 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7147 if(dq.is(p, simpleSelector)){
7148 return returnEl ? Roo.get(p) : p;
7158 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7159 * @param {String} selector The simple selector to test
7160 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7161 search as a number or element (defaults to 10 || document.body)
7162 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7163 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7165 findParentNode : function(simpleSelector, maxDepth, returnEl){
7166 var p = Roo.fly(this.dom.parentNode, '_internal');
7167 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7171 * Looks at the scrollable parent element
7173 findScrollableParent : function()
7175 var overflowRegex = /(auto|scroll)/;
7177 if(this.getStyle('position') === 'fixed'){
7178 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7181 var excludeStaticParent = this.getStyle('position') === "absolute";
7183 for (var parent = this; (parent = Roo.get(parent.dom.parentNode));){
7185 if (excludeStaticParent && parent.getStyle('position') === "static") {
7189 if (overflowRegex.test(parent.getStyle('overflow') + parent.getStyle('overflow-x') + parent.getStyle('overflow-y'))){
7193 if(parent.dom.nodeName.toLowerCase() == 'body'){
7194 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7198 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7202 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7203 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7204 * @param {String} selector The simple selector to test
7205 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7206 search as a number or element (defaults to 10 || document.body)
7207 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7209 up : function(simpleSelector, maxDepth){
7210 return this.findParentNode(simpleSelector, maxDepth, true);
7216 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7217 * @param {String} selector The simple selector to test
7218 * @return {Boolean} True if this element matches the selector, else false
7220 is : function(simpleSelector){
7221 return Roo.DomQuery.is(this.dom, simpleSelector);
7225 * Perform animation on this element.
7226 * @param {Object} args The YUI animation control args
7227 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7228 * @param {Function} onComplete (optional) Function to call when animation completes
7229 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7230 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7231 * @return {Roo.Element} this
7233 animate : function(args, duration, onComplete, easing, animType){
7234 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7239 * @private Internal animation call
7241 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7242 animType = animType || 'run';
7244 var anim = Roo.lib.Anim[animType](
7246 (opt.duration || defaultDur) || .35,
7247 (opt.easing || defaultEase) || 'easeOut',
7249 Roo.callback(cb, this);
7250 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7258 // private legacy anim prep
7259 preanim : function(a, i){
7260 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7264 * Removes worthless text nodes
7265 * @param {Boolean} forceReclean (optional) By default the element
7266 * keeps track if it has been cleaned already so
7267 * you can call this over and over. However, if you update the element and
7268 * need to force a reclean, you can pass true.
7270 clean : function(forceReclean){
7271 if(this.isCleaned && forceReclean !== true){
7275 var d = this.dom, n = d.firstChild, ni = -1;
7277 var nx = n.nextSibling;
7278 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7285 this.isCleaned = true;
7290 calcOffsetsTo : function(el){
7293 var restorePos = false;
7294 if(el.getStyle('position') == 'static'){
7295 el.position('relative');
7300 while(op && op != d && op.tagName != 'HTML'){
7303 op = op.offsetParent;
7306 el.position('static');
7312 * Scrolls this element into view within the passed container.
7313 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7314 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7315 * @return {Roo.Element} this
7317 scrollIntoView : function(container, hscroll){
7318 var c = Roo.getDom(container) || document.body;
7321 var o = this.calcOffsetsTo(c),
7324 b = t+el.offsetHeight,
7325 r = l+el.offsetWidth;
7327 var ch = c.clientHeight;
7328 var ct = parseInt(c.scrollTop, 10);
7329 var cl = parseInt(c.scrollLeft, 10);
7331 var cr = cl + c.clientWidth;
7339 if(hscroll !== false){
7343 c.scrollLeft = r-c.clientWidth;
7350 scrollChildIntoView : function(child, hscroll){
7351 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7355 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7356 * the new height may not be available immediately.
7357 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7358 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7359 * @param {Function} onComplete (optional) Function to call when animation completes
7360 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7361 * @return {Roo.Element} this
7363 autoHeight : function(animate, duration, onComplete, easing){
7364 var oldHeight = this.getHeight();
7366 this.setHeight(1); // force clipping
7367 setTimeout(function(){
7368 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7370 this.setHeight(height);
7372 if(typeof onComplete == "function"){
7376 this.setHeight(oldHeight); // restore original height
7377 this.setHeight(height, animate, duration, function(){
7379 if(typeof onComplete == "function") { onComplete(); }
7380 }.createDelegate(this), easing);
7382 }.createDelegate(this), 0);
7387 * Returns true if this element is an ancestor of the passed element
7388 * @param {HTMLElement/String} el The element to check
7389 * @return {Boolean} True if this element is an ancestor of el, else false
7391 contains : function(el){
7392 if(!el){return false;}
7393 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7397 * Checks whether the element is currently visible using both visibility and display properties.
7398 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7399 * @return {Boolean} True if the element is currently visible, else false
7401 isVisible : function(deep) {
7402 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7403 if(deep !== true || !vis){
7406 var p = this.dom.parentNode;
7407 while(p && p.tagName.toLowerCase() != "body"){
7408 if(!Roo.fly(p, '_isVisible').isVisible()){
7417 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7418 * @param {String} selector The CSS selector
7419 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7420 * @return {CompositeElement/CompositeElementLite} The composite element
7422 select : function(selector, unique){
7423 return El.select(selector, unique, this.dom);
7427 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7428 * @param {String} selector The CSS selector
7429 * @return {Array} An array of the matched nodes
7431 query : function(selector, unique){
7432 return Roo.DomQuery.select(selector, this.dom);
7436 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7437 * @param {String} selector The CSS selector
7438 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7439 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7441 child : function(selector, returnDom){
7442 var n = Roo.DomQuery.selectNode(selector, this.dom);
7443 return returnDom ? n : Roo.get(n);
7447 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7448 * @param {String} selector The CSS selector
7449 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7450 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7452 down : function(selector, returnDom){
7453 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7454 return returnDom ? n : Roo.get(n);
7458 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7459 * @param {String} group The group the DD object is member of
7460 * @param {Object} config The DD config object
7461 * @param {Object} overrides An object containing methods to override/implement on the DD object
7462 * @return {Roo.dd.DD} The DD object
7464 initDD : function(group, config, overrides){
7465 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7466 return Roo.apply(dd, overrides);
7470 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7471 * @param {String} group The group the DDProxy object is member of
7472 * @param {Object} config The DDProxy config object
7473 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7474 * @return {Roo.dd.DDProxy} The DDProxy object
7476 initDDProxy : function(group, config, overrides){
7477 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7478 return Roo.apply(dd, overrides);
7482 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7483 * @param {String} group The group the DDTarget object is member of
7484 * @param {Object} config The DDTarget config object
7485 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7486 * @return {Roo.dd.DDTarget} The DDTarget object
7488 initDDTarget : function(group, config, overrides){
7489 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7490 return Roo.apply(dd, overrides);
7494 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7495 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7496 * @param {Boolean} visible Whether the element is visible
7497 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7498 * @return {Roo.Element} this
7500 setVisible : function(visible, animate){
7502 if(this.visibilityMode == El.DISPLAY){
7503 this.setDisplayed(visible);
7506 this.dom.style.visibility = visible ? "visible" : "hidden";
7509 // closure for composites
7511 var visMode = this.visibilityMode;
7513 this.setOpacity(.01);
7514 this.setVisible(true);
7516 this.anim({opacity: { to: (visible?1:0) }},
7517 this.preanim(arguments, 1),
7518 null, .35, 'easeIn', function(){
7520 if(visMode == El.DISPLAY){
7521 dom.style.display = "none";
7523 dom.style.visibility = "hidden";
7525 Roo.get(dom).setOpacity(1);
7533 * Returns true if display is not "none"
7536 isDisplayed : function() {
7537 return this.getStyle("display") != "none";
7541 * Toggles the element's visibility or display, depending on visibility mode.
7542 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7543 * @return {Roo.Element} this
7545 toggle : function(animate){
7546 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7551 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7552 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7553 * @return {Roo.Element} this
7555 setDisplayed : function(value) {
7556 if(typeof value == "boolean"){
7557 value = value ? this.originalDisplay : "none";
7559 this.setStyle("display", value);
7564 * Tries to focus the element. Any exceptions are caught and ignored.
7565 * @return {Roo.Element} this
7567 focus : function() {
7575 * Tries to blur the element. Any exceptions are caught and ignored.
7576 * @return {Roo.Element} this
7586 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7587 * @param {String/Array} className The CSS class to add, or an array of classes
7588 * @return {Roo.Element} this
7590 addClass : function(className){
7591 if(className instanceof Array){
7592 for(var i = 0, len = className.length; i < len; i++) {
7593 this.addClass(className[i]);
7596 if(className && !this.hasClass(className)){
7597 this.dom.className = this.dom.className + " " + className;
7604 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7605 * @param {String/Array} className The CSS class to add, or an array of classes
7606 * @return {Roo.Element} this
7608 radioClass : function(className){
7609 var siblings = this.dom.parentNode.childNodes;
7610 for(var i = 0; i < siblings.length; i++) {
7611 var s = siblings[i];
7612 if(s.nodeType == 1){
7613 Roo.get(s).removeClass(className);
7616 this.addClass(className);
7621 * Removes one or more CSS classes from the element.
7622 * @param {String/Array} className The CSS class to remove, or an array of classes
7623 * @return {Roo.Element} this
7625 removeClass : function(className){
7626 if(!className || !this.dom.className){
7629 if(className instanceof Array){
7630 for(var i = 0, len = className.length; i < len; i++) {
7631 this.removeClass(className[i]);
7634 if(this.hasClass(className)){
7635 var re = this.classReCache[className];
7637 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7638 this.classReCache[className] = re;
7640 this.dom.className =
7641 this.dom.className.replace(re, " ");
7651 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7652 * @param {String} className The CSS class to toggle
7653 * @return {Roo.Element} this
7655 toggleClass : function(className){
7656 if(this.hasClass(className)){
7657 this.removeClass(className);
7659 this.addClass(className);
7665 * Checks if the specified CSS class exists on this element's DOM node.
7666 * @param {String} className The CSS class to check for
7667 * @return {Boolean} True if the class exists, else false
7669 hasClass : function(className){
7670 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7674 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7675 * @param {String} oldClassName The CSS class to replace
7676 * @param {String} newClassName The replacement CSS class
7677 * @return {Roo.Element} this
7679 replaceClass : function(oldClassName, newClassName){
7680 this.removeClass(oldClassName);
7681 this.addClass(newClassName);
7686 * Returns an object with properties matching the styles requested.
7687 * For example, el.getStyles('color', 'font-size', 'width') might return
7688 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7689 * @param {String} style1 A style name
7690 * @param {String} style2 A style name
7691 * @param {String} etc.
7692 * @return {Object} The style object
7694 getStyles : function(){
7695 var a = arguments, len = a.length, r = {};
7696 for(var i = 0; i < len; i++){
7697 r[a[i]] = this.getStyle(a[i]);
7703 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7704 * @param {String} property The style property whose value is returned.
7705 * @return {String} The current value of the style property for this element.
7707 getStyle : function(){
7708 return view && view.getComputedStyle ?
7710 var el = this.dom, v, cs, camel;
7711 if(prop == 'float'){
7714 if(el.style && (v = el.style[prop])){
7717 if(cs = view.getComputedStyle(el, "")){
7718 if(!(camel = propCache[prop])){
7719 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7726 var el = this.dom, v, cs, camel;
7727 if(prop == 'opacity'){
7728 if(typeof el.style.filter == 'string'){
7729 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7731 var fv = parseFloat(m[1]);
7733 return fv ? fv / 100 : 0;
7738 }else if(prop == 'float'){
7739 prop = "styleFloat";
7741 if(!(camel = propCache[prop])){
7742 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7744 if(v = el.style[camel]){
7747 if(cs = el.currentStyle){
7755 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7756 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7757 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7758 * @return {Roo.Element} this
7760 setStyle : function(prop, value){
7761 if(typeof prop == "string"){
7763 if (prop == 'float') {
7764 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7769 if(!(camel = propCache[prop])){
7770 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7773 if(camel == 'opacity') {
7774 this.setOpacity(value);
7776 this.dom.style[camel] = value;
7779 for(var style in prop){
7780 if(typeof prop[style] != "function"){
7781 this.setStyle(style, prop[style]);
7789 * More flexible version of {@link #setStyle} for setting style properties.
7790 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7791 * a function which returns such a specification.
7792 * @return {Roo.Element} this
7794 applyStyles : function(style){
7795 Roo.DomHelper.applyStyles(this.dom, style);
7800 * 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).
7801 * @return {Number} The X position of the element
7804 return D.getX(this.dom);
7808 * 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).
7809 * @return {Number} The Y position of the element
7812 return D.getY(this.dom);
7816 * 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).
7817 * @return {Array} The XY position of the element
7820 return D.getXY(this.dom);
7824 * 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).
7825 * @param {Number} The X position of the element
7826 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7827 * @return {Roo.Element} this
7829 setX : function(x, animate){
7831 D.setX(this.dom, x);
7833 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7839 * 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).
7840 * @param {Number} The Y position of the element
7841 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7842 * @return {Roo.Element} this
7844 setY : function(y, animate){
7846 D.setY(this.dom, y);
7848 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7854 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7855 * @param {String} left The left CSS property value
7856 * @return {Roo.Element} this
7858 setLeft : function(left){
7859 this.setStyle("left", this.addUnits(left));
7864 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7865 * @param {String} top The top CSS property value
7866 * @return {Roo.Element} this
7868 setTop : function(top){
7869 this.setStyle("top", this.addUnits(top));
7874 * Sets the element's CSS right style.
7875 * @param {String} right The right CSS property value
7876 * @return {Roo.Element} this
7878 setRight : function(right){
7879 this.setStyle("right", this.addUnits(right));
7884 * Sets the element's CSS bottom style.
7885 * @param {String} bottom The bottom CSS property value
7886 * @return {Roo.Element} this
7888 setBottom : function(bottom){
7889 this.setStyle("bottom", this.addUnits(bottom));
7894 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7895 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7896 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7897 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7898 * @return {Roo.Element} this
7900 setXY : function(pos, animate){
7902 D.setXY(this.dom, pos);
7904 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7910 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7911 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7912 * @param {Number} x X value for new position (coordinates are page-based)
7913 * @param {Number} y Y value for new position (coordinates are page-based)
7914 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7915 * @return {Roo.Element} this
7917 setLocation : function(x, y, animate){
7918 this.setXY([x, y], this.preanim(arguments, 2));
7923 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7924 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7925 * @param {Number} x X value for new position (coordinates are page-based)
7926 * @param {Number} y Y value for new position (coordinates are page-based)
7927 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7928 * @return {Roo.Element} this
7930 moveTo : function(x, y, animate){
7931 this.setXY([x, y], this.preanim(arguments, 2));
7936 * Returns the region of the given element.
7937 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7938 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7940 getRegion : function(){
7941 return D.getRegion(this.dom);
7945 * Returns the offset height of the element
7946 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7947 * @return {Number} The element's height
7949 getHeight : function(contentHeight){
7950 var h = this.dom.offsetHeight || 0;
7951 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7955 * Returns the offset width of the element
7956 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7957 * @return {Number} The element's width
7959 getWidth : function(contentWidth){
7960 var w = this.dom.offsetWidth || 0;
7961 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7965 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7966 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7967 * if a height has not been set using CSS.
7970 getComputedHeight : function(){
7971 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7973 h = parseInt(this.getStyle('height'), 10) || 0;
7974 if(!this.isBorderBox()){
7975 h += this.getFrameWidth('tb');
7982 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7983 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7984 * if a width has not been set using CSS.
7987 getComputedWidth : function(){
7988 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7990 w = parseInt(this.getStyle('width'), 10) || 0;
7991 if(!this.isBorderBox()){
7992 w += this.getFrameWidth('lr');
7999 * Returns the size of the element.
8000 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
8001 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
8003 getSize : function(contentSize){
8004 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
8008 * Returns the width and height of the viewport.
8009 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
8011 getViewSize : function(){
8012 var d = this.dom, doc = document, aw = 0, ah = 0;
8013 if(d == doc || d == doc.body){
8014 return {width : D.getViewWidth(), height: D.getViewHeight()};
8017 width : d.clientWidth,
8018 height: d.clientHeight
8024 * Returns the value of the "value" attribute
8025 * @param {Boolean} asNumber true to parse the value as a number
8026 * @return {String/Number}
8028 getValue : function(asNumber){
8029 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
8033 adjustWidth : function(width){
8034 if(typeof width == "number"){
8035 if(this.autoBoxAdjust && !this.isBorderBox()){
8036 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8046 adjustHeight : function(height){
8047 if(typeof height == "number"){
8048 if(this.autoBoxAdjust && !this.isBorderBox()){
8049 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8059 * Set the width of the element
8060 * @param {Number} width The new width
8061 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8062 * @return {Roo.Element} this
8064 setWidth : function(width, animate){
8065 width = this.adjustWidth(width);
8067 this.dom.style.width = this.addUnits(width);
8069 this.anim({width: {to: width}}, this.preanim(arguments, 1));
8075 * Set the height of the element
8076 * @param {Number} height The new height
8077 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8078 * @return {Roo.Element} this
8080 setHeight : function(height, animate){
8081 height = this.adjustHeight(height);
8083 this.dom.style.height = this.addUnits(height);
8085 this.anim({height: {to: height}}, this.preanim(arguments, 1));
8091 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
8092 * @param {Number} width The new width
8093 * @param {Number} height The new height
8094 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8095 * @return {Roo.Element} this
8097 setSize : function(width, height, animate){
8098 if(typeof width == "object"){ // in case of object from getSize()
8099 height = width.height; width = width.width;
8101 width = this.adjustWidth(width); height = this.adjustHeight(height);
8103 this.dom.style.width = this.addUnits(width);
8104 this.dom.style.height = this.addUnits(height);
8106 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8112 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8113 * @param {Number} x X value for new position (coordinates are page-based)
8114 * @param {Number} y Y value for new position (coordinates are page-based)
8115 * @param {Number} width The new width
8116 * @param {Number} height The new height
8117 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8118 * @return {Roo.Element} this
8120 setBounds : function(x, y, width, height, animate){
8122 this.setSize(width, height);
8123 this.setLocation(x, y);
8125 width = this.adjustWidth(width); height = this.adjustHeight(height);
8126 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8127 this.preanim(arguments, 4), 'motion');
8133 * 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.
8134 * @param {Roo.lib.Region} region The region to fill
8135 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8136 * @return {Roo.Element} this
8138 setRegion : function(region, animate){
8139 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8144 * Appends an event handler
8146 * @param {String} eventName The type of event to append
8147 * @param {Function} fn The method the event invokes
8148 * @param {Object} scope (optional) The scope (this object) of the fn
8149 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8151 addListener : function(eventName, fn, scope, options){
8153 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8158 * Removes an event handler from this element
8159 * @param {String} eventName the type of event to remove
8160 * @param {Function} fn the method the event invokes
8161 * @return {Roo.Element} this
8163 removeListener : function(eventName, fn){
8164 Roo.EventManager.removeListener(this.dom, eventName, fn);
8169 * Removes all previous added listeners from this element
8170 * @return {Roo.Element} this
8172 removeAllListeners : function(){
8173 E.purgeElement(this.dom);
8177 relayEvent : function(eventName, observable){
8178 this.on(eventName, function(e){
8179 observable.fireEvent(eventName, e);
8184 * Set the opacity of the element
8185 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8186 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8187 * @return {Roo.Element} this
8189 setOpacity : function(opacity, animate){
8191 var s = this.dom.style;
8194 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8195 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8197 s.opacity = opacity;
8200 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8206 * Gets the left X coordinate
8207 * @param {Boolean} local True to get the local css position instead of page coordinate
8210 getLeft : function(local){
8214 return parseInt(this.getStyle("left"), 10) || 0;
8219 * Gets the right X coordinate of the element (element X position + element width)
8220 * @param {Boolean} local True to get the local css position instead of page coordinate
8223 getRight : function(local){
8225 return this.getX() + this.getWidth();
8227 return (this.getLeft(true) + this.getWidth()) || 0;
8232 * Gets the top Y coordinate
8233 * @param {Boolean} local True to get the local css position instead of page coordinate
8236 getTop : function(local) {
8240 return parseInt(this.getStyle("top"), 10) || 0;
8245 * Gets the bottom Y coordinate of the element (element Y position + element height)
8246 * @param {Boolean} local True to get the local css position instead of page coordinate
8249 getBottom : function(local){
8251 return this.getY() + this.getHeight();
8253 return (this.getTop(true) + this.getHeight()) || 0;
8258 * Initializes positioning on this element. If a desired position is not passed, it will make the
8259 * the element positioned relative IF it is not already positioned.
8260 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8261 * @param {Number} zIndex (optional) The zIndex to apply
8262 * @param {Number} x (optional) Set the page X position
8263 * @param {Number} y (optional) Set the page Y position
8265 position : function(pos, zIndex, x, y){
8267 if(this.getStyle('position') == 'static'){
8268 this.setStyle('position', 'relative');
8271 this.setStyle("position", pos);
8274 this.setStyle("z-index", zIndex);
8276 if(x !== undefined && y !== undefined){
8278 }else if(x !== undefined){
8280 }else if(y !== undefined){
8286 * Clear positioning back to the default when the document was loaded
8287 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8288 * @return {Roo.Element} this
8290 clearPositioning : function(value){
8298 "position" : "static"
8304 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8305 * snapshot before performing an update and then restoring the element.
8308 getPositioning : function(){
8309 var l = this.getStyle("left");
8310 var t = this.getStyle("top");
8312 "position" : this.getStyle("position"),
8314 "right" : l ? "" : this.getStyle("right"),
8316 "bottom" : t ? "" : this.getStyle("bottom"),
8317 "z-index" : this.getStyle("z-index")
8322 * Gets the width of the border(s) for the specified side(s)
8323 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8324 * passing lr would get the border (l)eft width + the border (r)ight width.
8325 * @return {Number} The width of the sides passed added together
8327 getBorderWidth : function(side){
8328 return this.addStyles(side, El.borders);
8332 * Gets the width of the padding(s) for the specified side(s)
8333 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8334 * passing lr would get the padding (l)eft + the padding (r)ight.
8335 * @return {Number} The padding of the sides passed added together
8337 getPadding : function(side){
8338 return this.addStyles(side, El.paddings);
8342 * Set positioning with an object returned by getPositioning().
8343 * @param {Object} posCfg
8344 * @return {Roo.Element} this
8346 setPositioning : function(pc){
8347 this.applyStyles(pc);
8348 if(pc.right == "auto"){
8349 this.dom.style.right = "";
8351 if(pc.bottom == "auto"){
8352 this.dom.style.bottom = "";
8358 fixDisplay : function(){
8359 if(this.getStyle("display") == "none"){
8360 this.setStyle("visibility", "hidden");
8361 this.setStyle("display", this.originalDisplay); // first try reverting to default
8362 if(this.getStyle("display") == "none"){ // if that fails, default to block
8363 this.setStyle("display", "block");
8369 * Quick set left and top adding default units
8370 * @param {String} left The left CSS property value
8371 * @param {String} top The top CSS property value
8372 * @return {Roo.Element} this
8374 setLeftTop : function(left, top){
8375 this.dom.style.left = this.addUnits(left);
8376 this.dom.style.top = this.addUnits(top);
8381 * Move this element relative to its current position.
8382 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8383 * @param {Number} distance How far to move the element in pixels
8384 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8385 * @return {Roo.Element} this
8387 move : function(direction, distance, animate){
8388 var xy = this.getXY();
8389 direction = direction.toLowerCase();
8393 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8397 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8402 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8407 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8414 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8415 * @return {Roo.Element} this
8418 if(!this.isClipped){
8419 this.isClipped = true;
8420 this.originalClip = {
8421 "o": this.getStyle("overflow"),
8422 "x": this.getStyle("overflow-x"),
8423 "y": this.getStyle("overflow-y")
8425 this.setStyle("overflow", "hidden");
8426 this.setStyle("overflow-x", "hidden");
8427 this.setStyle("overflow-y", "hidden");
8433 * Return clipping (overflow) to original clipping before clip() was called
8434 * @return {Roo.Element} this
8436 unclip : function(){
8438 this.isClipped = false;
8439 var o = this.originalClip;
8440 if(o.o){this.setStyle("overflow", o.o);}
8441 if(o.x){this.setStyle("overflow-x", o.x);}
8442 if(o.y){this.setStyle("overflow-y", o.y);}
8449 * Gets the x,y coordinates specified by the anchor position on the element.
8450 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8451 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8452 * {width: (target width), height: (target height)} (defaults to the element's current size)
8453 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8454 * @return {Array} [x, y] An array containing the element's x and y coordinates
8456 getAnchorXY : function(anchor, local, s){
8457 //Passing a different size is useful for pre-calculating anchors,
8458 //especially for anchored animations that change the el size.
8460 var w, h, vp = false;
8463 if(d == document.body || d == document){
8465 w = D.getViewWidth(); h = D.getViewHeight();
8467 w = this.getWidth(); h = this.getHeight();
8470 w = s.width; h = s.height;
8472 var x = 0, y = 0, r = Math.round;
8473 switch((anchor || "tl").toLowerCase()){
8515 var sc = this.getScroll();
8516 return [x + sc.left, y + sc.top];
8518 //Add the element's offset xy
8519 var o = this.getXY();
8520 return [x+o[0], y+o[1]];
8524 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8525 * supported position values.
8526 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8527 * @param {String} position The position to align to.
8528 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8529 * @return {Array} [x, y]
8531 getAlignToXY : function(el, p, o){
8535 throw "Element.alignTo with an element that doesn't exist";
8537 var c = false; //constrain to viewport
8538 var p1 = "", p2 = "";
8545 }else if(p.indexOf("-") == -1){
8548 p = p.toLowerCase();
8549 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8551 throw "Element.alignTo with an invalid alignment " + p;
8553 p1 = m[1]; p2 = m[2]; c = !!m[3];
8555 //Subtract the aligned el's internal xy from the target's offset xy
8556 //plus custom offset to get the aligned el's new offset xy
8557 var a1 = this.getAnchorXY(p1, true);
8558 var a2 = el.getAnchorXY(p2, false);
8559 var x = a2[0] - a1[0] + o[0];
8560 var y = a2[1] - a1[1] + o[1];
8562 //constrain the aligned el to viewport if necessary
8563 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8564 // 5px of margin for ie
8565 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8567 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8568 //perpendicular to the vp border, allow the aligned el to slide on that border,
8569 //otherwise swap the aligned el to the opposite border of the target.
8570 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8571 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8572 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8573 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8576 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8577 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8579 if((x+w) > dw + scrollX){
8580 x = swapX ? r.left-w : dw+scrollX-w;
8583 x = swapX ? r.right : scrollX;
8585 if((y+h) > dh + scrollY){
8586 y = swapY ? r.top-h : dh+scrollY-h;
8589 y = swapY ? r.bottom : scrollY;
8596 getConstrainToXY : function(){
8597 var os = {top:0, left:0, bottom:0, right: 0};
8599 return function(el, local, offsets, proposedXY){
8601 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8603 var vw, vh, vx = 0, vy = 0;
8604 if(el.dom == document.body || el.dom == document){
8605 vw = Roo.lib.Dom.getViewWidth();
8606 vh = Roo.lib.Dom.getViewHeight();
8608 vw = el.dom.clientWidth;
8609 vh = el.dom.clientHeight;
8611 var vxy = el.getXY();
8617 var s = el.getScroll();
8619 vx += offsets.left + s.left;
8620 vy += offsets.top + s.top;
8622 vw -= offsets.right;
8623 vh -= offsets.bottom;
8628 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8629 var x = xy[0], y = xy[1];
8630 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8632 // only move it if it needs it
8635 // first validate right/bottom
8644 // then make sure top/left isn't negative
8653 return moved ? [x, y] : false;
8658 adjustForConstraints : function(xy, parent, offsets){
8659 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8663 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8664 * document it aligns it to the viewport.
8665 * The position parameter is optional, and can be specified in any one of the following formats:
8667 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8668 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8669 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8670 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8671 * <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
8672 * element's anchor point, and the second value is used as the target's anchor point.</li>
8674 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8675 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8676 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8677 * that specified in order to enforce the viewport constraints.
8678 * Following are all of the supported anchor positions:
8681 ----- -----------------------------
8682 tl The top left corner (default)
8683 t The center of the top edge
8684 tr The top right corner
8685 l The center of the left edge
8686 c In the center of the element
8687 r The center of the right edge
8688 bl The bottom left corner
8689 b The center of the bottom edge
8690 br The bottom right corner
8694 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8695 el.alignTo("other-el");
8697 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8698 el.alignTo("other-el", "tr?");
8700 // align the bottom right corner of el with the center left edge of other-el
8701 el.alignTo("other-el", "br-l?");
8703 // align the center of el with the bottom left corner of other-el and
8704 // adjust the x position by -6 pixels (and the y position by 0)
8705 el.alignTo("other-el", "c-bl", [-6, 0]);
8707 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8708 * @param {String} position The position to align to.
8709 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8710 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8711 * @return {Roo.Element} this
8713 alignTo : function(element, position, offsets, animate){
8714 var xy = this.getAlignToXY(element, position, offsets);
8715 this.setXY(xy, this.preanim(arguments, 3));
8720 * Anchors an element to another element and realigns it when the window is resized.
8721 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8722 * @param {String} position The position to align to.
8723 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8724 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8725 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8726 * is a number, it is used as the buffer delay (defaults to 50ms).
8727 * @param {Function} callback The function to call after the animation finishes
8728 * @return {Roo.Element} this
8730 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8731 var action = function(){
8732 this.alignTo(el, alignment, offsets, animate);
8733 Roo.callback(callback, this);
8735 Roo.EventManager.onWindowResize(action, this);
8736 var tm = typeof monitorScroll;
8737 if(tm != 'undefined'){
8738 Roo.EventManager.on(window, 'scroll', action, this,
8739 {buffer: tm == 'number' ? monitorScroll : 50});
8741 action.call(this); // align immediately
8745 * Clears any opacity settings from this element. Required in some cases for IE.
8746 * @return {Roo.Element} this
8748 clearOpacity : function(){
8749 if (window.ActiveXObject) {
8750 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8751 this.dom.style.filter = "";
8754 this.dom.style.opacity = "";
8755 this.dom.style["-moz-opacity"] = "";
8756 this.dom.style["-khtml-opacity"] = "";
8762 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8763 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8764 * @return {Roo.Element} this
8766 hide : function(animate){
8767 this.setVisible(false, this.preanim(arguments, 0));
8772 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8773 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8774 * @return {Roo.Element} this
8776 show : function(animate){
8777 this.setVisible(true, this.preanim(arguments, 0));
8782 * @private Test if size has a unit, otherwise appends the default
8784 addUnits : function(size){
8785 return Roo.Element.addUnits(size, this.defaultUnit);
8789 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8790 * @return {Roo.Element} this
8792 beginMeasure : function(){
8794 if(el.offsetWidth || el.offsetHeight){
8795 return this; // offsets work already
8798 var p = this.dom, b = document.body; // start with this element
8799 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8800 var pe = Roo.get(p);
8801 if(pe.getStyle('display') == 'none'){
8802 changed.push({el: p, visibility: pe.getStyle("visibility")});
8803 p.style.visibility = "hidden";
8804 p.style.display = "block";
8808 this._measureChanged = changed;
8814 * Restores displays to before beginMeasure was called
8815 * @return {Roo.Element} this
8817 endMeasure : function(){
8818 var changed = this._measureChanged;
8820 for(var i = 0, len = changed.length; i < len; i++) {
8822 r.el.style.visibility = r.visibility;
8823 r.el.style.display = "none";
8825 this._measureChanged = null;
8831 * Update the innerHTML of this element, optionally searching for and processing scripts
8832 * @param {String} html The new HTML
8833 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8834 * @param {Function} callback For async script loading you can be noticed when the update completes
8835 * @return {Roo.Element} this
8837 update : function(html, loadScripts, callback){
8838 if(typeof html == "undefined"){
8841 if(loadScripts !== true){
8842 this.dom.innerHTML = html;
8843 if(typeof callback == "function"){
8851 html += '<span id="' + id + '"></span>';
8853 E.onAvailable(id, function(){
8854 var hd = document.getElementsByTagName("head")[0];
8855 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8856 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8857 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8860 while(match = re.exec(html)){
8861 var attrs = match[1];
8862 var srcMatch = attrs ? attrs.match(srcRe) : false;
8863 if(srcMatch && srcMatch[2]){
8864 var s = document.createElement("script");
8865 s.src = srcMatch[2];
8866 var typeMatch = attrs.match(typeRe);
8867 if(typeMatch && typeMatch[2]){
8868 s.type = typeMatch[2];
8871 }else if(match[2] && match[2].length > 0){
8872 if(window.execScript) {
8873 window.execScript(match[2]);
8881 window.eval(match[2]);
8885 var el = document.getElementById(id);
8886 if(el){el.parentNode.removeChild(el);}
8887 if(typeof callback == "function"){
8891 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8896 * Direct access to the UpdateManager update() method (takes the same parameters).
8897 * @param {String/Function} url The url for this request or a function to call to get the url
8898 * @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}
8899 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8900 * @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.
8901 * @return {Roo.Element} this
8904 var um = this.getUpdateManager();
8905 um.update.apply(um, arguments);
8910 * Gets this element's UpdateManager
8911 * @return {Roo.UpdateManager} The UpdateManager
8913 getUpdateManager : function(){
8914 if(!this.updateManager){
8915 this.updateManager = new Roo.UpdateManager(this);
8917 return this.updateManager;
8921 * Disables text selection for this element (normalized across browsers)
8922 * @return {Roo.Element} this
8924 unselectable : function(){
8925 this.dom.unselectable = "on";
8926 this.swallowEvent("selectstart", true);
8927 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8928 this.addClass("x-unselectable");
8933 * Calculates the x, y to center this element on the screen
8934 * @return {Array} The x, y values [x, y]
8936 getCenterXY : function(){
8937 return this.getAlignToXY(document, 'c-c');
8941 * Centers the Element in either the viewport, or another Element.
8942 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8944 center : function(centerIn){
8945 this.alignTo(centerIn || document, 'c-c');
8950 * Tests various css rules/browsers to determine if this element uses a border box
8953 isBorderBox : function(){
8954 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8958 * Return a box {x, y, width, height} that can be used to set another elements
8959 * size/location to match this element.
8960 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8961 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8962 * @return {Object} box An object in the format {x, y, width, height}
8964 getBox : function(contentBox, local){
8969 var left = parseInt(this.getStyle("left"), 10) || 0;
8970 var top = parseInt(this.getStyle("top"), 10) || 0;
8973 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8975 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8977 var l = this.getBorderWidth("l")+this.getPadding("l");
8978 var r = this.getBorderWidth("r")+this.getPadding("r");
8979 var t = this.getBorderWidth("t")+this.getPadding("t");
8980 var b = this.getBorderWidth("b")+this.getPadding("b");
8981 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)};
8983 bx.right = bx.x + bx.width;
8984 bx.bottom = bx.y + bx.height;
8989 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8990 for more information about the sides.
8991 * @param {String} sides
8994 getFrameWidth : function(sides, onlyContentBox){
8995 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8999 * 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.
9000 * @param {Object} box The box to fill {x, y, width, height}
9001 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
9002 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9003 * @return {Roo.Element} this
9005 setBox : function(box, adjust, animate){
9006 var w = box.width, h = box.height;
9007 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
9008 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
9009 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
9011 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
9016 * Forces the browser to repaint this element
9017 * @return {Roo.Element} this
9019 repaint : function(){
9021 this.addClass("x-repaint");
9022 setTimeout(function(){
9023 Roo.get(dom).removeClass("x-repaint");
9029 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
9030 * then it returns the calculated width of the sides (see getPadding)
9031 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
9032 * @return {Object/Number}
9034 getMargins : function(side){
9037 top: parseInt(this.getStyle("margin-top"), 10) || 0,
9038 left: parseInt(this.getStyle("margin-left"), 10) || 0,
9039 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
9040 right: parseInt(this.getStyle("margin-right"), 10) || 0
9043 return this.addStyles(side, El.margins);
9048 addStyles : function(sides, styles){
9050 for(var i = 0, len = sides.length; i < len; i++){
9051 v = this.getStyle(styles[sides.charAt(i)]);
9053 w = parseInt(v, 10);
9061 * Creates a proxy element of this element
9062 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
9063 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
9064 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
9065 * @return {Roo.Element} The new proxy element
9067 createProxy : function(config, renderTo, matchBox){
9069 renderTo = Roo.getDom(renderTo);
9071 renderTo = document.body;
9073 config = typeof config == "object" ?
9074 config : {tag : "div", cls: config};
9075 var proxy = Roo.DomHelper.append(renderTo, config, true);
9077 proxy.setBox(this.getBox());
9083 * Puts a mask over this element to disable user interaction. Requires core.css.
9084 * This method can only be applied to elements which accept child nodes.
9085 * @param {String} msg (optional) A message to display in the mask
9086 * @param {String} msgCls (optional) A css class to apply to the msg element
9087 * @return {Element} The mask element
9089 mask : function(msg, msgCls)
9091 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
9092 this.setStyle("position", "relative");
9095 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
9097 this.addClass("x-masked");
9098 this._mask.setDisplayed(true);
9103 while (dom && dom.style) {
9104 if (!isNaN(parseInt(dom.style.zIndex))) {
9105 z = Math.max(z, parseInt(dom.style.zIndex));
9107 dom = dom.parentNode;
9109 // if we are masking the body - then it hides everything..
9110 if (this.dom == document.body) {
9112 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9113 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9116 if(typeof msg == 'string'){
9118 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9120 var mm = this._maskMsg;
9121 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9122 if (mm.dom.firstChild) { // weird IE issue?
9123 mm.dom.firstChild.innerHTML = msg;
9125 mm.setDisplayed(true);
9127 mm.setStyle('z-index', z + 102);
9129 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9130 this._mask.setHeight(this.getHeight());
9132 this._mask.setStyle('z-index', z + 100);
9138 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9139 * it is cached for reuse.
9141 unmask : function(removeEl){
9143 if(removeEl === true){
9144 this._mask.remove();
9147 this._maskMsg.remove();
9148 delete this._maskMsg;
9151 this._mask.setDisplayed(false);
9153 this._maskMsg.setDisplayed(false);
9157 this.removeClass("x-masked");
9161 * Returns true if this element is masked
9164 isMasked : function(){
9165 return this._mask && this._mask.isVisible();
9169 * Creates an iframe shim for this element to keep selects and other windowed objects from
9171 * @return {Roo.Element} The new shim element
9173 createShim : function(){
9174 var el = document.createElement('iframe');
9175 el.frameBorder = 'no';
9176 el.className = 'roo-shim';
9177 if(Roo.isIE && Roo.isSecure){
9178 el.src = Roo.SSL_SECURE_URL;
9180 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9181 shim.autoBoxAdjust = false;
9186 * Removes this element from the DOM and deletes it from the cache
9188 remove : function(){
9189 if(this.dom.parentNode){
9190 this.dom.parentNode.removeChild(this.dom);
9192 delete El.cache[this.dom.id];
9196 * Sets up event handlers to add and remove a css class when the mouse is over this element
9197 * @param {String} className
9198 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9199 * mouseout events for children elements
9200 * @return {Roo.Element} this
9202 addClassOnOver : function(className, preventFlicker){
9203 this.on("mouseover", function(){
9204 Roo.fly(this, '_internal').addClass(className);
9206 var removeFn = function(e){
9207 if(preventFlicker !== true || !e.within(this, true)){
9208 Roo.fly(this, '_internal').removeClass(className);
9211 this.on("mouseout", removeFn, this.dom);
9216 * Sets up event handlers to add and remove a css class when this element has the focus
9217 * @param {String} className
9218 * @return {Roo.Element} this
9220 addClassOnFocus : function(className){
9221 this.on("focus", function(){
9222 Roo.fly(this, '_internal').addClass(className);
9224 this.on("blur", function(){
9225 Roo.fly(this, '_internal').removeClass(className);
9230 * 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)
9231 * @param {String} className
9232 * @return {Roo.Element} this
9234 addClassOnClick : function(className){
9236 this.on("mousedown", function(){
9237 Roo.fly(dom, '_internal').addClass(className);
9238 var d = Roo.get(document);
9239 var fn = function(){
9240 Roo.fly(dom, '_internal').removeClass(className);
9241 d.removeListener("mouseup", fn);
9243 d.on("mouseup", fn);
9249 * Stops the specified event from bubbling and optionally prevents the default action
9250 * @param {String} eventName
9251 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9252 * @return {Roo.Element} this
9254 swallowEvent : function(eventName, preventDefault){
9255 var fn = function(e){
9256 e.stopPropagation();
9261 if(eventName instanceof Array){
9262 for(var i = 0, len = eventName.length; i < len; i++){
9263 this.on(eventName[i], fn);
9267 this.on(eventName, fn);
9274 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9277 * Sizes this element to its parent element's dimensions performing
9278 * neccessary box adjustments.
9279 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9280 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9281 * @return {Roo.Element} this
9283 fitToParent : function(monitorResize, targetParent) {
9284 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9285 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9286 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9289 var p = Roo.get(targetParent || this.dom.parentNode);
9290 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9291 if (monitorResize === true) {
9292 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9293 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9299 * Gets the next sibling, skipping text nodes
9300 * @return {HTMLElement} The next sibling or null
9302 getNextSibling : function(){
9303 var n = this.dom.nextSibling;
9304 while(n && n.nodeType != 1){
9311 * Gets the previous sibling, skipping text nodes
9312 * @return {HTMLElement} The previous sibling or null
9314 getPrevSibling : function(){
9315 var n = this.dom.previousSibling;
9316 while(n && n.nodeType != 1){
9317 n = n.previousSibling;
9324 * Appends the passed element(s) to this element
9325 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9326 * @return {Roo.Element} this
9328 appendChild: function(el){
9335 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9336 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9337 * automatically generated with the specified attributes.
9338 * @param {HTMLElement} insertBefore (optional) a child element of this element
9339 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9340 * @return {Roo.Element} The new child element
9342 createChild: function(config, insertBefore, returnDom){
9343 config = config || {tag:'div'};
9345 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9347 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9351 * Appends this element to the passed element
9352 * @param {String/HTMLElement/Element} el The new parent element
9353 * @return {Roo.Element} this
9355 appendTo: function(el){
9356 el = Roo.getDom(el);
9357 el.appendChild(this.dom);
9362 * Inserts this element before the passed element in the DOM
9363 * @param {String/HTMLElement/Element} el The element to insert before
9364 * @return {Roo.Element} this
9366 insertBefore: function(el){
9367 el = Roo.getDom(el);
9368 el.parentNode.insertBefore(this.dom, el);
9373 * Inserts this element after the passed element in the DOM
9374 * @param {String/HTMLElement/Element} el The element to insert after
9375 * @return {Roo.Element} this
9377 insertAfter: function(el){
9378 el = Roo.getDom(el);
9379 el.parentNode.insertBefore(this.dom, el.nextSibling);
9384 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9385 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9386 * @return {Roo.Element} The new child
9388 insertFirst: function(el, returnDom){
9390 if(typeof el == 'object' && !el.nodeType){ // dh config
9391 return this.createChild(el, this.dom.firstChild, returnDom);
9393 el = Roo.getDom(el);
9394 this.dom.insertBefore(el, this.dom.firstChild);
9395 return !returnDom ? Roo.get(el) : el;
9400 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9401 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9402 * @param {String} where (optional) 'before' or 'after' defaults to before
9403 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9404 * @return {Roo.Element} the inserted Element
9406 insertSibling: function(el, where, returnDom){
9407 where = where ? where.toLowerCase() : 'before';
9409 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9411 if(typeof el == 'object' && !el.nodeType){ // dh config
9412 if(where == 'after' && !this.dom.nextSibling){
9413 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9415 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9419 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9420 where == 'before' ? this.dom : this.dom.nextSibling);
9429 * Creates and wraps this element with another element
9430 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9431 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9432 * @return {HTMLElement/Element} The newly created wrapper element
9434 wrap: function(config, returnDom){
9436 config = {tag: "div"};
9438 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9439 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9444 * Replaces the passed element with this element
9445 * @param {String/HTMLElement/Element} el The element to replace
9446 * @return {Roo.Element} this
9448 replace: function(el){
9450 this.insertBefore(el);
9456 * Inserts an html fragment into this element
9457 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9458 * @param {String} html The HTML fragment
9459 * @param {Boolean} returnEl True to return an Roo.Element
9460 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9462 insertHtml : function(where, html, returnEl){
9463 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9464 return returnEl ? Roo.get(el) : el;
9468 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9469 * @param {Object} o The object with the attributes
9470 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9471 * @return {Roo.Element} this
9473 set : function(o, useSet){
9475 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9477 if(attr == "style" || typeof o[attr] == "function") { continue; }
9479 el.className = o["cls"];
9482 el.setAttribute(attr, o[attr]);
9489 Roo.DomHelper.applyStyles(el, o.style);
9495 * Convenience method for constructing a KeyMap
9496 * @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:
9497 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9498 * @param {Function} fn The function to call
9499 * @param {Object} scope (optional) The scope of the function
9500 * @return {Roo.KeyMap} The KeyMap created
9502 addKeyListener : function(key, fn, scope){
9504 if(typeof key != "object" || key instanceof Array){
9520 return new Roo.KeyMap(this, config);
9524 * Creates a KeyMap for this element
9525 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9526 * @return {Roo.KeyMap} The KeyMap created
9528 addKeyMap : function(config){
9529 return new Roo.KeyMap(this, config);
9533 * Returns true if this element is scrollable.
9536 isScrollable : function(){
9538 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9542 * 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().
9543 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9544 * @param {Number} value The new scroll value
9545 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9546 * @return {Element} this
9549 scrollTo : function(side, value, animate){
9550 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9552 this.dom[prop] = value;
9554 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9555 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9561 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9562 * within this element's scrollable range.
9563 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9564 * @param {Number} distance How far to scroll the element in pixels
9565 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9566 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9567 * was scrolled as far as it could go.
9569 scroll : function(direction, distance, animate){
9570 if(!this.isScrollable()){
9574 var l = el.scrollLeft, t = el.scrollTop;
9575 var w = el.scrollWidth, h = el.scrollHeight;
9576 var cw = el.clientWidth, ch = el.clientHeight;
9577 direction = direction.toLowerCase();
9578 var scrolled = false;
9579 var a = this.preanim(arguments, 2);
9584 var v = Math.min(l + distance, w-cw);
9585 this.scrollTo("left", v, a);
9592 var v = Math.max(l - distance, 0);
9593 this.scrollTo("left", v, a);
9601 var v = Math.max(t - distance, 0);
9602 this.scrollTo("top", v, a);
9610 var v = Math.min(t + distance, h-ch);
9611 this.scrollTo("top", v, a);
9620 * Translates the passed page coordinates into left/top css values for this element
9621 * @param {Number/Array} x The page x or an array containing [x, y]
9622 * @param {Number} y The page y
9623 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9625 translatePoints : function(x, y){
9626 if(typeof x == 'object' || x instanceof Array){
9629 var p = this.getStyle('position');
9630 var o = this.getXY();
9632 var l = parseInt(this.getStyle('left'), 10);
9633 var t = parseInt(this.getStyle('top'), 10);
9636 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9639 t = (p == "relative") ? 0 : this.dom.offsetTop;
9642 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9646 * Returns the current scroll position of the element.
9647 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9649 getScroll : function(){
9650 var d = this.dom, doc = document;
9651 if(d == doc || d == doc.body){
9652 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9653 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9654 return {left: l, top: t};
9656 return {left: d.scrollLeft, top: d.scrollTop};
9661 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9662 * are convert to standard 6 digit hex color.
9663 * @param {String} attr The css attribute
9664 * @param {String} defaultValue The default value to use when a valid color isn't found
9665 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9668 getColor : function(attr, defaultValue, prefix){
9669 var v = this.getStyle(attr);
9670 if(!v || v == "transparent" || v == "inherit") {
9671 return defaultValue;
9673 var color = typeof prefix == "undefined" ? "#" : prefix;
9674 if(v.substr(0, 4) == "rgb("){
9675 var rvs = v.slice(4, v.length -1).split(",");
9676 for(var i = 0; i < 3; i++){
9677 var h = parseInt(rvs[i]).toString(16);
9684 if(v.substr(0, 1) == "#"){
9686 for(var i = 1; i < 4; i++){
9687 var c = v.charAt(i);
9690 }else if(v.length == 7){
9691 color += v.substr(1);
9695 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9699 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9700 * gradient background, rounded corners and a 4-way shadow.
9701 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9702 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9703 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9704 * @return {Roo.Element} this
9706 boxWrap : function(cls){
9707 cls = cls || 'x-box';
9708 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9709 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9714 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9715 * @param {String} namespace The namespace in which to look for the attribute
9716 * @param {String} name The attribute name
9717 * @return {String} The attribute value
9719 getAttributeNS : Roo.isIE ? function(ns, name){
9721 var type = typeof d[ns+":"+name];
9722 if(type != 'undefined' && type != 'unknown'){
9723 return d[ns+":"+name];
9726 } : function(ns, name){
9728 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9733 * Sets or Returns the value the dom attribute value
9734 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9735 * @param {String} value (optional) The value to set the attribute to
9736 * @return {String} The attribute value
9738 attr : function(name){
9739 if (arguments.length > 1) {
9740 this.dom.setAttribute(name, arguments[1]);
9741 return arguments[1];
9743 if (typeof(name) == 'object') {
9744 for(var i in name) {
9745 this.attr(i, name[i]);
9751 if (!this.dom.hasAttribute(name)) {
9754 return this.dom.getAttribute(name);
9761 var ep = El.prototype;
9764 * Appends an event handler (Shorthand for addListener)
9765 * @param {String} eventName The type of event to append
9766 * @param {Function} fn The method the event invokes
9767 * @param {Object} scope (optional) The scope (this object) of the fn
9768 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9771 ep.on = ep.addListener;
9773 ep.mon = ep.addListener;
9776 * Removes an event handler from this element (shorthand for removeListener)
9777 * @param {String} eventName the type of event to remove
9778 * @param {Function} fn the method the event invokes
9779 * @return {Roo.Element} this
9782 ep.un = ep.removeListener;
9785 * true to automatically adjust width and height settings for box-model issues (default to true)
9787 ep.autoBoxAdjust = true;
9790 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9793 El.addUnits = function(v, defaultUnit){
9794 if(v === "" || v == "auto"){
9797 if(v === undefined){
9800 if(typeof v == "number" || !El.unitPattern.test(v)){
9801 return v + (defaultUnit || 'px');
9806 // special markup used throughout Roo when box wrapping elements
9807 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>';
9809 * Visibility mode constant - Use visibility to hide element
9815 * Visibility mode constant - Use display to hide element
9821 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9822 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9823 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9835 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9836 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9837 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9838 * @return {Element} The Element object
9841 El.get = function(el){
9843 if(!el){ return null; }
9844 if(typeof el == "string"){ // element id
9845 if(!(elm = document.getElementById(el))){
9848 if(ex = El.cache[el]){
9851 ex = El.cache[el] = new El(elm);
9854 }else if(el.tagName){ // dom element
9858 if(ex = El.cache[id]){
9861 ex = El.cache[id] = new El(el);
9864 }else if(el instanceof El){
9866 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9867 // catch case where it hasn't been appended
9868 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9871 }else if(el.isComposite){
9873 }else if(el instanceof Array){
9874 return El.select(el);
9875 }else if(el == document){
9876 // create a bogus element object representing the document object
9878 var f = function(){};
9879 f.prototype = El.prototype;
9881 docEl.dom = document;
9889 El.uncache = function(el){
9890 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9892 delete El.cache[a[i].id || a[i]];
9898 // Garbage collection - uncache elements/purge listeners on orphaned elements
9899 // so we don't hold a reference and cause the browser to retain them
9900 El.garbageCollect = function(){
9901 if(!Roo.enableGarbageCollector){
9902 clearInterval(El.collectorThread);
9905 for(var eid in El.cache){
9906 var el = El.cache[eid], d = el.dom;
9907 // -------------------------------------------------------
9908 // Determining what is garbage:
9909 // -------------------------------------------------------
9911 // dom node is null, definitely garbage
9912 // -------------------------------------------------------
9914 // no parentNode == direct orphan, definitely garbage
9915 // -------------------------------------------------------
9916 // !d.offsetParent && !document.getElementById(eid)
9917 // display none elements have no offsetParent so we will
9918 // also try to look it up by it's id. However, check
9919 // offsetParent first so we don't do unneeded lookups.
9920 // This enables collection of elements that are not orphans
9921 // directly, but somewhere up the line they have an orphan
9923 // -------------------------------------------------------
9924 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9925 delete El.cache[eid];
9926 if(d && Roo.enableListenerCollection){
9932 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9936 El.Flyweight = function(dom){
9939 El.Flyweight.prototype = El.prototype;
9941 El._flyweights = {};
9943 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9944 * the dom node can be overwritten by other code.
9945 * @param {String/HTMLElement} el The dom node or id
9946 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9947 * prevent conflicts (e.g. internally Roo uses "_internal")
9949 * @return {Element} The shared Element object
9951 El.fly = function(el, named){
9952 named = named || '_global';
9953 el = Roo.getDom(el);
9957 if(!El._flyweights[named]){
9958 El._flyweights[named] = new El.Flyweight();
9960 El._flyweights[named].dom = el;
9961 return El._flyweights[named];
9965 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9966 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9967 * Shorthand of {@link Roo.Element#get}
9968 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9969 * @return {Element} The Element object
9975 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9976 * the dom node can be overwritten by other code.
9977 * Shorthand of {@link Roo.Element#fly}
9978 * @param {String/HTMLElement} el The dom node or id
9979 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9980 * prevent conflicts (e.g. internally Roo uses "_internal")
9982 * @return {Element} The shared Element object
9988 // speedy lookup for elements never to box adjust
9989 var noBoxAdjust = Roo.isStrict ? {
9992 input:1, select:1, textarea:1
9994 if(Roo.isIE || Roo.isGecko){
9995 noBoxAdjust['button'] = 1;
9999 Roo.EventManager.on(window, 'unload', function(){
10001 delete El._flyweights;
10009 Roo.Element.selectorFunction = Roo.DomQuery.select;
10012 Roo.Element.select = function(selector, unique, root){
10014 if(typeof selector == "string"){
10015 els = Roo.Element.selectorFunction(selector, root);
10016 }else if(selector.length !== undefined){
10019 throw "Invalid selector";
10021 if(unique === true){
10022 return new Roo.CompositeElement(els);
10024 return new Roo.CompositeElementLite(els);
10028 * Selects elements based on the passed CSS selector to enable working on them as 1.
10029 * @param {String/Array} selector The CSS selector or an array of elements
10030 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
10031 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
10032 * @return {CompositeElementLite/CompositeElement}
10036 Roo.select = Roo.Element.select;
10053 * Ext JS Library 1.1.1
10054 * Copyright(c) 2006-2007, Ext JS, LLC.
10056 * Originally Released Under LGPL - original licence link has changed is not relivant.
10059 * <script type="text/javascript">
10064 //Notifies Element that fx methods are available
10065 Roo.enableFx = true;
10069 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
10070 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
10071 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
10072 * Element effects to work.</p><br/>
10074 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
10075 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
10076 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
10077 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
10078 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
10079 * expected results and should be done with care.</p><br/>
10081 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
10082 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
10085 ----- -----------------------------
10086 tl The top left corner
10087 t The center of the top edge
10088 tr The top right corner
10089 l The center of the left edge
10090 r The center of the right edge
10091 bl The bottom left corner
10092 b The center of the bottom edge
10093 br The bottom right corner
10095 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
10096 * below are common options that can be passed to any Fx method.</b>
10097 * @cfg {Function} callback A function called when the effect is finished
10098 * @cfg {Object} scope The scope of the effect function
10099 * @cfg {String} easing A valid Easing value for the effect
10100 * @cfg {String} afterCls A css class to apply after the effect
10101 * @cfg {Number} duration The length of time (in seconds) that the effect should last
10102 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
10103 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
10104 * effects that end with the element being visually hidden, ignored otherwise)
10105 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
10106 * a function which returns such a specification that will be applied to the Element after the effect finishes
10107 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
10108 * @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
10109 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10113 * Slides the element into view. An anchor point can be optionally passed to set the point of
10114 * origin for the slide effect. This function automatically handles wrapping the element with
10115 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10118 // default: slide the element in from the top
10121 // custom: slide the element in from the right with a 2-second duration
10122 el.slideIn('r', { duration: 2 });
10124 // common config options shown with default values
10130 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10131 * @param {Object} options (optional) Object literal with any of the Fx config options
10132 * @return {Roo.Element} The Element
10134 slideIn : function(anchor, o){
10135 var el = this.getFxEl();
10138 el.queueFx(o, function(){
10140 anchor = anchor || "t";
10142 // fix display to visibility
10145 // restore values after effect
10146 var r = this.getFxRestore();
10147 var b = this.getBox();
10148 // fixed size for slide
10152 var wrap = this.fxWrap(r.pos, o, "hidden");
10154 var st = this.dom.style;
10155 st.visibility = "visible";
10156 st.position = "absolute";
10158 // clear out temp styles after slide and unwrap
10159 var after = function(){
10160 el.fxUnwrap(wrap, r.pos, o);
10161 st.width = r.width;
10162 st.height = r.height;
10165 // time to calc the positions
10166 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10168 switch(anchor.toLowerCase()){
10170 wrap.setSize(b.width, 0);
10171 st.left = st.bottom = "0";
10175 wrap.setSize(0, b.height);
10176 st.right = st.top = "0";
10180 wrap.setSize(0, b.height);
10181 wrap.setX(b.right);
10182 st.left = st.top = "0";
10183 a = {width: bw, points: pt};
10186 wrap.setSize(b.width, 0);
10187 wrap.setY(b.bottom);
10188 st.left = st.top = "0";
10189 a = {height: bh, points: pt};
10192 wrap.setSize(0, 0);
10193 st.right = st.bottom = "0";
10194 a = {width: bw, height: bh};
10197 wrap.setSize(0, 0);
10198 wrap.setY(b.y+b.height);
10199 st.right = st.top = "0";
10200 a = {width: bw, height: bh, points: pt};
10203 wrap.setSize(0, 0);
10204 wrap.setXY([b.right, b.bottom]);
10205 st.left = st.top = "0";
10206 a = {width: bw, height: bh, points: pt};
10209 wrap.setSize(0, 0);
10210 wrap.setX(b.x+b.width);
10211 st.left = st.bottom = "0";
10212 a = {width: bw, height: bh, points: pt};
10215 this.dom.style.visibility = "visible";
10218 arguments.callee.anim = wrap.fxanim(a,
10228 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10229 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10230 * 'hidden') but block elements will still take up space in the document. The element must be removed
10231 * from the DOM using the 'remove' config option if desired. This function automatically handles
10232 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10235 // default: slide the element out to the top
10238 // custom: slide the element out to the right with a 2-second duration
10239 el.slideOut('r', { duration: 2 });
10241 // common config options shown with default values
10249 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10250 * @param {Object} options (optional) Object literal with any of the Fx config options
10251 * @return {Roo.Element} The Element
10253 slideOut : function(anchor, o){
10254 var el = this.getFxEl();
10257 el.queueFx(o, function(){
10259 anchor = anchor || "t";
10261 // restore values after effect
10262 var r = this.getFxRestore();
10264 var b = this.getBox();
10265 // fixed size for slide
10269 var wrap = this.fxWrap(r.pos, o, "visible");
10271 var st = this.dom.style;
10272 st.visibility = "visible";
10273 st.position = "absolute";
10277 var after = function(){
10279 el.setDisplayed(false);
10284 el.fxUnwrap(wrap, r.pos, o);
10286 st.width = r.width;
10287 st.height = r.height;
10292 var a, zero = {to: 0};
10293 switch(anchor.toLowerCase()){
10295 st.left = st.bottom = "0";
10296 a = {height: zero};
10299 st.right = st.top = "0";
10303 st.left = st.top = "0";
10304 a = {width: zero, points: {to:[b.right, b.y]}};
10307 st.left = st.top = "0";
10308 a = {height: zero, points: {to:[b.x, b.bottom]}};
10311 st.right = st.bottom = "0";
10312 a = {width: zero, height: zero};
10315 st.right = st.top = "0";
10316 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10319 st.left = st.top = "0";
10320 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10323 st.left = st.bottom = "0";
10324 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10328 arguments.callee.anim = wrap.fxanim(a,
10338 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10339 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10340 * The element must be removed from the DOM using the 'remove' config option if desired.
10346 // common config options shown with default values
10354 * @param {Object} options (optional) Object literal with any of the Fx config options
10355 * @return {Roo.Element} The Element
10357 puff : function(o){
10358 var el = this.getFxEl();
10361 el.queueFx(o, function(){
10362 this.clearOpacity();
10365 // restore values after effect
10366 var r = this.getFxRestore();
10367 var st = this.dom.style;
10369 var after = function(){
10371 el.setDisplayed(false);
10378 el.setPositioning(r.pos);
10379 st.width = r.width;
10380 st.height = r.height;
10385 var width = this.getWidth();
10386 var height = this.getHeight();
10388 arguments.callee.anim = this.fxanim({
10389 width : {to: this.adjustWidth(width * 2)},
10390 height : {to: this.adjustHeight(height * 2)},
10391 points : {by: [-(width * .5), -(height * .5)]},
10393 fontSize: {to:200, unit: "%"}
10404 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10405 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10406 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10412 // all config options shown with default values
10420 * @param {Object} options (optional) Object literal with any of the Fx config options
10421 * @return {Roo.Element} The Element
10423 switchOff : function(o){
10424 var el = this.getFxEl();
10427 el.queueFx(o, function(){
10428 this.clearOpacity();
10431 // restore values after effect
10432 var r = this.getFxRestore();
10433 var st = this.dom.style;
10435 var after = function(){
10437 el.setDisplayed(false);
10443 el.setPositioning(r.pos);
10444 st.width = r.width;
10445 st.height = r.height;
10450 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10451 this.clearOpacity();
10455 points:{by:[0, this.getHeight() * .5]}
10456 }, o, 'motion', 0.3, 'easeIn', after);
10457 }).defer(100, this);
10464 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10465 * changed using the "attr" config option) and then fading back to the original color. If no original
10466 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10469 // default: highlight background to yellow
10472 // custom: highlight foreground text to blue for 2 seconds
10473 el.highlight("0000ff", { attr: 'color', duration: 2 });
10475 // common config options shown with default values
10476 el.highlight("ffff9c", {
10477 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10478 endColor: (current color) or "ffffff",
10483 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10484 * @param {Object} options (optional) Object literal with any of the Fx config options
10485 * @return {Roo.Element} The Element
10487 highlight : function(color, o){
10488 var el = this.getFxEl();
10491 el.queueFx(o, function(){
10492 color = color || "ffff9c";
10493 attr = o.attr || "backgroundColor";
10495 this.clearOpacity();
10498 var origColor = this.getColor(attr);
10499 var restoreColor = this.dom.style[attr];
10500 endColor = (o.endColor || origColor) || "ffffff";
10502 var after = function(){
10503 el.dom.style[attr] = restoreColor;
10508 a[attr] = {from: color, to: endColor};
10509 arguments.callee.anim = this.fxanim(a,
10519 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10522 // default: a single light blue ripple
10525 // custom: 3 red ripples lasting 3 seconds total
10526 el.frame("ff0000", 3, { duration: 3 });
10528 // common config options shown with default values
10529 el.frame("C3DAF9", 1, {
10530 duration: 1 //duration of entire animation (not each individual ripple)
10531 // Note: Easing is not configurable and will be ignored if included
10534 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10535 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10536 * @param {Object} options (optional) Object literal with any of the Fx config options
10537 * @return {Roo.Element} The Element
10539 frame : function(color, count, o){
10540 var el = this.getFxEl();
10543 el.queueFx(o, function(){
10544 color = color || "#C3DAF9";
10545 if(color.length == 6){
10546 color = "#" + color;
10548 count = count || 1;
10549 duration = o.duration || 1;
10552 var b = this.getBox();
10553 var animFn = function(){
10554 var proxy = this.createProxy({
10557 visbility:"hidden",
10558 position:"absolute",
10559 "z-index":"35000", // yee haw
10560 border:"0px solid " + color
10563 var scale = Roo.isBorderBox ? 2 : 1;
10565 top:{from:b.y, to:b.y - 20},
10566 left:{from:b.x, to:b.x - 20},
10567 borderWidth:{from:0, to:10},
10568 opacity:{from:1, to:0},
10569 height:{from:b.height, to:(b.height + (20*scale))},
10570 width:{from:b.width, to:(b.width + (20*scale))}
10571 }, duration, function(){
10575 animFn.defer((duration/2)*1000, this);
10586 * Creates a pause before any subsequent queued effects begin. If there are
10587 * no effects queued after the pause it will have no effect.
10592 * @param {Number} seconds The length of time to pause (in seconds)
10593 * @return {Roo.Element} The Element
10595 pause : function(seconds){
10596 var el = this.getFxEl();
10599 el.queueFx(o, function(){
10600 setTimeout(function(){
10602 }, seconds * 1000);
10608 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10609 * using the "endOpacity" config option.
10612 // default: fade in from opacity 0 to 100%
10615 // custom: fade in from opacity 0 to 75% over 2 seconds
10616 el.fadeIn({ endOpacity: .75, duration: 2});
10618 // common config options shown with default values
10620 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10625 * @param {Object} options (optional) Object literal with any of the Fx config options
10626 * @return {Roo.Element} The Element
10628 fadeIn : function(o){
10629 var el = this.getFxEl();
10631 el.queueFx(o, function(){
10632 this.setOpacity(0);
10634 this.dom.style.visibility = 'visible';
10635 var to = o.endOpacity || 1;
10636 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10637 o, null, .5, "easeOut", function(){
10639 this.clearOpacity();
10648 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10649 * using the "endOpacity" config option.
10652 // default: fade out from the element's current opacity to 0
10655 // custom: fade out from the element's current opacity to 25% over 2 seconds
10656 el.fadeOut({ endOpacity: .25, duration: 2});
10658 // common config options shown with default values
10660 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10667 * @param {Object} options (optional) Object literal with any of the Fx config options
10668 * @return {Roo.Element} The Element
10670 fadeOut : function(o){
10671 var el = this.getFxEl();
10673 el.queueFx(o, function(){
10674 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10675 o, null, .5, "easeOut", function(){
10676 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10677 this.dom.style.display = "none";
10679 this.dom.style.visibility = "hidden";
10681 this.clearOpacity();
10689 * Animates the transition of an element's dimensions from a starting height/width
10690 * to an ending height/width.
10693 // change height and width to 100x100 pixels
10694 el.scale(100, 100);
10696 // common config options shown with default values. The height and width will default to
10697 // the element's existing values if passed as null.
10700 [element's height], {
10705 * @param {Number} width The new width (pass undefined to keep the original width)
10706 * @param {Number} height The new height (pass undefined to keep the original height)
10707 * @param {Object} options (optional) Object literal with any of the Fx config options
10708 * @return {Roo.Element} The Element
10710 scale : function(w, h, o){
10711 this.shift(Roo.apply({}, o, {
10719 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10720 * Any of these properties not specified in the config object will not be changed. This effect
10721 * requires that at least one new dimension, position or opacity setting must be passed in on
10722 * the config object in order for the function to have any effect.
10725 // slide the element horizontally to x position 200 while changing the height and opacity
10726 el.shift({ x: 200, height: 50, opacity: .8 });
10728 // common config options shown with default values.
10730 width: [element's width],
10731 height: [element's height],
10732 x: [element's x position],
10733 y: [element's y position],
10734 opacity: [element's opacity],
10739 * @param {Object} options Object literal with any of the Fx config options
10740 * @return {Roo.Element} The Element
10742 shift : function(o){
10743 var el = this.getFxEl();
10745 el.queueFx(o, function(){
10746 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10747 if(w !== undefined){
10748 a.width = {to: this.adjustWidth(w)};
10750 if(h !== undefined){
10751 a.height = {to: this.adjustHeight(h)};
10753 if(x !== undefined || y !== undefined){
10755 x !== undefined ? x : this.getX(),
10756 y !== undefined ? y : this.getY()
10759 if(op !== undefined){
10760 a.opacity = {to: op};
10762 if(o.xy !== undefined){
10763 a.points = {to: o.xy};
10765 arguments.callee.anim = this.fxanim(a,
10766 o, 'motion', .35, "easeOut", function(){
10774 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10775 * ending point of the effect.
10778 // default: slide the element downward while fading out
10781 // custom: slide the element out to the right with a 2-second duration
10782 el.ghost('r', { duration: 2 });
10784 // common config options shown with default values
10792 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10793 * @param {Object} options (optional) Object literal with any of the Fx config options
10794 * @return {Roo.Element} The Element
10796 ghost : function(anchor, o){
10797 var el = this.getFxEl();
10800 el.queueFx(o, function(){
10801 anchor = anchor || "b";
10803 // restore values after effect
10804 var r = this.getFxRestore();
10805 var w = this.getWidth(),
10806 h = this.getHeight();
10808 var st = this.dom.style;
10810 var after = function(){
10812 el.setDisplayed(false);
10818 el.setPositioning(r.pos);
10819 st.width = r.width;
10820 st.height = r.height;
10825 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10826 switch(anchor.toLowerCase()){
10853 arguments.callee.anim = this.fxanim(a,
10863 * Ensures that all effects queued after syncFx is called on the element are
10864 * run concurrently. This is the opposite of {@link #sequenceFx}.
10865 * @return {Roo.Element} The Element
10867 syncFx : function(){
10868 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10877 * Ensures that all effects queued after sequenceFx is called on the element are
10878 * run in sequence. This is the opposite of {@link #syncFx}.
10879 * @return {Roo.Element} The Element
10881 sequenceFx : function(){
10882 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10884 concurrent : false,
10891 nextFx : function(){
10892 var ef = this.fxQueue[0];
10899 * Returns true if the element has any effects actively running or queued, else returns false.
10900 * @return {Boolean} True if element has active effects, else false
10902 hasActiveFx : function(){
10903 return this.fxQueue && this.fxQueue[0];
10907 * Stops any running effects and clears the element's internal effects queue if it contains
10908 * any additional effects that haven't started yet.
10909 * @return {Roo.Element} The Element
10911 stopFx : function(){
10912 if(this.hasActiveFx()){
10913 var cur = this.fxQueue[0];
10914 if(cur && cur.anim && cur.anim.isAnimated()){
10915 this.fxQueue = [cur]; // clear out others
10916 cur.anim.stop(true);
10923 beforeFx : function(o){
10924 if(this.hasActiveFx() && !o.concurrent){
10935 * Returns true if the element is currently blocking so that no other effect can be queued
10936 * until this effect is finished, else returns false if blocking is not set. This is commonly
10937 * used to ensure that an effect initiated by a user action runs to completion prior to the
10938 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10939 * @return {Boolean} True if blocking, else false
10941 hasFxBlock : function(){
10942 var q = this.fxQueue;
10943 return q && q[0] && q[0].block;
10947 queueFx : function(o, fn){
10951 if(!this.hasFxBlock()){
10952 Roo.applyIf(o, this.fxDefaults);
10954 var run = this.beforeFx(o);
10955 fn.block = o.block;
10956 this.fxQueue.push(fn);
10968 fxWrap : function(pos, o, vis){
10970 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10973 wrapXY = this.getXY();
10975 var div = document.createElement("div");
10976 div.style.visibility = vis;
10977 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10978 wrap.setPositioning(pos);
10979 if(wrap.getStyle("position") == "static"){
10980 wrap.position("relative");
10982 this.clearPositioning('auto');
10984 wrap.dom.appendChild(this.dom);
10986 wrap.setXY(wrapXY);
10993 fxUnwrap : function(wrap, pos, o){
10994 this.clearPositioning();
10995 this.setPositioning(pos);
10997 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
11003 getFxRestore : function(){
11004 var st = this.dom.style;
11005 return {pos: this.getPositioning(), width: st.width, height : st.height};
11009 afterFx : function(o){
11011 this.applyStyles(o.afterStyle);
11014 this.addClass(o.afterCls);
11016 if(o.remove === true){
11019 Roo.callback(o.callback, o.scope, [this]);
11021 this.fxQueue.shift();
11027 getFxEl : function(){ // support for composite element fx
11028 return Roo.get(this.dom);
11032 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
11033 animType = animType || 'run';
11035 var anim = Roo.lib.Anim[animType](
11037 (opt.duration || defaultDur) || .35,
11038 (opt.easing || defaultEase) || 'easeOut',
11040 Roo.callback(cb, this);
11049 // backwords compat
11050 Roo.Fx.resize = Roo.Fx.scale;
11052 //When included, Roo.Fx is automatically applied to Element so that all basic
11053 //effects are available directly via the Element API
11054 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
11056 * Ext JS Library 1.1.1
11057 * Copyright(c) 2006-2007, Ext JS, LLC.
11059 * Originally Released Under LGPL - original licence link has changed is not relivant.
11062 * <script type="text/javascript">
11067 * @class Roo.CompositeElement
11068 * Standard composite class. Creates a Roo.Element for every element in the collection.
11070 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11071 * actions will be performed on all the elements in this collection.</b>
11073 * All methods return <i>this</i> and can be chained.
11075 var els = Roo.select("#some-el div.some-class", true);
11076 // or select directly from an existing element
11077 var el = Roo.get('some-el');
11078 el.select('div.some-class', true);
11080 els.setWidth(100); // all elements become 100 width
11081 els.hide(true); // all elements fade out and hide
11083 els.setWidth(100).hide(true);
11086 Roo.CompositeElement = function(els){
11087 this.elements = [];
11088 this.addElements(els);
11090 Roo.CompositeElement.prototype = {
11092 addElements : function(els){
11096 if(typeof els == "string"){
11097 els = Roo.Element.selectorFunction(els);
11099 var yels = this.elements;
11100 var index = yels.length-1;
11101 for(var i = 0, len = els.length; i < len; i++) {
11102 yels[++index] = Roo.get(els[i]);
11108 * Clears this composite and adds the elements returned by the passed selector.
11109 * @param {String/Array} els A string CSS selector, an array of elements or an element
11110 * @return {CompositeElement} this
11112 fill : function(els){
11113 this.elements = [];
11119 * Filters this composite to only elements that match the passed selector.
11120 * @param {String} selector A string CSS selector
11121 * @param {Boolean} inverse return inverse filter (not matches)
11122 * @return {CompositeElement} this
11124 filter : function(selector, inverse){
11126 inverse = inverse || false;
11127 this.each(function(el){
11128 var match = inverse ? !el.is(selector) : el.is(selector);
11130 els[els.length] = el.dom;
11137 invoke : function(fn, args){
11138 var els = this.elements;
11139 for(var i = 0, len = els.length; i < len; i++) {
11140 Roo.Element.prototype[fn].apply(els[i], args);
11145 * Adds elements to this composite.
11146 * @param {String/Array} els A string CSS selector, an array of elements or an element
11147 * @return {CompositeElement} this
11149 add : function(els){
11150 if(typeof els == "string"){
11151 this.addElements(Roo.Element.selectorFunction(els));
11152 }else if(els.length !== undefined){
11153 this.addElements(els);
11155 this.addElements([els]);
11160 * Calls the passed function passing (el, this, index) for each element in this composite.
11161 * @param {Function} fn The function to call
11162 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11163 * @return {CompositeElement} this
11165 each : function(fn, scope){
11166 var els = this.elements;
11167 for(var i = 0, len = els.length; i < len; i++){
11168 if(fn.call(scope || els[i], els[i], this, i) === false) {
11176 * Returns the Element object at the specified index
11177 * @param {Number} index
11178 * @return {Roo.Element}
11180 item : function(index){
11181 return this.elements[index] || null;
11185 * Returns the first Element
11186 * @return {Roo.Element}
11188 first : function(){
11189 return this.item(0);
11193 * Returns the last Element
11194 * @return {Roo.Element}
11197 return this.item(this.elements.length-1);
11201 * Returns the number of elements in this composite
11204 getCount : function(){
11205 return this.elements.length;
11209 * Returns true if this composite contains the passed element
11212 contains : function(el){
11213 return this.indexOf(el) !== -1;
11217 * Returns true if this composite contains the passed element
11220 indexOf : function(el){
11221 return this.elements.indexOf(Roo.get(el));
11226 * Removes the specified element(s).
11227 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11228 * or an array of any of those.
11229 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11230 * @return {CompositeElement} this
11232 removeElement : function(el, removeDom){
11233 if(el instanceof Array){
11234 for(var i = 0, len = el.length; i < len; i++){
11235 this.removeElement(el[i]);
11239 var index = typeof el == 'number' ? el : this.indexOf(el);
11242 var d = this.elements[index];
11246 d.parentNode.removeChild(d);
11249 this.elements.splice(index, 1);
11255 * Replaces the specified element with the passed element.
11256 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11258 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11259 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11260 * @return {CompositeElement} this
11262 replaceElement : function(el, replacement, domReplace){
11263 var index = typeof el == 'number' ? el : this.indexOf(el);
11266 this.elements[index].replaceWith(replacement);
11268 this.elements.splice(index, 1, Roo.get(replacement))
11275 * Removes all elements.
11277 clear : function(){
11278 this.elements = [];
11282 Roo.CompositeElement.createCall = function(proto, fnName){
11283 if(!proto[fnName]){
11284 proto[fnName] = function(){
11285 return this.invoke(fnName, arguments);
11289 for(var fnName in Roo.Element.prototype){
11290 if(typeof Roo.Element.prototype[fnName] == "function"){
11291 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11297 * Ext JS Library 1.1.1
11298 * Copyright(c) 2006-2007, Ext JS, LLC.
11300 * Originally Released Under LGPL - original licence link has changed is not relivant.
11303 * <script type="text/javascript">
11307 * @class Roo.CompositeElementLite
11308 * @extends Roo.CompositeElement
11309 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11311 var els = Roo.select("#some-el div.some-class");
11312 // or select directly from an existing element
11313 var el = Roo.get('some-el');
11314 el.select('div.some-class');
11316 els.setWidth(100); // all elements become 100 width
11317 els.hide(true); // all elements fade out and hide
11319 els.setWidth(100).hide(true);
11320 </code></pre><br><br>
11321 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11322 * actions will be performed on all the elements in this collection.</b>
11324 Roo.CompositeElementLite = function(els){
11325 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11326 this.el = new Roo.Element.Flyweight();
11328 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11329 addElements : function(els){
11331 if(els instanceof Array){
11332 this.elements = this.elements.concat(els);
11334 var yels = this.elements;
11335 var index = yels.length-1;
11336 for(var i = 0, len = els.length; i < len; i++) {
11337 yels[++index] = els[i];
11343 invoke : function(fn, args){
11344 var els = this.elements;
11346 for(var i = 0, len = els.length; i < len; i++) {
11348 Roo.Element.prototype[fn].apply(el, args);
11353 * Returns a flyweight Element of the dom element object at the specified index
11354 * @param {Number} index
11355 * @return {Roo.Element}
11357 item : function(index){
11358 if(!this.elements[index]){
11361 this.el.dom = this.elements[index];
11365 // fixes scope with flyweight
11366 addListener : function(eventName, handler, scope, opt){
11367 var els = this.elements;
11368 for(var i = 0, len = els.length; i < len; i++) {
11369 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11375 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11376 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11377 * a reference to the dom node, use el.dom.</b>
11378 * @param {Function} fn The function to call
11379 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11380 * @return {CompositeElement} this
11382 each : function(fn, scope){
11383 var els = this.elements;
11385 for(var i = 0, len = els.length; i < len; i++){
11387 if(fn.call(scope || el, el, this, i) === false){
11394 indexOf : function(el){
11395 return this.elements.indexOf(Roo.getDom(el));
11398 replaceElement : function(el, replacement, domReplace){
11399 var index = typeof el == 'number' ? el : this.indexOf(el);
11401 replacement = Roo.getDom(replacement);
11403 var d = this.elements[index];
11404 d.parentNode.insertBefore(replacement, d);
11405 d.parentNode.removeChild(d);
11407 this.elements.splice(index, 1, replacement);
11412 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11416 * Ext JS Library 1.1.1
11417 * Copyright(c) 2006-2007, Ext JS, LLC.
11419 * Originally Released Under LGPL - original licence link has changed is not relivant.
11422 * <script type="text/javascript">
11428 * @class Roo.data.Connection
11429 * @extends Roo.util.Observable
11430 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11431 * either to a configured URL, or to a URL specified at request time.<br><br>
11433 * Requests made by this class are asynchronous, and will return immediately. No data from
11434 * the server will be available to the statement immediately following the {@link #request} call.
11435 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11437 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11438 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11439 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11440 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11441 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11442 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11443 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11444 * standard DOM methods.
11446 * @param {Object} config a configuration object.
11448 Roo.data.Connection = function(config){
11449 Roo.apply(this, config);
11452 * @event beforerequest
11453 * Fires before a network request is made to retrieve a data object.
11454 * @param {Connection} conn This Connection object.
11455 * @param {Object} options The options config object passed to the {@link #request} method.
11457 "beforerequest" : true,
11459 * @event requestcomplete
11460 * Fires if the request was successfully completed.
11461 * @param {Connection} conn This Connection object.
11462 * @param {Object} response The XHR object containing the response data.
11463 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11464 * @param {Object} options The options config object passed to the {@link #request} method.
11466 "requestcomplete" : true,
11468 * @event requestexception
11469 * Fires if an error HTTP status was returned from the server.
11470 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11471 * @param {Connection} conn This Connection object.
11472 * @param {Object} response The XHR object containing the response data.
11473 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11474 * @param {Object} options The options config object passed to the {@link #request} method.
11476 "requestexception" : true
11478 Roo.data.Connection.superclass.constructor.call(this);
11481 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11483 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11486 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11487 * extra parameters to each request made by this object. (defaults to undefined)
11490 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11491 * to each request made by this object. (defaults to undefined)
11494 * @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)
11497 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11501 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11507 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11510 disableCaching: true,
11513 * Sends an HTTP request to a remote server.
11514 * @param {Object} options An object which may contain the following properties:<ul>
11515 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11516 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11517 * request, a url encoded string or a function to call to get either.</li>
11518 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11519 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11520 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11521 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11522 * <li>options {Object} The parameter to the request call.</li>
11523 * <li>success {Boolean} True if the request succeeded.</li>
11524 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11526 * <li><b>success</b> {Function} (Optional) The function to be called upon success 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>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11532 * The callback is passed the following parameters:<ul>
11533 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11534 * <li>options {Object} The parameter to the request call.</li>
11536 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11537 * for the callback function. Defaults to the browser window.</li>
11538 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11539 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11540 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11541 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11542 * params for the post data. Any params will be appended to the URL.</li>
11543 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11545 * @return {Number} transactionId
11547 request : function(o){
11548 if(this.fireEvent("beforerequest", this, o) !== false){
11551 if(typeof p == "function"){
11552 p = p.call(o.scope||window, o);
11554 if(typeof p == "object"){
11555 p = Roo.urlEncode(o.params);
11557 if(this.extraParams){
11558 var extras = Roo.urlEncode(this.extraParams);
11559 p = p ? (p + '&' + extras) : extras;
11562 var url = o.url || this.url;
11563 if(typeof url == 'function'){
11564 url = url.call(o.scope||window, o);
11568 var form = Roo.getDom(o.form);
11569 url = url || form.action;
11571 var enctype = form.getAttribute("enctype");
11572 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11573 return this.doFormUpload(o, p, url);
11575 var f = Roo.lib.Ajax.serializeForm(form);
11576 p = p ? (p + '&' + f) : f;
11579 var hs = o.headers;
11580 if(this.defaultHeaders){
11581 hs = Roo.apply(hs || {}, this.defaultHeaders);
11588 success: this.handleResponse,
11589 failure: this.handleFailure,
11591 argument: {options: o},
11592 timeout : o.timeout || this.timeout
11595 var method = o.method||this.method||(p ? "POST" : "GET");
11597 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11598 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11601 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11605 }else if(this.autoAbort !== false){
11609 if((method == 'GET' && p) || o.xmlData){
11610 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11613 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11614 return this.transId;
11616 Roo.callback(o.callback, o.scope, [o, null, null]);
11622 * Determine whether this object has a request outstanding.
11623 * @param {Number} transactionId (Optional) defaults to the last transaction
11624 * @return {Boolean} True if there is an outstanding request.
11626 isLoading : function(transId){
11628 return Roo.lib.Ajax.isCallInProgress(transId);
11630 return this.transId ? true : false;
11635 * Aborts any outstanding request.
11636 * @param {Number} transactionId (Optional) defaults to the last transaction
11638 abort : function(transId){
11639 if(transId || this.isLoading()){
11640 Roo.lib.Ajax.abort(transId || this.transId);
11645 handleResponse : function(response){
11646 this.transId = false;
11647 var options = response.argument.options;
11648 response.argument = options ? options.argument : null;
11649 this.fireEvent("requestcomplete", this, response, options);
11650 Roo.callback(options.success, options.scope, [response, options]);
11651 Roo.callback(options.callback, options.scope, [options, true, response]);
11655 handleFailure : function(response, e){
11656 this.transId = false;
11657 var options = response.argument.options;
11658 response.argument = options ? options.argument : null;
11659 this.fireEvent("requestexception", this, response, options, e);
11660 Roo.callback(options.failure, options.scope, [response, options]);
11661 Roo.callback(options.callback, options.scope, [options, false, response]);
11665 doFormUpload : function(o, ps, url){
11667 var frame = document.createElement('iframe');
11670 frame.className = 'x-hidden';
11672 frame.src = Roo.SSL_SECURE_URL;
11674 document.body.appendChild(frame);
11677 document.frames[id].name = id;
11680 var form = Roo.getDom(o.form);
11682 form.method = 'POST';
11683 form.enctype = form.encoding = 'multipart/form-data';
11689 if(ps){ // add dynamic params
11691 ps = Roo.urlDecode(ps, false);
11693 if(ps.hasOwnProperty(k)){
11694 hd = document.createElement('input');
11695 hd.type = 'hidden';
11698 form.appendChild(hd);
11705 var r = { // bogus response object
11710 r.argument = o ? o.argument : null;
11715 doc = frame.contentWindow.document;
11717 doc = (frame.contentDocument || window.frames[id].document);
11719 if(doc && doc.body){
11720 r.responseText = doc.body.innerHTML;
11722 if(doc && doc.XMLDocument){
11723 r.responseXML = doc.XMLDocument;
11725 r.responseXML = doc;
11732 Roo.EventManager.removeListener(frame, 'load', cb, this);
11734 this.fireEvent("requestcomplete", this, r, o);
11735 Roo.callback(o.success, o.scope, [r, o]);
11736 Roo.callback(o.callback, o.scope, [o, true, r]);
11738 setTimeout(function(){document.body.removeChild(frame);}, 100);
11741 Roo.EventManager.on(frame, 'load', cb, this);
11744 if(hiddens){ // remove dynamic params
11745 for(var i = 0, len = hiddens.length; i < len; i++){
11746 form.removeChild(hiddens[i]);
11753 * Ext JS Library 1.1.1
11754 * Copyright(c) 2006-2007, Ext JS, LLC.
11756 * Originally Released Under LGPL - original licence link has changed is not relivant.
11759 * <script type="text/javascript">
11763 * Global Ajax request class.
11766 * @extends Roo.data.Connection
11769 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11770 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11771 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11772 * @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)
11773 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11774 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11775 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11777 Roo.Ajax = new Roo.data.Connection({
11786 * Serialize the passed form into a url encoded string
11788 * @param {String/HTMLElement} form
11791 serializeForm : function(form){
11792 return Roo.lib.Ajax.serializeForm(form);
11796 * Ext JS Library 1.1.1
11797 * Copyright(c) 2006-2007, Ext JS, LLC.
11799 * Originally Released Under LGPL - original licence link has changed is not relivant.
11802 * <script type="text/javascript">
11807 * @class Roo.UpdateManager
11808 * @extends Roo.util.Observable
11809 * Provides AJAX-style update for Element object.<br><br>
11812 * // Get it from a Roo.Element object
11813 * var el = Roo.get("foo");
11814 * var mgr = el.getUpdateManager();
11815 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11817 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11819 * // or directly (returns the same UpdateManager instance)
11820 * var mgr = new Roo.UpdateManager("myElementId");
11821 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11822 * mgr.on("update", myFcnNeedsToKnow);
11824 // short handed call directly from the element object
11825 Roo.get("foo").load({
11829 text: "Loading Foo..."
11833 * Create new UpdateManager directly.
11834 * @param {String/HTMLElement/Roo.Element} el The element to update
11835 * @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).
11837 Roo.UpdateManager = function(el, forceNew){
11839 if(!forceNew && el.updateManager){
11840 return el.updateManager;
11843 * The Element object
11844 * @type Roo.Element
11848 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11851 this.defaultUrl = null;
11855 * @event beforeupdate
11856 * Fired before an update is made, return false from your handler and the update is cancelled.
11857 * @param {Roo.Element} el
11858 * @param {String/Object/Function} url
11859 * @param {String/Object} params
11861 "beforeupdate": true,
11864 * Fired after successful update is made.
11865 * @param {Roo.Element} el
11866 * @param {Object} oResponseObject The response Object
11871 * Fired on update failure.
11872 * @param {Roo.Element} el
11873 * @param {Object} oResponseObject The response Object
11877 var d = Roo.UpdateManager.defaults;
11879 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11882 this.sslBlankUrl = d.sslBlankUrl;
11884 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11887 this.disableCaching = d.disableCaching;
11889 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11892 this.indicatorText = d.indicatorText;
11894 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11897 this.showLoadIndicator = d.showLoadIndicator;
11899 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11902 this.timeout = d.timeout;
11905 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11908 this.loadScripts = d.loadScripts;
11911 * Transaction object of current executing transaction
11913 this.transaction = null;
11918 this.autoRefreshProcId = null;
11920 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11923 this.refreshDelegate = this.refresh.createDelegate(this);
11925 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11928 this.updateDelegate = this.update.createDelegate(this);
11930 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11933 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11937 this.successDelegate = this.processSuccess.createDelegate(this);
11941 this.failureDelegate = this.processFailure.createDelegate(this);
11943 if(!this.renderer){
11945 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11947 this.renderer = new Roo.UpdateManager.BasicRenderer();
11950 Roo.UpdateManager.superclass.constructor.call(this);
11953 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11955 * Get the Element this UpdateManager is bound to
11956 * @return {Roo.Element} The element
11958 getEl : function(){
11962 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11963 * @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:
11966 url: "your-url.php",<br/>
11967 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11968 callback: yourFunction,<br/>
11969 scope: yourObject, //(optional scope) <br/>
11970 discardUrl: false, <br/>
11971 nocache: false,<br/>
11972 text: "Loading...",<br/>
11974 scripts: false<br/>
11977 * The only required property is url. The optional properties nocache, text and scripts
11978 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11979 * @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}
11980 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11981 * @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.
11983 update : function(url, params, callback, discardUrl){
11984 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11985 var method = this.method,
11987 if(typeof url == "object"){ // must be config object
11990 params = params || cfg.params;
11991 callback = callback || cfg.callback;
11992 discardUrl = discardUrl || cfg.discardUrl;
11993 if(callback && cfg.scope){
11994 callback = callback.createDelegate(cfg.scope);
11996 if(typeof cfg.method != "undefined"){method = cfg.method;};
11997 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11998 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11999 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
12000 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
12002 this.showLoading();
12004 this.defaultUrl = url;
12006 if(typeof url == "function"){
12007 url = url.call(this);
12010 method = method || (params ? "POST" : "GET");
12011 if(method == "GET"){
12012 url = this.prepareUrl(url);
12015 var o = Roo.apply(cfg ||{}, {
12018 success: this.successDelegate,
12019 failure: this.failureDelegate,
12020 callback: undefined,
12021 timeout: (this.timeout*1000),
12022 argument: {"url": url, "form": null, "callback": callback, "params": params}
12024 Roo.log("updated manager called with timeout of " + o.timeout);
12025 this.transaction = Roo.Ajax.request(o);
12030 * 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.
12031 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
12032 * @param {String/HTMLElement} form The form Id or form element
12033 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
12034 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
12035 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
12037 formUpdate : function(form, url, reset, callback){
12038 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
12039 if(typeof url == "function"){
12040 url = url.call(this);
12042 form = Roo.getDom(form);
12043 this.transaction = Roo.Ajax.request({
12046 success: this.successDelegate,
12047 failure: this.failureDelegate,
12048 timeout: (this.timeout*1000),
12049 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
12051 this.showLoading.defer(1, this);
12056 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
12057 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12059 refresh : function(callback){
12060 if(this.defaultUrl == null){
12063 this.update(this.defaultUrl, null, callback, true);
12067 * Set this element to auto refresh.
12068 * @param {Number} interval How often to update (in seconds).
12069 * @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)
12070 * @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}
12071 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12072 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
12074 startAutoRefresh : function(interval, url, params, callback, refreshNow){
12076 this.update(url || this.defaultUrl, params, callback, true);
12078 if(this.autoRefreshProcId){
12079 clearInterval(this.autoRefreshProcId);
12081 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
12085 * Stop auto refresh on this element.
12087 stopAutoRefresh : function(){
12088 if(this.autoRefreshProcId){
12089 clearInterval(this.autoRefreshProcId);
12090 delete this.autoRefreshProcId;
12094 isAutoRefreshing : function(){
12095 return this.autoRefreshProcId ? true : false;
12098 * Called to update the element to "Loading" state. Override to perform custom action.
12100 showLoading : function(){
12101 if(this.showLoadIndicator){
12102 this.el.update(this.indicatorText);
12107 * Adds unique parameter to query string if disableCaching = true
12110 prepareUrl : function(url){
12111 if(this.disableCaching){
12112 var append = "_dc=" + (new Date().getTime());
12113 if(url.indexOf("?") !== -1){
12114 url += "&" + append;
12116 url += "?" + append;
12125 processSuccess : function(response){
12126 this.transaction = null;
12127 if(response.argument.form && response.argument.reset){
12128 try{ // put in try/catch since some older FF releases had problems with this
12129 response.argument.form.reset();
12132 if(this.loadScripts){
12133 this.renderer.render(this.el, response, this,
12134 this.updateComplete.createDelegate(this, [response]));
12136 this.renderer.render(this.el, response, this);
12137 this.updateComplete(response);
12141 updateComplete : function(response){
12142 this.fireEvent("update", this.el, response);
12143 if(typeof response.argument.callback == "function"){
12144 response.argument.callback(this.el, true, response);
12151 processFailure : function(response){
12152 this.transaction = null;
12153 this.fireEvent("failure", this.el, response);
12154 if(typeof response.argument.callback == "function"){
12155 response.argument.callback(this.el, false, response);
12160 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12161 * @param {Object} renderer The object implementing the render() method
12163 setRenderer : function(renderer){
12164 this.renderer = renderer;
12167 getRenderer : function(){
12168 return this.renderer;
12172 * Set the defaultUrl used for updates
12173 * @param {String/Function} defaultUrl The url or a function to call to get the url
12175 setDefaultUrl : function(defaultUrl){
12176 this.defaultUrl = defaultUrl;
12180 * Aborts the executing transaction
12182 abort : function(){
12183 if(this.transaction){
12184 Roo.Ajax.abort(this.transaction);
12189 * Returns true if an update is in progress
12190 * @return {Boolean}
12192 isUpdating : function(){
12193 if(this.transaction){
12194 return Roo.Ajax.isLoading(this.transaction);
12201 * @class Roo.UpdateManager.defaults
12202 * @static (not really - but it helps the doc tool)
12203 * The defaults collection enables customizing the default properties of UpdateManager
12205 Roo.UpdateManager.defaults = {
12207 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12213 * True to process scripts by default (Defaults to false).
12216 loadScripts : false,
12219 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12222 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12224 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12227 disableCaching : false,
12229 * Whether to show indicatorText when loading (Defaults to true).
12232 showLoadIndicator : true,
12234 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12237 indicatorText : '<div class="loading-indicator">Loading...</div>'
12241 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12243 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12244 * @param {String/HTMLElement/Roo.Element} el The element to update
12245 * @param {String} url The url
12246 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12247 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12250 * @member Roo.UpdateManager
12252 Roo.UpdateManager.updateElement = function(el, url, params, options){
12253 var um = Roo.get(el, true).getUpdateManager();
12254 Roo.apply(um, options);
12255 um.update(url, params, options ? options.callback : null);
12257 // alias for backwards compat
12258 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12260 * @class Roo.UpdateManager.BasicRenderer
12261 * Default Content renderer. Updates the elements innerHTML with the responseText.
12263 Roo.UpdateManager.BasicRenderer = function(){};
12265 Roo.UpdateManager.BasicRenderer.prototype = {
12267 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12268 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12269 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12270 * @param {Roo.Element} el The element being rendered
12271 * @param {Object} response The YUI Connect response object
12272 * @param {UpdateManager} updateManager The calling update manager
12273 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12275 render : function(el, response, updateManager, callback){
12276 el.update(response.responseText, updateManager.loadScripts, callback);
12282 * (c)) Alan Knowles
12288 * @class Roo.DomTemplate
12289 * @extends Roo.Template
12290 * An effort at a dom based template engine..
12292 * Similar to XTemplate, except it uses dom parsing to create the template..
12294 * Supported features:
12299 {a_variable} - output encoded.
12300 {a_variable.format:("Y-m-d")} - call a method on the variable
12301 {a_variable:raw} - unencoded output
12302 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12303 {a_variable:this.method_on_template(...)} - call a method on the template object.
12308 <div roo-for="a_variable or condition.."></div>
12309 <div roo-if="a_variable or condition"></div>
12310 <div roo-exec="some javascript"></div>
12311 <div roo-name="named_template"></div>
12316 Roo.DomTemplate = function()
12318 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12325 Roo.extend(Roo.DomTemplate, Roo.Template, {
12327 * id counter for sub templates.
12331 * flag to indicate if dom parser is inside a pre,
12332 * it will strip whitespace if not.
12337 * The various sub templates
12345 * basic tag replacing syntax
12348 * // you can fake an object call by doing this
12352 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12353 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12355 iterChild : function (node, method) {
12357 var oldPre = this.inPre;
12358 if (node.tagName == 'PRE') {
12361 for( var i = 0; i < node.childNodes.length; i++) {
12362 method.call(this, node.childNodes[i]);
12364 this.inPre = oldPre;
12370 * compile the template
12372 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12375 compile: function()
12379 // covert the html into DOM...
12383 doc = document.implementation.createHTMLDocument("");
12384 doc.documentElement.innerHTML = this.html ;
12385 div = doc.documentElement;
12387 // old IE... - nasty -- it causes all sorts of issues.. with
12388 // images getting pulled from server..
12389 div = document.createElement('div');
12390 div.innerHTML = this.html;
12392 //doc.documentElement.innerHTML = htmlBody
12398 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12400 var tpls = this.tpls;
12402 // create a top level template from the snippet..
12404 //Roo.log(div.innerHTML);
12411 body : div.innerHTML,
12424 Roo.each(tpls, function(tp){
12425 this.compileTpl(tp);
12426 this.tpls[tp.id] = tp;
12429 this.master = tpls[0];
12435 compileNode : function(node, istop) {
12440 // skip anything not a tag..
12441 if (node.nodeType != 1) {
12442 if (node.nodeType == 3 && !this.inPre) {
12443 // reduce white space..
12444 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12467 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12468 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12469 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12470 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12476 // just itterate children..
12477 this.iterChild(node,this.compileNode);
12480 tpl.uid = this.id++;
12481 tpl.value = node.getAttribute('roo-' + tpl.attr);
12482 node.removeAttribute('roo-'+ tpl.attr);
12483 if (tpl.attr != 'name') {
12484 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12485 node.parentNode.replaceChild(placeholder, node);
12488 var placeholder = document.createElement('span');
12489 placeholder.className = 'roo-tpl-' + tpl.value;
12490 node.parentNode.replaceChild(placeholder, node);
12493 // parent now sees '{domtplXXXX}
12494 this.iterChild(node,this.compileNode);
12496 // we should now have node body...
12497 var div = document.createElement('div');
12498 div.appendChild(node);
12500 // this has the unfortunate side effect of converting tagged attributes
12501 // eg. href="{...}" into %7C...%7D
12502 // this has been fixed by searching for those combo's although it's a bit hacky..
12505 tpl.body = div.innerHTML;
12512 switch (tpl.value) {
12513 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12514 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12515 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12520 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12524 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12528 tpl.id = tpl.value; // replace non characters???
12534 this.tpls.push(tpl);
12544 * Compile a segment of the template into a 'sub-template'
12550 compileTpl : function(tpl)
12552 var fm = Roo.util.Format;
12553 var useF = this.disableFormats !== true;
12555 var sep = Roo.isGecko ? "+\n" : ",\n";
12557 var undef = function(str) {
12558 Roo.debug && Roo.log("Property not found :" + str);
12562 //Roo.log(tpl.body);
12566 var fn = function(m, lbrace, name, format, args)
12569 //Roo.log(arguments);
12570 args = args ? args.replace(/\\'/g,"'") : args;
12571 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12572 if (typeof(format) == 'undefined') {
12573 format = 'htmlEncode';
12575 if (format == 'raw' ) {
12579 if(name.substr(0, 6) == 'domtpl'){
12580 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12583 // build an array of options to determine if value is undefined..
12585 // basically get 'xxxx.yyyy' then do
12586 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12587 // (function () { Roo.log("Property not found"); return ''; })() :
12592 Roo.each(name.split('.'), function(st) {
12593 lookfor += (lookfor.length ? '.': '') + st;
12594 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12597 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12600 if(format && useF){
12602 args = args ? ',' + args : "";
12604 if(format.substr(0, 5) != "this."){
12605 format = "fm." + format + '(';
12607 format = 'this.call("'+ format.substr(5) + '", ';
12611 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12614 if (args && args.length) {
12615 // called with xxyx.yuu:(test,test)
12617 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12619 // raw.. - :raw modifier..
12620 return "'"+ sep + udef_st + name + ")"+sep+"'";
12624 // branched to use + in gecko and [].join() in others
12626 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12627 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12630 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12631 body.push(tpl.body.replace(/(\r\n|\n)/g,
12632 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12633 body.push("'].join('');};};");
12634 body = body.join('');
12637 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12639 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12646 * same as applyTemplate, except it's done to one of the subTemplates
12647 * when using named templates, you can do:
12649 * var str = pl.applySubTemplate('your-name', values);
12652 * @param {Number} id of the template
12653 * @param {Object} values to apply to template
12654 * @param {Object} parent (normaly the instance of this object)
12656 applySubTemplate : function(id, values, parent)
12660 var t = this.tpls[id];
12664 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12665 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12669 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12676 if(t.execCall && t.execCall.call(this, values, parent)){
12680 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12686 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12687 parent = t.target ? values : parent;
12688 if(t.forCall && vs instanceof Array){
12690 for(var i = 0, len = vs.length; i < len; i++){
12692 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12694 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12696 //Roo.log(t.compiled);
12700 return buf.join('');
12703 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12708 return t.compiled.call(this, vs, parent);
12710 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12712 //Roo.log(t.compiled);
12720 applyTemplate : function(values){
12721 return this.master.compiled.call(this, values, {});
12722 //var s = this.subs;
12725 apply : function(){
12726 return this.applyTemplate.apply(this, arguments);
12731 Roo.DomTemplate.from = function(el){
12732 el = Roo.getDom(el);
12733 return new Roo.Domtemplate(el.value || el.innerHTML);
12736 * Ext JS Library 1.1.1
12737 * Copyright(c) 2006-2007, Ext JS, LLC.
12739 * Originally Released Under LGPL - original licence link has changed is not relivant.
12742 * <script type="text/javascript">
12746 * @class Roo.util.DelayedTask
12747 * Provides a convenient method of performing setTimeout where a new
12748 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12749 * You can use this class to buffer
12750 * the keypress events for a certain number of milliseconds, and perform only if they stop
12751 * for that amount of time.
12752 * @constructor The parameters to this constructor serve as defaults and are not required.
12753 * @param {Function} fn (optional) The default function to timeout
12754 * @param {Object} scope (optional) The default scope of that timeout
12755 * @param {Array} args (optional) The default Array of arguments
12757 Roo.util.DelayedTask = function(fn, scope, args){
12758 var id = null, d, t;
12760 var call = function(){
12761 var now = new Date().getTime();
12765 fn.apply(scope, args || []);
12769 * Cancels any pending timeout and queues a new one
12770 * @param {Number} delay The milliseconds to delay
12771 * @param {Function} newFn (optional) Overrides function passed to constructor
12772 * @param {Object} newScope (optional) Overrides scope passed to constructor
12773 * @param {Array} newArgs (optional) Overrides args passed to constructor
12775 this.delay = function(delay, newFn, newScope, newArgs){
12776 if(id && delay != d){
12780 t = new Date().getTime();
12782 scope = newScope || scope;
12783 args = newArgs || args;
12785 id = setInterval(call, d);
12790 * Cancel the last queued timeout
12792 this.cancel = function(){
12800 * Ext JS Library 1.1.1
12801 * Copyright(c) 2006-2007, Ext JS, LLC.
12803 * Originally Released Under LGPL - original licence link has changed is not relivant.
12806 * <script type="text/javascript">
12810 Roo.util.TaskRunner = function(interval){
12811 interval = interval || 10;
12812 var tasks = [], removeQueue = [];
12814 var running = false;
12816 var stopThread = function(){
12822 var startThread = function(){
12825 id = setInterval(runTasks, interval);
12829 var removeTask = function(task){
12830 removeQueue.push(task);
12836 var runTasks = function(){
12837 if(removeQueue.length > 0){
12838 for(var i = 0, len = removeQueue.length; i < len; i++){
12839 tasks.remove(removeQueue[i]);
12842 if(tasks.length < 1){
12847 var now = new Date().getTime();
12848 for(var i = 0, len = tasks.length; i < len; ++i){
12850 var itime = now - t.taskRunTime;
12851 if(t.interval <= itime){
12852 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12853 t.taskRunTime = now;
12854 if(rt === false || t.taskRunCount === t.repeat){
12859 if(t.duration && t.duration <= (now - t.taskStartTime)){
12866 * Queues a new task.
12867 * @param {Object} task
12869 this.start = function(task){
12871 task.taskStartTime = new Date().getTime();
12872 task.taskRunTime = 0;
12873 task.taskRunCount = 0;
12878 this.stop = function(task){
12883 this.stopAll = function(){
12885 for(var i = 0, len = tasks.length; i < len; i++){
12886 if(tasks[i].onStop){
12895 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12897 * Ext JS Library 1.1.1
12898 * Copyright(c) 2006-2007, Ext JS, LLC.
12900 * Originally Released Under LGPL - original licence link has changed is not relivant.
12903 * <script type="text/javascript">
12908 * @class Roo.util.MixedCollection
12909 * @extends Roo.util.Observable
12910 * A Collection class that maintains both numeric indexes and keys and exposes events.
12912 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12913 * collection (defaults to false)
12914 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12915 * and return the key value for that item. This is used when available to look up the key on items that
12916 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12917 * equivalent to providing an implementation for the {@link #getKey} method.
12919 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12927 * Fires when the collection is cleared.
12932 * Fires when an item is added to the collection.
12933 * @param {Number} index The index at which the item was added.
12934 * @param {Object} o The item added.
12935 * @param {String} key The key associated with the added item.
12940 * Fires when an item is replaced in the collection.
12941 * @param {String} key he key associated with the new added.
12942 * @param {Object} old The item being replaced.
12943 * @param {Object} new The new item.
12948 * Fires when an item is removed from the collection.
12949 * @param {Object} o The item being removed.
12950 * @param {String} key (optional) The key associated with the removed item.
12955 this.allowFunctions = allowFunctions === true;
12957 this.getKey = keyFn;
12959 Roo.util.MixedCollection.superclass.constructor.call(this);
12962 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12963 allowFunctions : false,
12966 * Adds an item to the collection.
12967 * @param {String} key The key to associate with the item
12968 * @param {Object} o The item to add.
12969 * @return {Object} The item added.
12971 add : function(key, o){
12972 if(arguments.length == 1){
12974 key = this.getKey(o);
12976 if(typeof key == "undefined" || key === null){
12978 this.items.push(o);
12979 this.keys.push(null);
12981 var old = this.map[key];
12983 return this.replace(key, o);
12986 this.items.push(o);
12988 this.keys.push(key);
12990 this.fireEvent("add", this.length-1, o, key);
12995 * MixedCollection has a generic way to fetch keys if you implement getKey.
12998 var mc = new Roo.util.MixedCollection();
12999 mc.add(someEl.dom.id, someEl);
13000 mc.add(otherEl.dom.id, otherEl);
13004 var mc = new Roo.util.MixedCollection();
13005 mc.getKey = function(el){
13011 // or via the constructor
13012 var mc = new Roo.util.MixedCollection(false, function(el){
13018 * @param o {Object} The item for which to find the key.
13019 * @return {Object} The key for the passed item.
13021 getKey : function(o){
13026 * Replaces an item in the collection.
13027 * @param {String} key The key associated with the item to replace, or the item to replace.
13028 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
13029 * @return {Object} The new item.
13031 replace : function(key, o){
13032 if(arguments.length == 1){
13034 key = this.getKey(o);
13036 var old = this.item(key);
13037 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
13038 return this.add(key, o);
13040 var index = this.indexOfKey(key);
13041 this.items[index] = o;
13043 this.fireEvent("replace", key, old, o);
13048 * Adds all elements of an Array or an Object to the collection.
13049 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
13050 * an Array of values, each of which are added to the collection.
13052 addAll : function(objs){
13053 if(arguments.length > 1 || objs instanceof Array){
13054 var args = arguments.length > 1 ? arguments : objs;
13055 for(var i = 0, len = args.length; i < len; i++){
13059 for(var key in objs){
13060 if(this.allowFunctions || typeof objs[key] != "function"){
13061 this.add(key, objs[key]);
13068 * Executes the specified function once for every item in the collection, passing each
13069 * item as the first and only parameter. returning false from the function will stop the iteration.
13070 * @param {Function} fn The function to execute for each item.
13071 * @param {Object} scope (optional) The scope in which to execute the function.
13073 each : function(fn, scope){
13074 var items = [].concat(this.items); // each safe for removal
13075 for(var i = 0, len = items.length; i < len; i++){
13076 if(fn.call(scope || items[i], items[i], i, len) === false){
13083 * Executes the specified function once for every key in the collection, passing each
13084 * key, and its associated item as the first two parameters.
13085 * @param {Function} fn The function to execute for each item.
13086 * @param {Object} scope (optional) The scope in which to execute the function.
13088 eachKey : function(fn, scope){
13089 for(var i = 0, len = this.keys.length; i < len; i++){
13090 fn.call(scope || window, this.keys[i], this.items[i], i, len);
13095 * Returns the first item in the collection which elicits a true return value from the
13096 * passed selection function.
13097 * @param {Function} fn The selection function to execute for each item.
13098 * @param {Object} scope (optional) The scope in which to execute the function.
13099 * @return {Object} The first item in the collection which returned true from the selection function.
13101 find : function(fn, scope){
13102 for(var i = 0, len = this.items.length; i < len; i++){
13103 if(fn.call(scope || window, this.items[i], this.keys[i])){
13104 return this.items[i];
13111 * Inserts an item at the specified index in the collection.
13112 * @param {Number} index The index to insert the item at.
13113 * @param {String} key The key to associate with the new item, or the item itself.
13114 * @param {Object} o (optional) If the second parameter was a key, the new item.
13115 * @return {Object} The item inserted.
13117 insert : function(index, key, o){
13118 if(arguments.length == 2){
13120 key = this.getKey(o);
13122 if(index >= this.length){
13123 return this.add(key, o);
13126 this.items.splice(index, 0, o);
13127 if(typeof key != "undefined" && key != null){
13130 this.keys.splice(index, 0, key);
13131 this.fireEvent("add", index, o, key);
13136 * Removed an item from the collection.
13137 * @param {Object} o The item to remove.
13138 * @return {Object} The item removed.
13140 remove : function(o){
13141 return this.removeAt(this.indexOf(o));
13145 * Remove an item from a specified index in the collection.
13146 * @param {Number} index The index within the collection of the item to remove.
13148 removeAt : function(index){
13149 if(index < this.length && index >= 0){
13151 var o = this.items[index];
13152 this.items.splice(index, 1);
13153 var key = this.keys[index];
13154 if(typeof key != "undefined"){
13155 delete this.map[key];
13157 this.keys.splice(index, 1);
13158 this.fireEvent("remove", o, key);
13163 * Removed an item associated with the passed key fom the collection.
13164 * @param {String} key The key of the item to remove.
13166 removeKey : function(key){
13167 return this.removeAt(this.indexOfKey(key));
13171 * Returns the number of items in the collection.
13172 * @return {Number} the number of items in the collection.
13174 getCount : function(){
13175 return this.length;
13179 * Returns index within the collection of the passed Object.
13180 * @param {Object} o The item to find the index of.
13181 * @return {Number} index of the item.
13183 indexOf : function(o){
13184 if(!this.items.indexOf){
13185 for(var i = 0, len = this.items.length; i < len; i++){
13186 if(this.items[i] == o) {
13192 return this.items.indexOf(o);
13197 * Returns index within the collection of the passed key.
13198 * @param {String} key The key to find the index of.
13199 * @return {Number} index of the key.
13201 indexOfKey : function(key){
13202 if(!this.keys.indexOf){
13203 for(var i = 0, len = this.keys.length; i < len; i++){
13204 if(this.keys[i] == key) {
13210 return this.keys.indexOf(key);
13215 * Returns the item associated with the passed key OR index. Key has priority over index.
13216 * @param {String/Number} key The key or index of the item.
13217 * @return {Object} The item associated with the passed key.
13219 item : function(key){
13220 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13221 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13225 * Returns the item at the specified index.
13226 * @param {Number} index The index of the item.
13229 itemAt : function(index){
13230 return this.items[index];
13234 * Returns the item associated with the passed key.
13235 * @param {String/Number} key The key of the item.
13236 * @return {Object} The item associated with the passed key.
13238 key : function(key){
13239 return this.map[key];
13243 * Returns true if the collection contains the passed Object as an item.
13244 * @param {Object} o The Object to look for in the collection.
13245 * @return {Boolean} True if the collection contains the Object as an item.
13247 contains : function(o){
13248 return this.indexOf(o) != -1;
13252 * Returns true if the collection contains the passed Object as a key.
13253 * @param {String} key The key to look for in the collection.
13254 * @return {Boolean} True if the collection contains the Object as a key.
13256 containsKey : function(key){
13257 return typeof this.map[key] != "undefined";
13261 * Removes all items from the collection.
13263 clear : function(){
13268 this.fireEvent("clear");
13272 * Returns the first item in the collection.
13273 * @return {Object} the first item in the collection..
13275 first : function(){
13276 return this.items[0];
13280 * Returns the last item in the collection.
13281 * @return {Object} the last item in the collection..
13284 return this.items[this.length-1];
13287 _sort : function(property, dir, fn){
13288 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13289 fn = fn || function(a, b){
13292 var c = [], k = this.keys, items = this.items;
13293 for(var i = 0, len = items.length; i < len; i++){
13294 c[c.length] = {key: k[i], value: items[i], index: i};
13296 c.sort(function(a, b){
13297 var v = fn(a[property], b[property]) * dsc;
13299 v = (a.index < b.index ? -1 : 1);
13303 for(var i = 0, len = c.length; i < len; i++){
13304 items[i] = c[i].value;
13307 this.fireEvent("sort", this);
13311 * Sorts this collection with the passed comparison function
13312 * @param {String} direction (optional) "ASC" or "DESC"
13313 * @param {Function} fn (optional) comparison function
13315 sort : function(dir, fn){
13316 this._sort("value", dir, fn);
13320 * Sorts this collection by keys
13321 * @param {String} direction (optional) "ASC" or "DESC"
13322 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13324 keySort : function(dir, fn){
13325 this._sort("key", dir, fn || function(a, b){
13326 return String(a).toUpperCase()-String(b).toUpperCase();
13331 * Returns a range of items in this collection
13332 * @param {Number} startIndex (optional) defaults to 0
13333 * @param {Number} endIndex (optional) default to the last item
13334 * @return {Array} An array of items
13336 getRange : function(start, end){
13337 var items = this.items;
13338 if(items.length < 1){
13341 start = start || 0;
13342 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13345 for(var i = start; i <= end; i++) {
13346 r[r.length] = items[i];
13349 for(var i = start; i >= end; i--) {
13350 r[r.length] = items[i];
13357 * Filter the <i>objects</i> in this collection by a specific property.
13358 * Returns a new collection that has been filtered.
13359 * @param {String} property A property on your objects
13360 * @param {String/RegExp} value Either string that the property values
13361 * should start with or a RegExp to test against the property
13362 * @return {MixedCollection} The new filtered collection
13364 filter : function(property, value){
13365 if(!value.exec){ // not a regex
13366 value = String(value);
13367 if(value.length == 0){
13368 return this.clone();
13370 value = new RegExp("^" + Roo.escapeRe(value), "i");
13372 return this.filterBy(function(o){
13373 return o && value.test(o[property]);
13378 * Filter by a function. * Returns a new collection that has been filtered.
13379 * The passed function will be called with each
13380 * object in the collection. If the function returns true, the value is included
13381 * otherwise it is filtered.
13382 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13383 * @param {Object} scope (optional) The scope of the function (defaults to this)
13384 * @return {MixedCollection} The new filtered collection
13386 filterBy : function(fn, scope){
13387 var r = new Roo.util.MixedCollection();
13388 r.getKey = this.getKey;
13389 var k = this.keys, it = this.items;
13390 for(var i = 0, len = it.length; i < len; i++){
13391 if(fn.call(scope||this, it[i], k[i])){
13392 r.add(k[i], it[i]);
13399 * Creates a duplicate of this collection
13400 * @return {MixedCollection}
13402 clone : function(){
13403 var r = new Roo.util.MixedCollection();
13404 var k = this.keys, it = this.items;
13405 for(var i = 0, len = it.length; i < len; i++){
13406 r.add(k[i], it[i]);
13408 r.getKey = this.getKey;
13413 * Returns the item associated with the passed key or index.
13415 * @param {String/Number} key The key or index of the item.
13416 * @return {Object} The item associated with the passed key.
13418 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13420 * Ext JS Library 1.1.1
13421 * Copyright(c) 2006-2007, Ext JS, LLC.
13423 * Originally Released Under LGPL - original licence link has changed is not relivant.
13426 * <script type="text/javascript">
13429 * @class Roo.util.JSON
13430 * Modified version of Douglas Crockford"s json.js that doesn"t
13431 * mess with the Object prototype
13432 * http://www.json.org/js.html
13435 Roo.util.JSON = new (function(){
13436 var useHasOwn = {}.hasOwnProperty ? true : false;
13438 // crashes Safari in some instances
13439 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13441 var pad = function(n) {
13442 return n < 10 ? "0" + n : n;
13455 var encodeString = function(s){
13456 if (/["\\\x00-\x1f]/.test(s)) {
13457 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13462 c = b.charCodeAt();
13464 Math.floor(c / 16).toString(16) +
13465 (c % 16).toString(16);
13468 return '"' + s + '"';
13471 var encodeArray = function(o){
13472 var a = ["["], b, i, l = o.length, v;
13473 for (i = 0; i < l; i += 1) {
13475 switch (typeof v) {
13484 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13492 var encodeDate = function(o){
13493 return '"' + o.getFullYear() + "-" +
13494 pad(o.getMonth() + 1) + "-" +
13495 pad(o.getDate()) + "T" +
13496 pad(o.getHours()) + ":" +
13497 pad(o.getMinutes()) + ":" +
13498 pad(o.getSeconds()) + '"';
13502 * Encodes an Object, Array or other value
13503 * @param {Mixed} o The variable to encode
13504 * @return {String} The JSON string
13506 this.encode = function(o)
13508 // should this be extended to fully wrap stringify..
13510 if(typeof o == "undefined" || o === null){
13512 }else if(o instanceof Array){
13513 return encodeArray(o);
13514 }else if(o instanceof Date){
13515 return encodeDate(o);
13516 }else if(typeof o == "string"){
13517 return encodeString(o);
13518 }else if(typeof o == "number"){
13519 return isFinite(o) ? String(o) : "null";
13520 }else if(typeof o == "boolean"){
13523 var a = ["{"], b, i, v;
13525 if(!useHasOwn || o.hasOwnProperty(i)) {
13527 switch (typeof v) {
13536 a.push(this.encode(i), ":",
13537 v === null ? "null" : this.encode(v));
13548 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13549 * @param {String} json The JSON string
13550 * @return {Object} The resulting object
13552 this.decode = function(json){
13554 return /** eval:var:json */ eval("(" + json + ')');
13558 * Shorthand for {@link Roo.util.JSON#encode}
13559 * @member Roo encode
13561 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13563 * Shorthand for {@link Roo.util.JSON#decode}
13564 * @member Roo decode
13566 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13569 * Ext JS Library 1.1.1
13570 * Copyright(c) 2006-2007, Ext JS, LLC.
13572 * Originally Released Under LGPL - original licence link has changed is not relivant.
13575 * <script type="text/javascript">
13579 * @class Roo.util.Format
13580 * Reusable data formatting functions
13583 Roo.util.Format = function(){
13584 var trimRe = /^\s+|\s+$/g;
13587 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13588 * @param {String} value The string to truncate
13589 * @param {Number} length The maximum length to allow before truncating
13590 * @return {String} The converted text
13592 ellipsis : function(value, len){
13593 if(value && value.length > len){
13594 return value.substr(0, len-3)+"...";
13600 * Checks a reference and converts it to empty string if it is undefined
13601 * @param {Mixed} value Reference to check
13602 * @return {Mixed} Empty string if converted, otherwise the original value
13604 undef : function(value){
13605 return typeof value != "undefined" ? value : "";
13609 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13610 * @param {String} value The string to encode
13611 * @return {String} The encoded text
13613 htmlEncode : function(value){
13614 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13618 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13619 * @param {String} value The string to decode
13620 * @return {String} The decoded text
13622 htmlDecode : function(value){
13623 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13627 * Trims any whitespace from either side of a string
13628 * @param {String} value The text to trim
13629 * @return {String} The trimmed text
13631 trim : function(value){
13632 return String(value).replace(trimRe, "");
13636 * Returns a substring from within an original string
13637 * @param {String} value The original text
13638 * @param {Number} start The start index of the substring
13639 * @param {Number} length The length of the substring
13640 * @return {String} The substring
13642 substr : function(value, start, length){
13643 return String(value).substr(start, length);
13647 * Converts a string to all lower case letters
13648 * @param {String} value The text to convert
13649 * @return {String} The converted text
13651 lowercase : function(value){
13652 return String(value).toLowerCase();
13656 * Converts a string to all upper case letters
13657 * @param {String} value The text to convert
13658 * @return {String} The converted text
13660 uppercase : function(value){
13661 return String(value).toUpperCase();
13665 * Converts the first character only of a string to upper case
13666 * @param {String} value The text to convert
13667 * @return {String} The converted text
13669 capitalize : function(value){
13670 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13674 call : function(value, fn){
13675 if(arguments.length > 2){
13676 var args = Array.prototype.slice.call(arguments, 2);
13677 args.unshift(value);
13679 return /** eval:var:value */ eval(fn).apply(window, args);
13681 /** eval:var:value */
13682 return /** eval:var:value */ eval(fn).call(window, value);
13688 * safer version of Math.toFixed..??/
13689 * @param {Number/String} value The numeric value to format
13690 * @param {Number/String} value Decimal places
13691 * @return {String} The formatted currency string
13693 toFixed : function(v, n)
13695 // why not use to fixed - precision is buggered???
13697 return Math.round(v-0);
13699 var fact = Math.pow(10,n+1);
13700 v = (Math.round((v-0)*fact))/fact;
13701 var z = (''+fact).substring(2);
13702 if (v == Math.floor(v)) {
13703 return Math.floor(v) + '.' + z;
13706 // now just padd decimals..
13707 var ps = String(v).split('.');
13708 var fd = (ps[1] + z);
13709 var r = fd.substring(0,n);
13710 var rm = fd.substring(n);
13712 return ps[0] + '.' + r;
13714 r*=1; // turn it into a number;
13716 if (String(r).length != n) {
13719 r = String(r).substring(1); // chop the end off.
13722 return ps[0] + '.' + r;
13727 * Format a number as US currency
13728 * @param {Number/String} value The numeric value to format
13729 * @return {String} The formatted currency string
13731 usMoney : function(v){
13732 return '$' + Roo.util.Format.number(v);
13737 * eventually this should probably emulate php's number_format
13738 * @param {Number/String} value The numeric value to format
13739 * @param {Number} decimals number of decimal places
13740 * @return {String} The formatted currency string
13742 number : function(v,decimals)
13744 // multiply and round.
13745 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13746 var mul = Math.pow(10, decimals);
13747 var zero = String(mul).substring(1);
13748 v = (Math.round((v-0)*mul))/mul;
13750 // if it's '0' number.. then
13752 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13754 var ps = v.split('.');
13758 var r = /(\d+)(\d{3})/;
13760 while (r.test(whole)) {
13761 whole = whole.replace(r, '$1' + ',' + '$2');
13767 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13768 // does not have decimals
13769 (decimals ? ('.' + zero) : '');
13772 return whole + sub ;
13776 * Parse a value into a formatted date using the specified format pattern.
13777 * @param {Mixed} value The value to format
13778 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13779 * @return {String} The formatted date string
13781 date : function(v, format){
13785 if(!(v instanceof Date)){
13786 v = new Date(Date.parse(v));
13788 return v.dateFormat(format || Roo.util.Format.defaults.date);
13792 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13793 * @param {String} format Any valid date format string
13794 * @return {Function} The date formatting function
13796 dateRenderer : function(format){
13797 return function(v){
13798 return Roo.util.Format.date(v, format);
13803 stripTagsRE : /<\/?[^>]+>/gi,
13806 * Strips all HTML tags
13807 * @param {Mixed} value The text from which to strip tags
13808 * @return {String} The stripped text
13810 stripTags : function(v){
13811 return !v ? v : String(v).replace(this.stripTagsRE, "");
13815 Roo.util.Format.defaults = {
13819 * Ext JS Library 1.1.1
13820 * Copyright(c) 2006-2007, Ext JS, LLC.
13822 * Originally Released Under LGPL - original licence link has changed is not relivant.
13825 * <script type="text/javascript">
13832 * @class Roo.MasterTemplate
13833 * @extends Roo.Template
13834 * Provides a template that can have child templates. The syntax is:
13836 var t = new Roo.MasterTemplate(
13837 '<select name="{name}">',
13838 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13841 t.add('options', {value: 'foo', text: 'bar'});
13842 // or you can add multiple child elements in one shot
13843 t.addAll('options', [
13844 {value: 'foo', text: 'bar'},
13845 {value: 'foo2', text: 'bar2'},
13846 {value: 'foo3', text: 'bar3'}
13848 // then append, applying the master template values
13849 t.append('my-form', {name: 'my-select'});
13851 * A name attribute for the child template is not required if you have only one child
13852 * template or you want to refer to them by index.
13854 Roo.MasterTemplate = function(){
13855 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13856 this.originalHtml = this.html;
13858 var m, re = this.subTemplateRe;
13861 while(m = re.exec(this.html)){
13862 var name = m[1], content = m[2];
13867 tpl : new Roo.Template(content)
13870 st[name] = st[subIndex];
13872 st[subIndex].tpl.compile();
13873 st[subIndex].tpl.call = this.call.createDelegate(this);
13876 this.subCount = subIndex;
13879 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13881 * The regular expression used to match sub templates
13885 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13888 * Applies the passed values to a child template.
13889 * @param {String/Number} name (optional) The name or index of the child template
13890 * @param {Array/Object} values The values to be applied to the template
13891 * @return {MasterTemplate} this
13893 add : function(name, values){
13894 if(arguments.length == 1){
13895 values = arguments[0];
13898 var s = this.subs[name];
13899 s.buffer[s.buffer.length] = s.tpl.apply(values);
13904 * Applies all the passed values to a child template.
13905 * @param {String/Number} name (optional) The name or index of the child template
13906 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13907 * @param {Boolean} reset (optional) True to reset the template first
13908 * @return {MasterTemplate} this
13910 fill : function(name, values, reset){
13912 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13920 for(var i = 0, len = values.length; i < len; i++){
13921 this.add(name, values[i]);
13927 * Resets the template for reuse
13928 * @return {MasterTemplate} this
13930 reset : function(){
13932 for(var i = 0; i < this.subCount; i++){
13938 applyTemplate : function(values){
13940 var replaceIndex = -1;
13941 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13942 return s[++replaceIndex].buffer.join("");
13944 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13947 apply : function(){
13948 return this.applyTemplate.apply(this, arguments);
13951 compile : function(){return this;}
13955 * Alias for fill().
13958 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13960 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13961 * var tpl = Roo.MasterTemplate.from('element-id');
13962 * @param {String/HTMLElement} el
13963 * @param {Object} config
13966 Roo.MasterTemplate.from = function(el, config){
13967 el = Roo.getDom(el);
13968 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13971 * Ext JS Library 1.1.1
13972 * Copyright(c) 2006-2007, Ext JS, LLC.
13974 * Originally Released Under LGPL - original licence link has changed is not relivant.
13977 * <script type="text/javascript">
13982 * @class Roo.util.CSS
13983 * Utility class for manipulating CSS rules
13986 Roo.util.CSS = function(){
13988 var doc = document;
13990 var camelRe = /(-[a-z])/gi;
13991 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13995 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13996 * tag and appended to the HEAD of the document.
13997 * @param {String|Object} cssText The text containing the css rules
13998 * @param {String} id An id to add to the stylesheet for later removal
13999 * @return {StyleSheet}
14001 createStyleSheet : function(cssText, id){
14003 var head = doc.getElementsByTagName("head")[0];
14004 var nrules = doc.createElement("style");
14005 nrules.setAttribute("type", "text/css");
14007 nrules.setAttribute("id", id);
14009 if (typeof(cssText) != 'string') {
14010 // support object maps..
14011 // not sure if this a good idea..
14012 // perhaps it should be merged with the general css handling
14013 // and handle js style props.
14014 var cssTextNew = [];
14015 for(var n in cssText) {
14017 for(var k in cssText[n]) {
14018 citems.push( k + ' : ' +cssText[n][k] + ';' );
14020 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
14023 cssText = cssTextNew.join("\n");
14029 head.appendChild(nrules);
14030 ss = nrules.styleSheet;
14031 ss.cssText = cssText;
14034 nrules.appendChild(doc.createTextNode(cssText));
14036 nrules.cssText = cssText;
14038 head.appendChild(nrules);
14039 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
14041 this.cacheStyleSheet(ss);
14046 * Removes a style or link tag by id
14047 * @param {String} id The id of the tag
14049 removeStyleSheet : function(id){
14050 var existing = doc.getElementById(id);
14052 existing.parentNode.removeChild(existing);
14057 * Dynamically swaps an existing stylesheet reference for a new one
14058 * @param {String} id The id of an existing link tag to remove
14059 * @param {String} url The href of the new stylesheet to include
14061 swapStyleSheet : function(id, url){
14062 this.removeStyleSheet(id);
14063 var ss = doc.createElement("link");
14064 ss.setAttribute("rel", "stylesheet");
14065 ss.setAttribute("type", "text/css");
14066 ss.setAttribute("id", id);
14067 ss.setAttribute("href", url);
14068 doc.getElementsByTagName("head")[0].appendChild(ss);
14072 * Refresh the rule cache if you have dynamically added stylesheets
14073 * @return {Object} An object (hash) of rules indexed by selector
14075 refreshCache : function(){
14076 return this.getRules(true);
14080 cacheStyleSheet : function(stylesheet){
14084 try{// try catch for cross domain access issue
14085 var ssRules = stylesheet.cssRules || stylesheet.rules;
14086 for(var j = ssRules.length-1; j >= 0; --j){
14087 rules[ssRules[j].selectorText] = ssRules[j];
14093 * Gets all css rules for the document
14094 * @param {Boolean} refreshCache true to refresh the internal cache
14095 * @return {Object} An object (hash) of rules indexed by selector
14097 getRules : function(refreshCache){
14098 if(rules == null || refreshCache){
14100 var ds = doc.styleSheets;
14101 for(var i =0, len = ds.length; i < len; i++){
14103 this.cacheStyleSheet(ds[i]);
14111 * Gets an an individual CSS rule by selector(s)
14112 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
14113 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
14114 * @return {CSSRule} The CSS rule or null if one is not found
14116 getRule : function(selector, refreshCache){
14117 var rs = this.getRules(refreshCache);
14118 if(!(selector instanceof Array)){
14119 return rs[selector];
14121 for(var i = 0; i < selector.length; i++){
14122 if(rs[selector[i]]){
14123 return rs[selector[i]];
14131 * Updates a rule property
14132 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14133 * @param {String} property The css property
14134 * @param {String} value The new value for the property
14135 * @return {Boolean} true If a rule was found and updated
14137 updateRule : function(selector, property, value){
14138 if(!(selector instanceof Array)){
14139 var rule = this.getRule(selector);
14141 rule.style[property.replace(camelRe, camelFn)] = value;
14145 for(var i = 0; i < selector.length; i++){
14146 if(this.updateRule(selector[i], property, value)){
14156 * Ext JS Library 1.1.1
14157 * Copyright(c) 2006-2007, Ext JS, LLC.
14159 * Originally Released Under LGPL - original licence link has changed is not relivant.
14162 * <script type="text/javascript">
14168 * @class Roo.util.ClickRepeater
14169 * @extends Roo.util.Observable
14171 * A wrapper class which can be applied to any element. Fires a "click" event while the
14172 * mouse is pressed. The interval between firings may be specified in the config but
14173 * defaults to 10 milliseconds.
14175 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14177 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14178 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14179 * Similar to an autorepeat key delay.
14180 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14181 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14182 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14183 * "interval" and "delay" are ignored. "immediate" is honored.
14184 * @cfg {Boolean} preventDefault True to prevent the default click event
14185 * @cfg {Boolean} stopDefault True to stop the default click event
14188 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14189 * 2007-02-02 jvs Renamed to ClickRepeater
14190 * 2007-02-03 jvs Modifications for FF Mac and Safari
14193 * @param {String/HTMLElement/Element} el The element to listen on
14194 * @param {Object} config
14196 Roo.util.ClickRepeater = function(el, config)
14198 this.el = Roo.get(el);
14199 this.el.unselectable();
14201 Roo.apply(this, config);
14206 * Fires when the mouse button is depressed.
14207 * @param {Roo.util.ClickRepeater} this
14209 "mousedown" : true,
14212 * Fires on a specified interval during the time the element is pressed.
14213 * @param {Roo.util.ClickRepeater} this
14218 * Fires when the mouse key is released.
14219 * @param {Roo.util.ClickRepeater} this
14224 this.el.on("mousedown", this.handleMouseDown, this);
14225 if(this.preventDefault || this.stopDefault){
14226 this.el.on("click", function(e){
14227 if(this.preventDefault){
14228 e.preventDefault();
14230 if(this.stopDefault){
14236 // allow inline handler
14238 this.on("click", this.handler, this.scope || this);
14241 Roo.util.ClickRepeater.superclass.constructor.call(this);
14244 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14247 preventDefault : true,
14248 stopDefault : false,
14252 handleMouseDown : function(){
14253 clearTimeout(this.timer);
14255 if(this.pressClass){
14256 this.el.addClass(this.pressClass);
14258 this.mousedownTime = new Date();
14260 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14261 this.el.on("mouseout", this.handleMouseOut, this);
14263 this.fireEvent("mousedown", this);
14264 this.fireEvent("click", this);
14266 this.timer = this.click.defer(this.delay || this.interval, this);
14270 click : function(){
14271 this.fireEvent("click", this);
14272 this.timer = this.click.defer(this.getInterval(), this);
14276 getInterval: function(){
14277 if(!this.accelerate){
14278 return this.interval;
14280 var pressTime = this.mousedownTime.getElapsed();
14281 if(pressTime < 500){
14283 }else if(pressTime < 1700){
14285 }else if(pressTime < 2600){
14287 }else if(pressTime < 3500){
14289 }else if(pressTime < 4400){
14291 }else if(pressTime < 5300){
14293 }else if(pressTime < 6200){
14301 handleMouseOut : function(){
14302 clearTimeout(this.timer);
14303 if(this.pressClass){
14304 this.el.removeClass(this.pressClass);
14306 this.el.on("mouseover", this.handleMouseReturn, this);
14310 handleMouseReturn : function(){
14311 this.el.un("mouseover", this.handleMouseReturn);
14312 if(this.pressClass){
14313 this.el.addClass(this.pressClass);
14319 handleMouseUp : function(){
14320 clearTimeout(this.timer);
14321 this.el.un("mouseover", this.handleMouseReturn);
14322 this.el.un("mouseout", this.handleMouseOut);
14323 Roo.get(document).un("mouseup", this.handleMouseUp);
14324 this.el.removeClass(this.pressClass);
14325 this.fireEvent("mouseup", this);
14329 * Ext JS Library 1.1.1
14330 * Copyright(c) 2006-2007, Ext JS, LLC.
14332 * Originally Released Under LGPL - original licence link has changed is not relivant.
14335 * <script type="text/javascript">
14340 * @class Roo.KeyNav
14341 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14342 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14343 * way to implement custom navigation schemes for any UI component.</p>
14344 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14345 * pageUp, pageDown, del, home, end. Usage:</p>
14347 var nav = new Roo.KeyNav("my-element", {
14348 "left" : function(e){
14349 this.moveLeft(e.ctrlKey);
14351 "right" : function(e){
14352 this.moveRight(e.ctrlKey);
14354 "enter" : function(e){
14361 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14362 * @param {Object} config The config
14364 Roo.KeyNav = function(el, config){
14365 this.el = Roo.get(el);
14366 Roo.apply(this, config);
14367 if(!this.disabled){
14368 this.disabled = true;
14373 Roo.KeyNav.prototype = {
14375 * @cfg {Boolean} disabled
14376 * True to disable this KeyNav instance (defaults to false)
14380 * @cfg {String} defaultEventAction
14381 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14382 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14383 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14385 defaultEventAction: "stopEvent",
14387 * @cfg {Boolean} forceKeyDown
14388 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14389 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14390 * handle keydown instead of keypress.
14392 forceKeyDown : false,
14395 prepareEvent : function(e){
14396 var k = e.getKey();
14397 var h = this.keyToHandler[k];
14398 //if(h && this[h]){
14399 // e.stopPropagation();
14401 if(Roo.isSafari && h && k >= 37 && k <= 40){
14407 relay : function(e){
14408 var k = e.getKey();
14409 var h = this.keyToHandler[k];
14411 if(this.doRelay(e, this[h], h) !== true){
14412 e[this.defaultEventAction]();
14418 doRelay : function(e, h, hname){
14419 return h.call(this.scope || this, e);
14422 // possible handlers
14436 // quick lookup hash
14453 * Enable this KeyNav
14455 enable: function(){
14457 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14458 // the EventObject will normalize Safari automatically
14459 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14460 this.el.on("keydown", this.relay, this);
14462 this.el.on("keydown", this.prepareEvent, this);
14463 this.el.on("keypress", this.relay, this);
14465 this.disabled = false;
14470 * Disable this KeyNav
14472 disable: function(){
14473 if(!this.disabled){
14474 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14475 this.el.un("keydown", this.relay);
14477 this.el.un("keydown", this.prepareEvent);
14478 this.el.un("keypress", this.relay);
14480 this.disabled = true;
14485 * Ext JS Library 1.1.1
14486 * Copyright(c) 2006-2007, Ext JS, LLC.
14488 * Originally Released Under LGPL - original licence link has changed is not relivant.
14491 * <script type="text/javascript">
14496 * @class Roo.KeyMap
14497 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14498 * The constructor accepts the same config object as defined by {@link #addBinding}.
14499 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14500 * combination it will call the function with this signature (if the match is a multi-key
14501 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14502 * A KeyMap can also handle a string representation of keys.<br />
14505 // map one key by key code
14506 var map = new Roo.KeyMap("my-element", {
14507 key: 13, // or Roo.EventObject.ENTER
14512 // map multiple keys to one action by string
14513 var map = new Roo.KeyMap("my-element", {
14519 // map multiple keys to multiple actions by strings and array of codes
14520 var map = new Roo.KeyMap("my-element", [
14523 fn: function(){ alert("Return was pressed"); }
14526 fn: function(){ alert('a, b or c was pressed'); }
14531 fn: function(){ alert('Control + shift + tab was pressed.'); }
14535 * <b>Note: A KeyMap starts enabled</b>
14537 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14538 * @param {Object} config The config (see {@link #addBinding})
14539 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14541 Roo.KeyMap = function(el, config, eventName){
14542 this.el = Roo.get(el);
14543 this.eventName = eventName || "keydown";
14544 this.bindings = [];
14546 this.addBinding(config);
14551 Roo.KeyMap.prototype = {
14553 * True to stop the event from bubbling and prevent the default browser action if the
14554 * key was handled by the KeyMap (defaults to false)
14560 * Add a new binding to this KeyMap. The following config object properties are supported:
14562 Property Type Description
14563 ---------- --------------- ----------------------------------------------------------------------
14564 key String/Array A single keycode or an array of keycodes to handle
14565 shift Boolean True to handle key only when shift is pressed (defaults to false)
14566 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14567 alt Boolean True to handle key only when alt is pressed (defaults to false)
14568 fn Function The function to call when KeyMap finds the expected key combination
14569 scope Object The scope of the callback function
14575 var map = new Roo.KeyMap(document, {
14576 key: Roo.EventObject.ENTER,
14581 //Add a new binding to the existing KeyMap later
14589 * @param {Object/Array} config A single KeyMap config or an array of configs
14591 addBinding : function(config){
14592 if(config instanceof Array){
14593 for(var i = 0, len = config.length; i < len; i++){
14594 this.addBinding(config[i]);
14598 var keyCode = config.key,
14599 shift = config.shift,
14600 ctrl = config.ctrl,
14603 scope = config.scope;
14604 if(typeof keyCode == "string"){
14606 var keyString = keyCode.toUpperCase();
14607 for(var j = 0, len = keyString.length; j < len; j++){
14608 ks.push(keyString.charCodeAt(j));
14612 var keyArray = keyCode instanceof Array;
14613 var handler = function(e){
14614 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14615 var k = e.getKey();
14617 for(var i = 0, len = keyCode.length; i < len; i++){
14618 if(keyCode[i] == k){
14619 if(this.stopEvent){
14622 fn.call(scope || window, k, e);
14628 if(this.stopEvent){
14631 fn.call(scope || window, k, e);
14636 this.bindings.push(handler);
14640 * Shorthand for adding a single key listener
14641 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14642 * following options:
14643 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14644 * @param {Function} fn The function to call
14645 * @param {Object} scope (optional) The scope of the function
14647 on : function(key, fn, scope){
14648 var keyCode, shift, ctrl, alt;
14649 if(typeof key == "object" && !(key instanceof Array)){
14668 handleKeyDown : function(e){
14669 if(this.enabled){ //just in case
14670 var b = this.bindings;
14671 for(var i = 0, len = b.length; i < len; i++){
14672 b[i].call(this, e);
14678 * Returns true if this KeyMap is enabled
14679 * @return {Boolean}
14681 isEnabled : function(){
14682 return this.enabled;
14686 * Enables this KeyMap
14688 enable: function(){
14690 this.el.on(this.eventName, this.handleKeyDown, this);
14691 this.enabled = true;
14696 * Disable this KeyMap
14698 disable: function(){
14700 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14701 this.enabled = false;
14706 * Ext JS Library 1.1.1
14707 * Copyright(c) 2006-2007, Ext JS, LLC.
14709 * Originally Released Under LGPL - original licence link has changed is not relivant.
14712 * <script type="text/javascript">
14717 * @class Roo.util.TextMetrics
14718 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14719 * wide, in pixels, a given block of text will be.
14722 Roo.util.TextMetrics = function(){
14726 * Measures the size of the specified text
14727 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14728 * that can affect the size of the rendered text
14729 * @param {String} text The text to measure
14730 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14731 * in order to accurately measure the text height
14732 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14734 measure : function(el, text, fixedWidth){
14736 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14739 shared.setFixedWidth(fixedWidth || 'auto');
14740 return shared.getSize(text);
14744 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14745 * the overhead of multiple calls to initialize the style properties on each measurement.
14746 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14747 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14748 * in order to accurately measure the text height
14749 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14751 createInstance : function(el, fixedWidth){
14752 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14759 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14760 var ml = new Roo.Element(document.createElement('div'));
14761 document.body.appendChild(ml.dom);
14762 ml.position('absolute');
14763 ml.setLeftTop(-1000, -1000);
14767 ml.setWidth(fixedWidth);
14772 * Returns the size of the specified text based on the internal element's style and width properties
14773 * @memberOf Roo.util.TextMetrics.Instance#
14774 * @param {String} text The text to measure
14775 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14777 getSize : function(text){
14779 var s = ml.getSize();
14785 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14786 * that can affect the size of the rendered text
14787 * @memberOf Roo.util.TextMetrics.Instance#
14788 * @param {String/HTMLElement} el The element, dom node or id
14790 bind : function(el){
14792 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14797 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14798 * to set a fixed width in order to accurately measure the text height.
14799 * @memberOf Roo.util.TextMetrics.Instance#
14800 * @param {Number} width The width to set on the element
14802 setFixedWidth : function(width){
14803 ml.setWidth(width);
14807 * Returns the measured width of the specified text
14808 * @memberOf Roo.util.TextMetrics.Instance#
14809 * @param {String} text The text to measure
14810 * @return {Number} width The width in pixels
14812 getWidth : function(text){
14813 ml.dom.style.width = 'auto';
14814 return this.getSize(text).width;
14818 * Returns the measured height of the specified text. For multiline text, be sure to call
14819 * {@link #setFixedWidth} if necessary.
14820 * @memberOf Roo.util.TextMetrics.Instance#
14821 * @param {String} text The text to measure
14822 * @return {Number} height The height in pixels
14824 getHeight : function(text){
14825 return this.getSize(text).height;
14829 instance.bind(bindTo);
14834 // backwards compat
14835 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14837 * Ext JS Library 1.1.1
14838 * Copyright(c) 2006-2007, Ext JS, LLC.
14840 * Originally Released Under LGPL - original licence link has changed is not relivant.
14843 * <script type="text/javascript">
14847 * @class Roo.state.Provider
14848 * Abstract base class for state provider implementations. This class provides methods
14849 * for encoding and decoding <b>typed</b> variables including dates and defines the
14850 * Provider interface.
14852 Roo.state.Provider = function(){
14854 * @event statechange
14855 * Fires when a state change occurs.
14856 * @param {Provider} this This state provider
14857 * @param {String} key The state key which was changed
14858 * @param {String} value The encoded value for the state
14861 "statechange": true
14864 Roo.state.Provider.superclass.constructor.call(this);
14866 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14868 * Returns the current value for a key
14869 * @param {String} name The key name
14870 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14871 * @return {Mixed} The state data
14873 get : function(name, defaultValue){
14874 return typeof this.state[name] == "undefined" ?
14875 defaultValue : this.state[name];
14879 * Clears a value from the state
14880 * @param {String} name The key name
14882 clear : function(name){
14883 delete this.state[name];
14884 this.fireEvent("statechange", this, name, null);
14888 * Sets the value for a key
14889 * @param {String} name The key name
14890 * @param {Mixed} value The value to set
14892 set : function(name, value){
14893 this.state[name] = value;
14894 this.fireEvent("statechange", this, name, value);
14898 * Decodes a string previously encoded with {@link #encodeValue}.
14899 * @param {String} value The value to decode
14900 * @return {Mixed} The decoded value
14902 decodeValue : function(cookie){
14903 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14904 var matches = re.exec(unescape(cookie));
14905 if(!matches || !matches[1]) {
14906 return; // non state cookie
14908 var type = matches[1];
14909 var v = matches[2];
14912 return parseFloat(v);
14914 return new Date(Date.parse(v));
14919 var values = v.split("^");
14920 for(var i = 0, len = values.length; i < len; i++){
14921 all.push(this.decodeValue(values[i]));
14926 var values = v.split("^");
14927 for(var i = 0, len = values.length; i < len; i++){
14928 var kv = values[i].split("=");
14929 all[kv[0]] = this.decodeValue(kv[1]);
14938 * Encodes a value including type information. Decode with {@link #decodeValue}.
14939 * @param {Mixed} value The value to encode
14940 * @return {String} The encoded value
14942 encodeValue : function(v){
14944 if(typeof v == "number"){
14946 }else if(typeof v == "boolean"){
14947 enc = "b:" + (v ? "1" : "0");
14948 }else if(v instanceof Date){
14949 enc = "d:" + v.toGMTString();
14950 }else if(v instanceof Array){
14952 for(var i = 0, len = v.length; i < len; i++){
14953 flat += this.encodeValue(v[i]);
14959 }else if(typeof v == "object"){
14962 if(typeof v[key] != "function"){
14963 flat += key + "=" + this.encodeValue(v[key]) + "^";
14966 enc = "o:" + flat.substring(0, flat.length-1);
14970 return escape(enc);
14976 * Ext JS Library 1.1.1
14977 * Copyright(c) 2006-2007, Ext JS, LLC.
14979 * Originally Released Under LGPL - original licence link has changed is not relivant.
14982 * <script type="text/javascript">
14985 * @class Roo.state.Manager
14986 * This is the global state manager. By default all components that are "state aware" check this class
14987 * for state information if you don't pass them a custom state provider. In order for this class
14988 * to be useful, it must be initialized with a provider when your application initializes.
14990 // in your initialization function
14992 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14994 // supposed you have a {@link Roo.BorderLayout}
14995 var layout = new Roo.BorderLayout(...);
14996 layout.restoreState();
14997 // or a {Roo.BasicDialog}
14998 var dialog = new Roo.BasicDialog(...);
14999 dialog.restoreState();
15003 Roo.state.Manager = function(){
15004 var provider = new Roo.state.Provider();
15008 * Configures the default state provider for your application
15009 * @param {Provider} stateProvider The state provider to set
15011 setProvider : function(stateProvider){
15012 provider = stateProvider;
15016 * Returns the current value for a key
15017 * @param {String} name The key name
15018 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
15019 * @return {Mixed} The state data
15021 get : function(key, defaultValue){
15022 return provider.get(key, defaultValue);
15026 * Sets the value for a key
15027 * @param {String} name The key name
15028 * @param {Mixed} value The state data
15030 set : function(key, value){
15031 provider.set(key, value);
15035 * Clears a value from the state
15036 * @param {String} name The key name
15038 clear : function(key){
15039 provider.clear(key);
15043 * Gets the currently configured state provider
15044 * @return {Provider} The state provider
15046 getProvider : function(){
15053 * Ext JS Library 1.1.1
15054 * Copyright(c) 2006-2007, Ext JS, LLC.
15056 * Originally Released Under LGPL - original licence link has changed is not relivant.
15059 * <script type="text/javascript">
15062 * @class Roo.state.CookieProvider
15063 * @extends Roo.state.Provider
15064 * The default Provider implementation which saves state via cookies.
15067 var cp = new Roo.state.CookieProvider({
15069 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
15070 domain: "roojs.com"
15072 Roo.state.Manager.setProvider(cp);
15074 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
15075 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
15076 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
15077 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
15078 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
15079 * domain the page is running on including the 'www' like 'www.roojs.com')
15080 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
15082 * Create a new CookieProvider
15083 * @param {Object} config The configuration object
15085 Roo.state.CookieProvider = function(config){
15086 Roo.state.CookieProvider.superclass.constructor.call(this);
15088 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
15089 this.domain = null;
15090 this.secure = false;
15091 Roo.apply(this, config);
15092 this.state = this.readCookies();
15095 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
15097 set : function(name, value){
15098 if(typeof value == "undefined" || value === null){
15102 this.setCookie(name, value);
15103 Roo.state.CookieProvider.superclass.set.call(this, name, value);
15107 clear : function(name){
15108 this.clearCookie(name);
15109 Roo.state.CookieProvider.superclass.clear.call(this, name);
15113 readCookies : function(){
15115 var c = document.cookie + ";";
15116 var re = /\s?(.*?)=(.*?);/g;
15118 while((matches = re.exec(c)) != null){
15119 var name = matches[1];
15120 var value = matches[2];
15121 if(name && name.substring(0,3) == "ys-"){
15122 cookies[name.substr(3)] = this.decodeValue(value);
15129 setCookie : function(name, value){
15130 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15131 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15132 ((this.path == null) ? "" : ("; path=" + this.path)) +
15133 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15134 ((this.secure == true) ? "; secure" : "");
15138 clearCookie : function(name){
15139 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15140 ((this.path == null) ? "" : ("; path=" + this.path)) +
15141 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15142 ((this.secure == true) ? "; secure" : "");
15146 * Ext JS Library 1.1.1
15147 * Copyright(c) 2006-2007, Ext JS, LLC.
15149 * Originally Released Under LGPL - original licence link has changed is not relivant.
15152 * <script type="text/javascript">
15157 * @class Roo.ComponentMgr
15158 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15161 Roo.ComponentMgr = function(){
15162 var all = new Roo.util.MixedCollection();
15166 * Registers a component.
15167 * @param {Roo.Component} c The component
15169 register : function(c){
15174 * Unregisters a component.
15175 * @param {Roo.Component} c The component
15177 unregister : function(c){
15182 * Returns a component by id
15183 * @param {String} id The component id
15185 get : function(id){
15186 return all.get(id);
15190 * Registers a function that will be called when a specified component is added to ComponentMgr
15191 * @param {String} id The component id
15192 * @param {Funtction} fn The callback function
15193 * @param {Object} scope The scope of the callback
15195 onAvailable : function(id, fn, scope){
15196 all.on("add", function(index, o){
15198 fn.call(scope || o, o);
15199 all.un("add", fn, scope);
15206 * Ext JS Library 1.1.1
15207 * Copyright(c) 2006-2007, Ext JS, LLC.
15209 * Originally Released Under LGPL - original licence link has changed is not relivant.
15212 * <script type="text/javascript">
15216 * @class Roo.Component
15217 * @extends Roo.util.Observable
15218 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15219 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15220 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15221 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15222 * All visual components (widgets) that require rendering into a layout should subclass Component.
15224 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15225 * 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
15226 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15228 Roo.Component = function(config){
15229 config = config || {};
15230 if(config.tagName || config.dom || typeof config == "string"){ // element object
15231 config = {el: config, id: config.id || config};
15233 this.initialConfig = config;
15235 Roo.apply(this, config);
15239 * Fires after the component is disabled.
15240 * @param {Roo.Component} this
15245 * Fires after the component is enabled.
15246 * @param {Roo.Component} this
15250 * @event beforeshow
15251 * Fires before the component is shown. Return false to stop the show.
15252 * @param {Roo.Component} this
15257 * Fires after the component is shown.
15258 * @param {Roo.Component} this
15262 * @event beforehide
15263 * Fires before the component is hidden. Return false to stop the hide.
15264 * @param {Roo.Component} this
15269 * Fires after the component is hidden.
15270 * @param {Roo.Component} this
15274 * @event beforerender
15275 * Fires before the component is rendered. Return false to stop the render.
15276 * @param {Roo.Component} this
15278 beforerender : true,
15281 * Fires after the component is rendered.
15282 * @param {Roo.Component} this
15286 * @event beforedestroy
15287 * Fires before the component is destroyed. Return false to stop the destroy.
15288 * @param {Roo.Component} this
15290 beforedestroy : true,
15293 * Fires after the component is destroyed.
15294 * @param {Roo.Component} this
15299 this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
15301 Roo.ComponentMgr.register(this);
15302 Roo.Component.superclass.constructor.call(this);
15303 this.initComponent();
15304 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15305 this.render(this.renderTo);
15306 delete this.renderTo;
15311 Roo.Component.AUTO_ID = 1000;
15313 Roo.extend(Roo.Component, Roo.util.Observable, {
15315 * @scope Roo.Component.prototype
15317 * true if this component is hidden. Read-only.
15322 * true if this component is disabled. Read-only.
15327 * true if this component has been rendered. Read-only.
15331 /** @cfg {String} disableClass
15332 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15334 disabledClass : "x-item-disabled",
15335 /** @cfg {Boolean} allowDomMove
15336 * Whether the component can move the Dom node when rendering (defaults to true).
15338 allowDomMove : true,
15339 /** @cfg {String} hideMode (display|visibility)
15340 * How this component should hidden. Supported values are
15341 * "visibility" (css visibility), "offsets" (negative offset position) and
15342 * "display" (css display) - defaults to "display".
15344 hideMode: 'display',
15347 ctype : "Roo.Component",
15350 * @cfg {String} actionMode
15351 * which property holds the element that used for hide() / show() / disable() / enable()
15357 getActionEl : function(){
15358 return this[this.actionMode];
15361 initComponent : Roo.emptyFn,
15363 * If this is a lazy rendering component, render it to its container element.
15364 * @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.
15366 render : function(container, position){
15367 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15368 if(!container && this.el){
15369 this.el = Roo.get(this.el);
15370 container = this.el.dom.parentNode;
15371 this.allowDomMove = false;
15373 this.container = Roo.get(container);
15374 this.rendered = true;
15375 if(position !== undefined){
15376 if(typeof position == 'number'){
15377 position = this.container.dom.childNodes[position];
15379 position = Roo.getDom(position);
15382 this.onRender(this.container, position || null);
15384 this.el.addClass(this.cls);
15388 this.el.applyStyles(this.style);
15391 this.fireEvent("render", this);
15392 this.afterRender(this.container);
15404 // default function is not really useful
15405 onRender : function(ct, position){
15407 this.el = Roo.get(this.el);
15408 if(this.allowDomMove !== false){
15409 ct.dom.insertBefore(this.el.dom, position);
15415 getAutoCreate : function(){
15416 var cfg = typeof this.autoCreate == "object" ?
15417 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15418 if(this.id && !cfg.id){
15425 afterRender : Roo.emptyFn,
15428 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15429 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15431 destroy : function(){
15432 if(this.fireEvent("beforedestroy", this) !== false){
15433 this.purgeListeners();
15434 this.beforeDestroy();
15436 this.el.removeAllListeners();
15438 if(this.actionMode == "container"){
15439 this.container.remove();
15443 Roo.ComponentMgr.unregister(this);
15444 this.fireEvent("destroy", this);
15449 beforeDestroy : function(){
15454 onDestroy : function(){
15459 * Returns the underlying {@link Roo.Element}.
15460 * @return {Roo.Element} The element
15462 getEl : function(){
15467 * Returns the id of this component.
15470 getId : function(){
15475 * Try to focus this component.
15476 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15477 * @return {Roo.Component} this
15479 focus : function(selectText){
15482 if(selectText === true){
15483 this.el.dom.select();
15498 * Disable this component.
15499 * @return {Roo.Component} this
15501 disable : function(){
15505 this.disabled = true;
15506 this.fireEvent("disable", this);
15511 onDisable : function(){
15512 this.getActionEl().addClass(this.disabledClass);
15513 this.el.dom.disabled = true;
15517 * Enable this component.
15518 * @return {Roo.Component} this
15520 enable : function(){
15524 this.disabled = false;
15525 this.fireEvent("enable", this);
15530 onEnable : function(){
15531 this.getActionEl().removeClass(this.disabledClass);
15532 this.el.dom.disabled = false;
15536 * Convenience function for setting disabled/enabled by boolean.
15537 * @param {Boolean} disabled
15539 setDisabled : function(disabled){
15540 this[disabled ? "disable" : "enable"]();
15544 * Show this component.
15545 * @return {Roo.Component} this
15548 if(this.fireEvent("beforeshow", this) !== false){
15549 this.hidden = false;
15553 this.fireEvent("show", this);
15559 onShow : function(){
15560 var ae = this.getActionEl();
15561 if(this.hideMode == 'visibility'){
15562 ae.dom.style.visibility = "visible";
15563 }else if(this.hideMode == 'offsets'){
15564 ae.removeClass('x-hidden');
15566 ae.dom.style.display = "";
15571 * Hide this component.
15572 * @return {Roo.Component} this
15575 if(this.fireEvent("beforehide", this) !== false){
15576 this.hidden = true;
15580 this.fireEvent("hide", this);
15586 onHide : function(){
15587 var ae = this.getActionEl();
15588 if(this.hideMode == 'visibility'){
15589 ae.dom.style.visibility = "hidden";
15590 }else if(this.hideMode == 'offsets'){
15591 ae.addClass('x-hidden');
15593 ae.dom.style.display = "none";
15598 * Convenience function to hide or show this component by boolean.
15599 * @param {Boolean} visible True to show, false to hide
15600 * @return {Roo.Component} this
15602 setVisible: function(visible){
15612 * Returns true if this component is visible.
15614 isVisible : function(){
15615 return this.getActionEl().isVisible();
15618 cloneConfig : function(overrides){
15619 overrides = overrides || {};
15620 var id = overrides.id || Roo.id();
15621 var cfg = Roo.applyIf(overrides, this.initialConfig);
15622 cfg.id = id; // prevent dup id
15623 return new this.constructor(cfg);
15627 * Ext JS Library 1.1.1
15628 * Copyright(c) 2006-2007, Ext JS, LLC.
15630 * Originally Released Under LGPL - original licence link has changed is not relivant.
15633 * <script type="text/javascript">
15637 * @class Roo.BoxComponent
15638 * @extends Roo.Component
15639 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15640 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15641 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15642 * layout containers.
15644 * @param {Roo.Element/String/Object} config The configuration options.
15646 Roo.BoxComponent = function(config){
15647 Roo.Component.call(this, config);
15651 * Fires after the component is resized.
15652 * @param {Roo.Component} this
15653 * @param {Number} adjWidth The box-adjusted width that was set
15654 * @param {Number} adjHeight The box-adjusted height that was set
15655 * @param {Number} rawWidth The width that was originally specified
15656 * @param {Number} rawHeight The height that was originally specified
15661 * Fires after the component is moved.
15662 * @param {Roo.Component} this
15663 * @param {Number} x The new x position
15664 * @param {Number} y The new y position
15670 Roo.extend(Roo.BoxComponent, Roo.Component, {
15671 // private, set in afterRender to signify that the component has been rendered
15673 // private, used to defer height settings to subclasses
15674 deferHeight: false,
15675 /** @cfg {Number} width
15676 * width (optional) size of component
15678 /** @cfg {Number} height
15679 * height (optional) size of component
15683 * Sets the width and height of the component. This method fires the resize event. This method can accept
15684 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15685 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15686 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15687 * @return {Roo.BoxComponent} this
15689 setSize : function(w, h){
15690 // support for standard size objects
15691 if(typeof w == 'object'){
15696 if(!this.boxReady){
15702 // prevent recalcs when not needed
15703 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15706 this.lastSize = {width: w, height: h};
15708 var adj = this.adjustSize(w, h);
15709 var aw = adj.width, ah = adj.height;
15710 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15711 var rz = this.getResizeEl();
15712 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15713 rz.setSize(aw, ah);
15714 }else if(!this.deferHeight && ah !== undefined){
15716 }else if(aw !== undefined){
15719 this.onResize(aw, ah, w, h);
15720 this.fireEvent('resize', this, aw, ah, w, h);
15726 * Gets the current size of the component's underlying element.
15727 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15729 getSize : function(){
15730 return this.el.getSize();
15734 * Gets the current XY position of the component's underlying element.
15735 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15736 * @return {Array} The XY position of the element (e.g., [100, 200])
15738 getPosition : function(local){
15739 if(local === true){
15740 return [this.el.getLeft(true), this.el.getTop(true)];
15742 return this.xy || this.el.getXY();
15746 * Gets the current box measurements of the component's underlying element.
15747 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15748 * @returns {Object} box An object in the format {x, y, width, height}
15750 getBox : function(local){
15751 var s = this.el.getSize();
15753 s.x = this.el.getLeft(true);
15754 s.y = this.el.getTop(true);
15756 var xy = this.xy || this.el.getXY();
15764 * Sets the current box measurements of the component's underlying element.
15765 * @param {Object} box An object in the format {x, y, width, height}
15766 * @returns {Roo.BoxComponent} this
15768 updateBox : function(box){
15769 this.setSize(box.width, box.height);
15770 this.setPagePosition(box.x, box.y);
15775 getResizeEl : function(){
15776 return this.resizeEl || this.el;
15780 getPositionEl : function(){
15781 return this.positionEl || this.el;
15785 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15786 * This method fires the move event.
15787 * @param {Number} left The new left
15788 * @param {Number} top The new top
15789 * @returns {Roo.BoxComponent} this
15791 setPosition : function(x, y){
15794 if(!this.boxReady){
15797 var adj = this.adjustPosition(x, y);
15798 var ax = adj.x, ay = adj.y;
15800 var el = this.getPositionEl();
15801 if(ax !== undefined || ay !== undefined){
15802 if(ax !== undefined && ay !== undefined){
15803 el.setLeftTop(ax, ay);
15804 }else if(ax !== undefined){
15806 }else if(ay !== undefined){
15809 this.onPosition(ax, ay);
15810 this.fireEvent('move', this, ax, ay);
15816 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15817 * This method fires the move event.
15818 * @param {Number} x The new x position
15819 * @param {Number} y The new y position
15820 * @returns {Roo.BoxComponent} this
15822 setPagePosition : function(x, y){
15825 if(!this.boxReady){
15828 if(x === undefined || y === undefined){ // cannot translate undefined points
15831 var p = this.el.translatePoints(x, y);
15832 this.setPosition(p.left, p.top);
15837 onRender : function(ct, position){
15838 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15840 this.resizeEl = Roo.get(this.resizeEl);
15842 if(this.positionEl){
15843 this.positionEl = Roo.get(this.positionEl);
15848 afterRender : function(){
15849 Roo.BoxComponent.superclass.afterRender.call(this);
15850 this.boxReady = true;
15851 this.setSize(this.width, this.height);
15852 if(this.x || this.y){
15853 this.setPosition(this.x, this.y);
15855 if(this.pageX || this.pageY){
15856 this.setPagePosition(this.pageX, this.pageY);
15861 * Force the component's size to recalculate based on the underlying element's current height and width.
15862 * @returns {Roo.BoxComponent} this
15864 syncSize : function(){
15865 delete this.lastSize;
15866 this.setSize(this.el.getWidth(), this.el.getHeight());
15871 * Called after the component is resized, this method is empty by default but can be implemented by any
15872 * subclass that needs to perform custom logic after a resize occurs.
15873 * @param {Number} adjWidth The box-adjusted width that was set
15874 * @param {Number} adjHeight The box-adjusted height that was set
15875 * @param {Number} rawWidth The width that was originally specified
15876 * @param {Number} rawHeight The height that was originally specified
15878 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15883 * Called after the component is moved, this method is empty by default but can be implemented by any
15884 * subclass that needs to perform custom logic after a move occurs.
15885 * @param {Number} x The new x position
15886 * @param {Number} y The new y position
15888 onPosition : function(x, y){
15893 adjustSize : function(w, h){
15894 if(this.autoWidth){
15897 if(this.autoHeight){
15900 return {width : w, height: h};
15904 adjustPosition : function(x, y){
15905 return {x : x, y: y};
15908 * Original code for Roojs - LGPL
15909 * <script type="text/javascript">
15913 * @class Roo.XComponent
15914 * A delayed Element creator...
15915 * Or a way to group chunks of interface together.
15916 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15917 * used in conjunction with XComponent.build() it will create an instance of each element,
15918 * then call addxtype() to build the User interface.
15920 * Mypart.xyx = new Roo.XComponent({
15922 parent : 'Mypart.xyz', // empty == document.element.!!
15926 disabled : function() {}
15928 tree : function() { // return an tree of xtype declared components
15932 xtype : 'NestedLayoutPanel',
15939 * It can be used to build a big heiracy, with parent etc.
15940 * or you can just use this to render a single compoent to a dom element
15941 * MYPART.render(Roo.Element | String(id) | dom_element )
15948 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15949 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15951 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15953 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15954 * - if mulitple topModules exist, the last one is defined as the top module.
15958 * When the top level or multiple modules are to embedded into a existing HTML page,
15959 * the parent element can container '#id' of the element where the module will be drawn.
15963 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15964 * it relies more on a include mechanism, where sub modules are included into an outer page.
15965 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15967 * Bootstrap Roo Included elements
15969 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15970 * hence confusing the component builder as it thinks there are multiple top level elements.
15974 * @extends Roo.util.Observable
15976 * @param cfg {Object} configuration of component
15979 Roo.XComponent = function(cfg) {
15980 Roo.apply(this, cfg);
15984 * Fires when this the componnt is built
15985 * @param {Roo.XComponent} c the component
15990 this.region = this.region || 'center'; // default..
15991 Roo.XComponent.register(this);
15992 this.modules = false;
15993 this.el = false; // where the layout goes..
15997 Roo.extend(Roo.XComponent, Roo.util.Observable, {
16000 * The created element (with Roo.factory())
16001 * @type {Roo.Layout}
16007 * for BC - use el in new code
16008 * @type {Roo.Layout}
16014 * for BC - use el in new code
16015 * @type {Roo.Layout}
16020 * @cfg {Function|boolean} disabled
16021 * If this module is disabled by some rule, return true from the funtion
16026 * @cfg {String} parent
16027 * Name of parent element which it get xtype added to..
16032 * @cfg {String} order
16033 * Used to set the order in which elements are created (usefull for multiple tabs)
16038 * @cfg {String} name
16039 * String to display while loading.
16043 * @cfg {String} region
16044 * Region to render component to (defaults to center)
16049 * @cfg {Array} items
16050 * A single item array - the first element is the root of the tree..
16051 * It's done this way to stay compatible with the Xtype system...
16057 * The method that retuns the tree of parts that make up this compoennt
16064 * render element to dom or tree
16065 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
16068 render : function(el)
16072 var hp = this.parent ? 1 : 0;
16073 Roo.debug && Roo.log(this);
16075 var tree = this._tree ? this._tree() : this.tree();
16078 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
16079 // if parent is a '#.....' string, then let's use that..
16080 var ename = this.parent.substr(1);
16081 this.parent = false;
16082 Roo.debug && Roo.log(ename);
16084 case 'bootstrap-body':
16085 if (typeof(tree.el) != 'undefined' && tree.el == document.body) {
16086 // this is the BorderLayout standard?
16087 this.parent = { el : true };
16090 if (["Nest", "Content", "Grid", "Tree"].indexOf(tree.xtype) > -1) {
16091 // need to insert stuff...
16093 el : new Roo.bootstrap.layout.Border({
16094 el : document.body,
16100 tabPosition: 'top',
16101 //resizeTabs: true,
16102 alwaysShowTabs: true,
16112 if (typeof(Roo.bootstrap.Body) != 'undefined' ) {
16113 this.parent = { el : new Roo.bootstrap.Body() };
16114 Roo.debug && Roo.log("setting el to doc body");
16117 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
16121 this.parent = { el : true};
16124 el = Roo.get(ename);
16125 if (typeof(Roo.bootstrap) != 'undefined' && tree['|xns'] == 'Roo.bootstrap') {
16126 this.parent = { el : true};
16133 if (!el && !this.parent) {
16134 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
16139 Roo.debug && Roo.log("EL:");
16140 Roo.debug && Roo.log(el);
16141 Roo.debug && Roo.log("this.parent.el:");
16142 Roo.debug && Roo.log(this.parent.el);
16145 // altertive root elements ??? - we need a better way to indicate these.
16146 var is_alt = Roo.XComponent.is_alt ||
16147 (typeof(tree.el) != 'undefined' && tree.el == document.body) ||
16148 (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
16149 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
16153 if (!this.parent && is_alt) {
16154 //el = Roo.get(document.body);
16155 this.parent = { el : true };
16160 if (!this.parent) {
16162 Roo.debug && Roo.log("no parent - creating one");
16164 el = el ? Roo.get(el) : false;
16166 if (typeof(Roo.BorderLayout) == 'undefined' ) {
16169 el : new Roo.bootstrap.layout.Border({
16170 el: el || document.body,
16176 tabPosition: 'top',
16177 //resizeTabs: true,
16178 alwaysShowTabs: false,
16181 overflow: 'visible'
16187 // it's a top level one..
16189 el : new Roo.BorderLayout(el || document.body, {
16194 tabPosition: 'top',
16195 //resizeTabs: true,
16196 alwaysShowTabs: el && hp? false : true,
16197 hideTabs: el || !hp ? true : false,
16205 if (!this.parent.el) {
16206 // probably an old style ctor, which has been disabled.
16210 // The 'tree' method is '_tree now'
16212 tree.region = tree.region || this.region;
16213 var is_body = false;
16214 if (this.parent.el === true) {
16215 // bootstrap... - body..
16219 this.parent.el = Roo.factory(tree);
16223 this.el = this.parent.el.addxtype(tree, undefined, is_body);
16224 this.fireEvent('built', this);
16226 this.panel = this.el;
16227 this.layout = this.panel.layout;
16228 this.parentLayout = this.parent.layout || false;
16234 Roo.apply(Roo.XComponent, {
16236 * @property hideProgress
16237 * true to disable the building progress bar.. usefull on single page renders.
16240 hideProgress : false,
16242 * @property buildCompleted
16243 * True when the builder has completed building the interface.
16246 buildCompleted : false,
16249 * @property topModule
16250 * the upper most module - uses document.element as it's constructor.
16257 * @property modules
16258 * array of modules to be created by registration system.
16259 * @type {Array} of Roo.XComponent
16264 * @property elmodules
16265 * array of modules to be created by which use #ID
16266 * @type {Array} of Roo.XComponent
16273 * Is an alternative Root - normally used by bootstrap or other systems,
16274 * where the top element in the tree can wrap 'body'
16275 * @type {boolean} (default false)
16280 * @property build_from_html
16281 * Build elements from html - used by bootstrap HTML stuff
16282 * - this is cleared after build is completed
16283 * @type {boolean} (default false)
16286 build_from_html : false,
16288 * Register components to be built later.
16290 * This solves the following issues
16291 * - Building is not done on page load, but after an authentication process has occured.
16292 * - Interface elements are registered on page load
16293 * - Parent Interface elements may not be loaded before child, so this handles that..
16300 module : 'Pman.Tab.projectMgr',
16302 parent : 'Pman.layout',
16303 disabled : false, // or use a function..
16306 * * @param {Object} details about module
16308 register : function(obj) {
16310 Roo.XComponent.event.fireEvent('register', obj);
16311 switch(typeof(obj.disabled) ) {
16317 if ( obj.disabled() ) {
16323 if (obj.disabled) {
16329 this.modules.push(obj);
16333 * convert a string to an object..
16334 * eg. 'AAA.BBB' -> finds AAA.BBB
16338 toObject : function(str)
16340 if (!str || typeof(str) == 'object') {
16343 if (str.substring(0,1) == '#') {
16347 var ar = str.split('.');
16352 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16354 throw "Module not found : " + str;
16358 throw "Module not found : " + str;
16360 Roo.each(ar, function(e) {
16361 if (typeof(o[e]) == 'undefined') {
16362 throw "Module not found : " + str;
16373 * move modules into their correct place in the tree..
16376 preBuild : function ()
16379 Roo.each(this.modules , function (obj)
16381 Roo.XComponent.event.fireEvent('beforebuild', obj);
16383 var opar = obj.parent;
16385 obj.parent = this.toObject(opar);
16387 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16392 Roo.debug && Roo.log("GOT top level module");
16393 Roo.debug && Roo.log(obj);
16394 obj.modules = new Roo.util.MixedCollection(false,
16395 function(o) { return o.order + '' }
16397 this.topModule = obj;
16400 // parent is a string (usually a dom element name..)
16401 if (typeof(obj.parent) == 'string') {
16402 this.elmodules.push(obj);
16405 if (obj.parent.constructor != Roo.XComponent) {
16406 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16408 if (!obj.parent.modules) {
16409 obj.parent.modules = new Roo.util.MixedCollection(false,
16410 function(o) { return o.order + '' }
16413 if (obj.parent.disabled) {
16414 obj.disabled = true;
16416 obj.parent.modules.add(obj);
16421 * make a list of modules to build.
16422 * @return {Array} list of modules.
16425 buildOrder : function()
16428 var cmp = function(a,b) {
16429 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16431 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16432 throw "No top level modules to build";
16435 // make a flat list in order of modules to build.
16436 var mods = this.topModule ? [ this.topModule ] : [];
16439 // elmodules (is a list of DOM based modules )
16440 Roo.each(this.elmodules, function(e) {
16442 if (!this.topModule &&
16443 typeof(e.parent) == 'string' &&
16444 e.parent.substring(0,1) == '#' &&
16445 Roo.get(e.parent.substr(1))
16448 _this.topModule = e;
16454 // add modules to their parents..
16455 var addMod = function(m) {
16456 Roo.debug && Roo.log("build Order: add: " + m.name);
16459 if (m.modules && !m.disabled) {
16460 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16461 m.modules.keySort('ASC', cmp );
16462 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16464 m.modules.each(addMod);
16466 Roo.debug && Roo.log("build Order: no child modules");
16468 // not sure if this is used any more..
16470 m.finalize.name = m.name + " (clean up) ";
16471 mods.push(m.finalize);
16475 if (this.topModule && this.topModule.modules) {
16476 this.topModule.modules.keySort('ASC', cmp );
16477 this.topModule.modules.each(addMod);
16483 * Build the registered modules.
16484 * @param {Object} parent element.
16485 * @param {Function} optional method to call after module has been added.
16489 build : function(opts)
16492 if (typeof(opts) != 'undefined') {
16493 Roo.apply(this,opts);
16497 var mods = this.buildOrder();
16499 //this.allmods = mods;
16500 //Roo.debug && Roo.log(mods);
16502 if (!mods.length) { // should not happen
16503 throw "NO modules!!!";
16507 var msg = "Building Interface...";
16508 // flash it up as modal - so we store the mask!?
16509 if (!this.hideProgress && Roo.MessageBox) {
16510 Roo.MessageBox.show({ title: 'loading' });
16511 Roo.MessageBox.show({
16512 title: "Please wait...",
16521 var total = mods.length;
16524 var progressRun = function() {
16525 if (!mods.length) {
16526 Roo.debug && Roo.log('hide?');
16527 if (!this.hideProgress && Roo.MessageBox) {
16528 Roo.MessageBox.hide();
16530 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16532 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16538 var m = mods.shift();
16541 Roo.debug && Roo.log(m);
16542 // not sure if this is supported any more.. - modules that are are just function
16543 if (typeof(m) == 'function') {
16545 return progressRun.defer(10, _this);
16549 msg = "Building Interface " + (total - mods.length) +
16551 (m.name ? (' - ' + m.name) : '');
16552 Roo.debug && Roo.log(msg);
16553 if (!_this.hideProgress && Roo.MessageBox) {
16554 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16558 // is the module disabled?
16559 var disabled = (typeof(m.disabled) == 'function') ?
16560 m.disabled.call(m.module.disabled) : m.disabled;
16564 return progressRun(); // we do not update the display!
16572 // it's 10 on top level, and 1 on others??? why...
16573 return progressRun.defer(10, _this);
16576 progressRun.defer(1, _this);
16590 * wrapper for event.on - aliased later..
16591 * Typically use to register a event handler for register:
16593 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16602 Roo.XComponent.event = new Roo.util.Observable({
16606 * Fires when an Component is registered,
16607 * set the disable property on the Component to stop registration.
16608 * @param {Roo.XComponent} c the component being registerd.
16613 * @event beforebuild
16614 * Fires before each Component is built
16615 * can be used to apply permissions.
16616 * @param {Roo.XComponent} c the component being registerd.
16619 'beforebuild' : true,
16621 * @event buildcomplete
16622 * Fires on the top level element when all elements have been built
16623 * @param {Roo.XComponent} the top level component.
16625 'buildcomplete' : true
16630 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);
16633 * marked - a markdown parser
16634 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
16635 * https://github.com/chjj/marked
16641 * Roo.Markdown - is a very crude wrapper around marked..
16645 * alert( Roo.Markdown.toHtml("Markdown *rocks*.") );
16647 * Note: move the sample code to the bottom of this
16648 * file before uncommenting it.
16653 Roo.Markdown.toHtml = function(text) {
16655 var c = new Roo.Markdown.marked.setOptions({
16656 renderer: new Roo.Markdown.marked.Renderer(),
16667 text = text.replace(/\\\n/g,' ');
16668 return Roo.Markdown.marked(text);
16673 // Wraps all "globals" so that the only thing
16674 // exposed is makeHtml().
16679 * Block-Level Grammar
16684 code: /^( {4}[^\n]+\n*)+/,
16686 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
16687 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
16689 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
16690 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
16691 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
16692 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
16693 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
16695 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
16699 block.bullet = /(?:[*+-]|\d+\.)/;
16700 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
16701 block.item = replace(block.item, 'gm')
16702 (/bull/g, block.bullet)
16705 block.list = replace(block.list)
16706 (/bull/g, block.bullet)
16707 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
16708 ('def', '\\n+(?=' + block.def.source + ')')
16711 block.blockquote = replace(block.blockquote)
16715 block._tag = '(?!(?:'
16716 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
16717 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
16718 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
16720 block.html = replace(block.html)
16721 ('comment', /<!--[\s\S]*?-->/)
16722 ('closed', /<(tag)[\s\S]+?<\/\1>/)
16723 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
16724 (/tag/g, block._tag)
16727 block.paragraph = replace(block.paragraph)
16729 ('heading', block.heading)
16730 ('lheading', block.lheading)
16731 ('blockquote', block.blockquote)
16732 ('tag', '<' + block._tag)
16737 * Normal Block Grammar
16740 block.normal = merge({}, block);
16743 * GFM Block Grammar
16746 block.gfm = merge({}, block.normal, {
16747 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
16749 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
16752 block.gfm.paragraph = replace(block.paragraph)
16754 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
16755 + block.list.source.replace('\\1', '\\3') + '|')
16759 * GFM + Tables Block Grammar
16762 block.tables = merge({}, block.gfm, {
16763 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
16764 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
16771 function Lexer(options) {
16773 this.tokens.links = {};
16774 this.options = options || marked.defaults;
16775 this.rules = block.normal;
16777 if (this.options.gfm) {
16778 if (this.options.tables) {
16779 this.rules = block.tables;
16781 this.rules = block.gfm;
16787 * Expose Block Rules
16790 Lexer.rules = block;
16793 * Static Lex Method
16796 Lexer.lex = function(src, options) {
16797 var lexer = new Lexer(options);
16798 return lexer.lex(src);
16805 Lexer.prototype.lex = function(src) {
16807 .replace(/\r\n|\r/g, '\n')
16808 .replace(/\t/g, ' ')
16809 .replace(/\u00a0/g, ' ')
16810 .replace(/\u2424/g, '\n');
16812 return this.token(src, true);
16819 Lexer.prototype.token = function(src, top, bq) {
16820 var src = src.replace(/^ +$/gm, '')
16833 if (cap = this.rules.newline.exec(src)) {
16834 src = src.substring(cap[0].length);
16835 if (cap[0].length > 1) {
16843 if (cap = this.rules.code.exec(src)) {
16844 src = src.substring(cap[0].length);
16845 cap = cap[0].replace(/^ {4}/gm, '');
16848 text: !this.options.pedantic
16849 ? cap.replace(/\n+$/, '')
16856 if (cap = this.rules.fences.exec(src)) {
16857 src = src.substring(cap[0].length);
16867 if (cap = this.rules.heading.exec(src)) {
16868 src = src.substring(cap[0].length);
16871 depth: cap[1].length,
16877 // table no leading pipe (gfm)
16878 if (top && (cap = this.rules.nptable.exec(src))) {
16879 src = src.substring(cap[0].length);
16883 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
16884 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
16885 cells: cap[3].replace(/\n$/, '').split('\n')
16888 for (i = 0; i < item.align.length; i++) {
16889 if (/^ *-+: *$/.test(item.align[i])) {
16890 item.align[i] = 'right';
16891 } else if (/^ *:-+: *$/.test(item.align[i])) {
16892 item.align[i] = 'center';
16893 } else if (/^ *:-+ *$/.test(item.align[i])) {
16894 item.align[i] = 'left';
16896 item.align[i] = null;
16900 for (i = 0; i < item.cells.length; i++) {
16901 item.cells[i] = item.cells[i].split(/ *\| */);
16904 this.tokens.push(item);
16910 if (cap = this.rules.lheading.exec(src)) {
16911 src = src.substring(cap[0].length);
16914 depth: cap[2] === '=' ? 1 : 2,
16921 if (cap = this.rules.hr.exec(src)) {
16922 src = src.substring(cap[0].length);
16930 if (cap = this.rules.blockquote.exec(src)) {
16931 src = src.substring(cap[0].length);
16934 type: 'blockquote_start'
16937 cap = cap[0].replace(/^ *> ?/gm, '');
16939 // Pass `top` to keep the current
16940 // "toplevel" state. This is exactly
16941 // how markdown.pl works.
16942 this.token(cap, top, true);
16945 type: 'blockquote_end'
16952 if (cap = this.rules.list.exec(src)) {
16953 src = src.substring(cap[0].length);
16957 type: 'list_start',
16958 ordered: bull.length > 1
16961 // Get each top-level item.
16962 cap = cap[0].match(this.rules.item);
16968 for (; i < l; i++) {
16971 // Remove the list item's bullet
16972 // so it is seen as the next token.
16973 space = item.length;
16974 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
16976 // Outdent whatever the
16977 // list item contains. Hacky.
16978 if (~item.indexOf('\n ')) {
16979 space -= item.length;
16980 item = !this.options.pedantic
16981 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
16982 : item.replace(/^ {1,4}/gm, '');
16985 // Determine whether the next list item belongs here.
16986 // Backpedal if it does not belong in this list.
16987 if (this.options.smartLists && i !== l - 1) {
16988 b = block.bullet.exec(cap[i + 1])[0];
16989 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
16990 src = cap.slice(i + 1).join('\n') + src;
16995 // Determine whether item is loose or not.
16996 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
16997 // for discount behavior.
16998 loose = next || /\n\n(?!\s*$)/.test(item);
17000 next = item.charAt(item.length - 1) === '\n';
17001 if (!loose) { loose = next; }
17006 ? 'loose_item_start'
17007 : 'list_item_start'
17011 this.token(item, false, bq);
17014 type: 'list_item_end'
17026 if (cap = this.rules.html.exec(src)) {
17027 src = src.substring(cap[0].length);
17029 type: this.options.sanitize
17032 pre: !this.options.sanitizer
17033 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
17040 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
17041 src = src.substring(cap[0].length);
17042 this.tokens.links[cap[1].toLowerCase()] = {
17050 if (top && (cap = this.rules.table.exec(src))) {
17051 src = src.substring(cap[0].length);
17055 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
17056 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
17057 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
17060 for (i = 0; i < item.align.length; i++) {
17061 if (/^ *-+: *$/.test(item.align[i])) {
17062 item.align[i] = 'right';
17063 } else if (/^ *:-+: *$/.test(item.align[i])) {
17064 item.align[i] = 'center';
17065 } else if (/^ *:-+ *$/.test(item.align[i])) {
17066 item.align[i] = 'left';
17068 item.align[i] = null;
17072 for (i = 0; i < item.cells.length; i++) {
17073 item.cells[i] = item.cells[i]
17074 .replace(/^ *\| *| *\| *$/g, '')
17078 this.tokens.push(item);
17083 // top-level paragraph
17084 if (top && (cap = this.rules.paragraph.exec(src))) {
17085 src = src.substring(cap[0].length);
17088 text: cap[1].charAt(cap[1].length - 1) === '\n'
17089 ? cap[1].slice(0, -1)
17096 if (cap = this.rules.text.exec(src)) {
17097 // Top-level should never reach here.
17098 src = src.substring(cap[0].length);
17108 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17112 return this.tokens;
17116 * Inline-Level Grammar
17120 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
17121 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
17123 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
17124 link: /^!?\[(inside)\]\(href\)/,
17125 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
17126 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
17127 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
17128 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
17129 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
17130 br: /^ {2,}\n(?!\s*$)/,
17132 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
17135 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
17136 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
17138 inline.link = replace(inline.link)
17139 ('inside', inline._inside)
17140 ('href', inline._href)
17143 inline.reflink = replace(inline.reflink)
17144 ('inside', inline._inside)
17148 * Normal Inline Grammar
17151 inline.normal = merge({}, inline);
17154 * Pedantic Inline Grammar
17157 inline.pedantic = merge({}, inline.normal, {
17158 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
17159 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
17163 * GFM Inline Grammar
17166 inline.gfm = merge({}, inline.normal, {
17167 escape: replace(inline.escape)('])', '~|])')(),
17168 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
17169 del: /^~~(?=\S)([\s\S]*?\S)~~/,
17170 text: replace(inline.text)
17172 ('|', '|https?://|')
17177 * GFM + Line Breaks Inline Grammar
17180 inline.breaks = merge({}, inline.gfm, {
17181 br: replace(inline.br)('{2,}', '*')(),
17182 text: replace(inline.gfm.text)('{2,}', '*')()
17186 * Inline Lexer & Compiler
17189 function InlineLexer(links, options) {
17190 this.options = options || marked.defaults;
17191 this.links = links;
17192 this.rules = inline.normal;
17193 this.renderer = this.options.renderer || new Renderer;
17194 this.renderer.options = this.options;
17198 Error('Tokens array requires a `links` property.');
17201 if (this.options.gfm) {
17202 if (this.options.breaks) {
17203 this.rules = inline.breaks;
17205 this.rules = inline.gfm;
17207 } else if (this.options.pedantic) {
17208 this.rules = inline.pedantic;
17213 * Expose Inline Rules
17216 InlineLexer.rules = inline;
17219 * Static Lexing/Compiling Method
17222 InlineLexer.output = function(src, links, options) {
17223 var inline = new InlineLexer(links, options);
17224 return inline.output(src);
17231 InlineLexer.prototype.output = function(src) {
17240 if (cap = this.rules.escape.exec(src)) {
17241 src = src.substring(cap[0].length);
17247 if (cap = this.rules.autolink.exec(src)) {
17248 src = src.substring(cap[0].length);
17249 if (cap[2] === '@') {
17250 text = cap[1].charAt(6) === ':'
17251 ? this.mangle(cap[1].substring(7))
17252 : this.mangle(cap[1]);
17253 href = this.mangle('mailto:') + text;
17255 text = escape(cap[1]);
17258 out += this.renderer.link(href, null, text);
17263 if (!this.inLink && (cap = this.rules.url.exec(src))) {
17264 src = src.substring(cap[0].length);
17265 text = escape(cap[1]);
17267 out += this.renderer.link(href, null, text);
17272 if (cap = this.rules.tag.exec(src)) {
17273 if (!this.inLink && /^<a /i.test(cap[0])) {
17274 this.inLink = true;
17275 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
17276 this.inLink = false;
17278 src = src.substring(cap[0].length);
17279 out += this.options.sanitize
17280 ? this.options.sanitizer
17281 ? this.options.sanitizer(cap[0])
17288 if (cap = this.rules.link.exec(src)) {
17289 src = src.substring(cap[0].length);
17290 this.inLink = true;
17291 out += this.outputLink(cap, {
17295 this.inLink = false;
17300 if ((cap = this.rules.reflink.exec(src))
17301 || (cap = this.rules.nolink.exec(src))) {
17302 src = src.substring(cap[0].length);
17303 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
17304 link = this.links[link.toLowerCase()];
17305 if (!link || !link.href) {
17306 out += cap[0].charAt(0);
17307 src = cap[0].substring(1) + src;
17310 this.inLink = true;
17311 out += this.outputLink(cap, link);
17312 this.inLink = false;
17317 if (cap = this.rules.strong.exec(src)) {
17318 src = src.substring(cap[0].length);
17319 out += this.renderer.strong(this.output(cap[2] || cap[1]));
17324 if (cap = this.rules.em.exec(src)) {
17325 src = src.substring(cap[0].length);
17326 out += this.renderer.em(this.output(cap[2] || cap[1]));
17331 if (cap = this.rules.code.exec(src)) {
17332 src = src.substring(cap[0].length);
17333 out += this.renderer.codespan(escape(cap[2], true));
17338 if (cap = this.rules.br.exec(src)) {
17339 src = src.substring(cap[0].length);
17340 out += this.renderer.br();
17345 if (cap = this.rules.del.exec(src)) {
17346 src = src.substring(cap[0].length);
17347 out += this.renderer.del(this.output(cap[1]));
17352 if (cap = this.rules.text.exec(src)) {
17353 src = src.substring(cap[0].length);
17354 out += this.renderer.text(escape(this.smartypants(cap[0])));
17360 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17371 InlineLexer.prototype.outputLink = function(cap, link) {
17372 var href = escape(link.href)
17373 , title = link.title ? escape(link.title) : null;
17375 return cap[0].charAt(0) !== '!'
17376 ? this.renderer.link(href, title, this.output(cap[1]))
17377 : this.renderer.image(href, title, escape(cap[1]));
17381 * Smartypants Transformations
17384 InlineLexer.prototype.smartypants = function(text) {
17385 if (!this.options.smartypants) { return text; }
17388 .replace(/---/g, '\u2014')
17390 .replace(/--/g, '\u2013')
17392 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
17393 // closing singles & apostrophes
17394 .replace(/'/g, '\u2019')
17396 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
17398 .replace(/"/g, '\u201d')
17400 .replace(/\.{3}/g, '\u2026');
17407 InlineLexer.prototype.mangle = function(text) {
17408 if (!this.options.mangle) { return text; }
17414 for (; i < l; i++) {
17415 ch = text.charCodeAt(i);
17416 if (Math.random() > 0.5) {
17417 ch = 'x' + ch.toString(16);
17419 out += '&#' + ch + ';';
17429 function Renderer(options) {
17430 this.options = options || {};
17433 Renderer.prototype.code = function(code, lang, escaped) {
17434 if (this.options.highlight) {
17435 var out = this.options.highlight(code, lang);
17436 if (out != null && out !== code) {
17441 // hack!!! - it's already escapeD?
17446 return '<pre><code>'
17447 + (escaped ? code : escape(code, true))
17448 + '\n</code></pre>';
17451 return '<pre><code class="'
17452 + this.options.langPrefix
17453 + escape(lang, true)
17455 + (escaped ? code : escape(code, true))
17456 + '\n</code></pre>\n';
17459 Renderer.prototype.blockquote = function(quote) {
17460 return '<blockquote>\n' + quote + '</blockquote>\n';
17463 Renderer.prototype.html = function(html) {
17467 Renderer.prototype.heading = function(text, level, raw) {
17471 + this.options.headerPrefix
17472 + raw.toLowerCase().replace(/[^\w]+/g, '-')
17480 Renderer.prototype.hr = function() {
17481 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
17484 Renderer.prototype.list = function(body, ordered) {
17485 var type = ordered ? 'ol' : 'ul';
17486 return '<' + type + '>\n' + body + '</' + type + '>\n';
17489 Renderer.prototype.listitem = function(text) {
17490 return '<li>' + text + '</li>\n';
17493 Renderer.prototype.paragraph = function(text) {
17494 return '<p>' + text + '</p>\n';
17497 Renderer.prototype.table = function(header, body) {
17498 return '<table class="table table-striped">\n'
17508 Renderer.prototype.tablerow = function(content) {
17509 return '<tr>\n' + content + '</tr>\n';
17512 Renderer.prototype.tablecell = function(content, flags) {
17513 var type = flags.header ? 'th' : 'td';
17514 var tag = flags.align
17515 ? '<' + type + ' style="text-align:' + flags.align + '">'
17516 : '<' + type + '>';
17517 return tag + content + '</' + type + '>\n';
17520 // span level renderer
17521 Renderer.prototype.strong = function(text) {
17522 return '<strong>' + text + '</strong>';
17525 Renderer.prototype.em = function(text) {
17526 return '<em>' + text + '</em>';
17529 Renderer.prototype.codespan = function(text) {
17530 return '<code>' + text + '</code>';
17533 Renderer.prototype.br = function() {
17534 return this.options.xhtml ? '<br/>' : '<br>';
17537 Renderer.prototype.del = function(text) {
17538 return '<del>' + text + '</del>';
17541 Renderer.prototype.link = function(href, title, text) {
17542 if (this.options.sanitize) {
17544 var prot = decodeURIComponent(unescape(href))
17545 .replace(/[^\w:]/g, '')
17550 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
17554 var out = '<a href="' + href + '"';
17556 out += ' title="' + title + '"';
17558 out += '>' + text + '</a>';
17562 Renderer.prototype.image = function(href, title, text) {
17563 var out = '<img src="' + href + '" alt="' + text + '"';
17565 out += ' title="' + title + '"';
17567 out += this.options.xhtml ? '/>' : '>';
17571 Renderer.prototype.text = function(text) {
17576 * Parsing & Compiling
17579 function Parser(options) {
17582 this.options = options || marked.defaults;
17583 this.options.renderer = this.options.renderer || new Renderer;
17584 this.renderer = this.options.renderer;
17585 this.renderer.options = this.options;
17589 * Static Parse Method
17592 Parser.parse = function(src, options, renderer) {
17593 var parser = new Parser(options, renderer);
17594 return parser.parse(src);
17601 Parser.prototype.parse = function(src) {
17602 this.inline = new InlineLexer(src.links, this.options, this.renderer);
17603 this.tokens = src.reverse();
17606 while (this.next()) {
17617 Parser.prototype.next = function() {
17618 return this.token = this.tokens.pop();
17622 * Preview Next Token
17625 Parser.prototype.peek = function() {
17626 return this.tokens[this.tokens.length - 1] || 0;
17630 * Parse Text Tokens
17633 Parser.prototype.parseText = function() {
17634 var body = this.token.text;
17636 while (this.peek().type === 'text') {
17637 body += '\n' + this.next().text;
17640 return this.inline.output(body);
17644 * Parse Current Token
17647 Parser.prototype.tok = function() {
17648 switch (this.token.type) {
17653 return this.renderer.hr();
17656 return this.renderer.heading(
17657 this.inline.output(this.token.text),
17662 return this.renderer.code(this.token.text,
17664 this.token.escaped);
17677 for (i = 0; i < this.token.header.length; i++) {
17678 flags = { header: true, align: this.token.align[i] };
17679 cell += this.renderer.tablecell(
17680 this.inline.output(this.token.header[i]),
17681 { header: true, align: this.token.align[i] }
17684 header += this.renderer.tablerow(cell);
17686 for (i = 0; i < this.token.cells.length; i++) {
17687 row = this.token.cells[i];
17690 for (j = 0; j < row.length; j++) {
17691 cell += this.renderer.tablecell(
17692 this.inline.output(row[j]),
17693 { header: false, align: this.token.align[j] }
17697 body += this.renderer.tablerow(cell);
17699 return this.renderer.table(header, body);
17701 case 'blockquote_start': {
17704 while (this.next().type !== 'blockquote_end') {
17705 body += this.tok();
17708 return this.renderer.blockquote(body);
17710 case 'list_start': {
17712 , ordered = this.token.ordered;
17714 while (this.next().type !== 'list_end') {
17715 body += this.tok();
17718 return this.renderer.list(body, ordered);
17720 case 'list_item_start': {
17723 while (this.next().type !== 'list_item_end') {
17724 body += this.token.type === 'text'
17729 return this.renderer.listitem(body);
17731 case 'loose_item_start': {
17734 while (this.next().type !== 'list_item_end') {
17735 body += this.tok();
17738 return this.renderer.listitem(body);
17741 var html = !this.token.pre && !this.options.pedantic
17742 ? this.inline.output(this.token.text)
17744 return this.renderer.html(html);
17746 case 'paragraph': {
17747 return this.renderer.paragraph(this.inline.output(this.token.text));
17750 return this.renderer.paragraph(this.parseText());
17759 function escape(html, encode) {
17761 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
17762 .replace(/</g, '<')
17763 .replace(/>/g, '>')
17764 .replace(/"/g, '"')
17765 .replace(/'/g, ''');
17768 function unescape(html) {
17769 // explicitly match decimal, hex, and named HTML entities
17770 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
17771 n = n.toLowerCase();
17772 if (n === 'colon') { return ':'; }
17773 if (n.charAt(0) === '#') {
17774 return n.charAt(1) === 'x'
17775 ? String.fromCharCode(parseInt(n.substring(2), 16))
17776 : String.fromCharCode(+n.substring(1));
17782 function replace(regex, opt) {
17783 regex = regex.source;
17785 return function self(name, val) {
17786 if (!name) { return new RegExp(regex, opt); }
17787 val = val.source || val;
17788 val = val.replace(/(^|[^\[])\^/g, '$1');
17789 regex = regex.replace(name, val);
17797 function merge(obj) {
17802 for (; i < arguments.length; i++) {
17803 target = arguments[i];
17804 for (key in target) {
17805 if (Object.prototype.hasOwnProperty.call(target, key)) {
17806 obj[key] = target[key];
17819 function marked(src, opt, callback) {
17820 if (callback || typeof opt === 'function') {
17826 opt = merge({}, marked.defaults, opt || {});
17828 var highlight = opt.highlight
17834 tokens = Lexer.lex(src, opt)
17836 return callback(e);
17839 pending = tokens.length;
17841 var done = function(err) {
17843 opt.highlight = highlight;
17844 return callback(err);
17850 out = Parser.parse(tokens, opt);
17855 opt.highlight = highlight;
17859 : callback(null, out);
17862 if (!highlight || highlight.length < 3) {
17866 delete opt.highlight;
17868 if (!pending) { return done(); }
17870 for (; i < tokens.length; i++) {
17872 if (token.type !== 'code') {
17873 return --pending || done();
17875 return highlight(token.text, token.lang, function(err, code) {
17876 if (err) { return done(err); }
17877 if (code == null || code === token.text) {
17878 return --pending || done();
17881 token.escaped = true;
17882 --pending || done();
17890 if (opt) { opt = merge({}, marked.defaults, opt); }
17891 return Parser.parse(Lexer.lex(src, opt), opt);
17893 e.message += '\nPlease report this to https://github.com/chjj/marked.';
17894 if ((opt || marked.defaults).silent) {
17895 return '<p>An error occured:</p><pre>'
17896 + escape(e.message + '', true)
17908 marked.setOptions = function(opt) {
17909 merge(marked.defaults, opt);
17913 marked.defaults = {
17924 langPrefix: 'lang-',
17925 smartypants: false,
17927 renderer: new Renderer,
17935 marked.Parser = Parser;
17936 marked.parser = Parser.parse;
17938 marked.Renderer = Renderer;
17940 marked.Lexer = Lexer;
17941 marked.lexer = Lexer.lex;
17943 marked.InlineLexer = InlineLexer;
17944 marked.inlineLexer = InlineLexer.output;
17946 marked.parse = marked;
17948 Roo.Markdown.marked = marked;
17952 * Ext JS Library 1.1.1
17953 * Copyright(c) 2006-2007, Ext JS, LLC.
17955 * Originally Released Under LGPL - original licence link has changed is not relivant.
17958 * <script type="text/javascript">
17964 * These classes are derivatives of the similarly named classes in the YUI Library.
17965 * The original license:
17966 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
17967 * Code licensed under the BSD License:
17968 * http://developer.yahoo.net/yui/license.txt
17973 var Event=Roo.EventManager;
17974 var Dom=Roo.lib.Dom;
17977 * @class Roo.dd.DragDrop
17978 * @extends Roo.util.Observable
17979 * Defines the interface and base operation of items that that can be
17980 * dragged or can be drop targets. It was designed to be extended, overriding
17981 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
17982 * Up to three html elements can be associated with a DragDrop instance:
17984 * <li>linked element: the element that is passed into the constructor.
17985 * This is the element which defines the boundaries for interaction with
17986 * other DragDrop objects.</li>
17987 * <li>handle element(s): The drag operation only occurs if the element that
17988 * was clicked matches a handle element. By default this is the linked
17989 * element, but there are times that you will want only a portion of the
17990 * linked element to initiate the drag operation, and the setHandleElId()
17991 * method provides a way to define this.</li>
17992 * <li>drag element: this represents the element that would be moved along
17993 * with the cursor during a drag operation. By default, this is the linked
17994 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
17995 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
17998 * This class should not be instantiated until the onload event to ensure that
17999 * the associated elements are available.
18000 * The following would define a DragDrop obj that would interact with any
18001 * other DragDrop obj in the "group1" group:
18003 * dd = new Roo.dd.DragDrop("div1", "group1");
18005 * Since none of the event handlers have been implemented, nothing would
18006 * actually happen if you were to run the code above. Normally you would
18007 * override this class or one of the default implementations, but you can
18008 * also override the methods you want on an instance of the class...
18010 * dd.onDragDrop = function(e, id) {
18011 * alert("dd was dropped on " + id);
18015 * @param {String} id of the element that is linked to this instance
18016 * @param {String} sGroup the group of related DragDrop objects
18017 * @param {object} config an object containing configurable attributes
18018 * Valid properties for DragDrop:
18019 * padding, isTarget, maintainOffset, primaryButtonOnly
18021 Roo.dd.DragDrop = function(id, sGroup, config) {
18023 this.init(id, sGroup, config);
18028 Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
18031 * The id of the element associated with this object. This is what we
18032 * refer to as the "linked element" because the size and position of
18033 * this element is used to determine when the drag and drop objects have
18041 * Configuration attributes passed into the constructor
18048 * The id of the element that will be dragged. By default this is same
18049 * as the linked element , but could be changed to another element. Ex:
18051 * @property dragElId
18058 * the id of the element that initiates the drag operation. By default
18059 * this is the linked element, but could be changed to be a child of this
18060 * element. This lets us do things like only starting the drag when the
18061 * header element within the linked html element is clicked.
18062 * @property handleElId
18069 * An associative array of HTML tags that will be ignored if clicked.
18070 * @property invalidHandleTypes
18071 * @type {string: string}
18073 invalidHandleTypes: null,
18076 * An associative array of ids for elements that will be ignored if clicked
18077 * @property invalidHandleIds
18078 * @type {string: string}
18080 invalidHandleIds: null,
18083 * An indexted array of css class names for elements that will be ignored
18085 * @property invalidHandleClasses
18088 invalidHandleClasses: null,
18091 * The linked element's absolute X position at the time the drag was
18093 * @property startPageX
18100 * The linked element's absolute X position at the time the drag was
18102 * @property startPageY
18109 * The group defines a logical collection of DragDrop objects that are
18110 * related. Instances only get events when interacting with other
18111 * DragDrop object in the same group. This lets us define multiple
18112 * groups using a single DragDrop subclass if we want.
18114 * @type {string: string}
18119 * Individual drag/drop instances can be locked. This will prevent
18120 * onmousedown start drag.
18128 * Lock this instance
18131 lock: function() { this.locked = true; },
18134 * Unlock this instace
18137 unlock: function() { this.locked = false; },
18140 * By default, all insances can be a drop target. This can be disabled by
18141 * setting isTarget to false.
18148 * The padding configured for this drag and drop object for calculating
18149 * the drop zone intersection with this object.
18156 * Cached reference to the linked element
18157 * @property _domRef
18163 * Internal typeof flag
18164 * @property __ygDragDrop
18167 __ygDragDrop: true,
18170 * Set to true when horizontal contraints are applied
18171 * @property constrainX
18178 * Set to true when vertical contraints are applied
18179 * @property constrainY
18186 * The left constraint
18194 * The right constraint
18202 * The up constraint
18211 * The down constraint
18219 * Maintain offsets when we resetconstraints. Set to true when you want
18220 * the position of the element relative to its parent to stay the same
18221 * when the page changes
18223 * @property maintainOffset
18226 maintainOffset: false,
18229 * Array of pixel locations the element will snap to if we specified a
18230 * horizontal graduation/interval. This array is generated automatically
18231 * when you define a tick interval.
18238 * Array of pixel locations the element will snap to if we specified a
18239 * vertical graduation/interval. This array is generated automatically
18240 * when you define a tick interval.
18247 * By default the drag and drop instance will only respond to the primary
18248 * button click (left button for a right-handed mouse). Set to true to
18249 * allow drag and drop to start with any mouse click that is propogated
18251 * @property primaryButtonOnly
18254 primaryButtonOnly: true,
18257 * The availabe property is false until the linked dom element is accessible.
18258 * @property available
18264 * By default, drags can only be initiated if the mousedown occurs in the
18265 * region the linked element is. This is done in part to work around a
18266 * bug in some browsers that mis-report the mousedown if the previous
18267 * mouseup happened outside of the window. This property is set to true
18268 * if outer handles are defined.
18270 * @property hasOuterHandles
18274 hasOuterHandles: false,
18277 * Code that executes immediately before the startDrag event
18278 * @method b4StartDrag
18281 b4StartDrag: function(x, y) { },
18284 * Abstract method called after a drag/drop object is clicked
18285 * and the drag or mousedown time thresholds have beeen met.
18286 * @method startDrag
18287 * @param {int} X click location
18288 * @param {int} Y click location
18290 startDrag: function(x, y) { /* override this */ },
18293 * Code that executes immediately before the onDrag event
18297 b4Drag: function(e) { },
18300 * Abstract method called during the onMouseMove event while dragging an
18303 * @param {Event} e the mousemove event
18305 onDrag: function(e) { /* override this */ },
18308 * Abstract method called when this element fist begins hovering over
18309 * another DragDrop obj
18310 * @method onDragEnter
18311 * @param {Event} e the mousemove event
18312 * @param {String|DragDrop[]} id In POINT mode, the element
18313 * id this is hovering over. In INTERSECT mode, an array of one or more
18314 * dragdrop items being hovered over.
18316 onDragEnter: function(e, id) { /* override this */ },
18319 * Code that executes immediately before the onDragOver event
18320 * @method b4DragOver
18323 b4DragOver: function(e) { },
18326 * Abstract method called when this element is hovering over another
18328 * @method onDragOver
18329 * @param {Event} e the mousemove event
18330 * @param {String|DragDrop[]} id In POINT mode, the element
18331 * id this is hovering over. In INTERSECT mode, an array of dd items
18332 * being hovered over.
18334 onDragOver: function(e, id) { /* override this */ },
18337 * Code that executes immediately before the onDragOut event
18338 * @method b4DragOut
18341 b4DragOut: function(e) { },
18344 * Abstract method called when we are no longer hovering over an element
18345 * @method onDragOut
18346 * @param {Event} e the mousemove event
18347 * @param {String|DragDrop[]} id In POINT mode, the element
18348 * id this was hovering over. In INTERSECT mode, an array of dd items
18349 * that the mouse is no longer over.
18351 onDragOut: function(e, id) { /* override this */ },
18354 * Code that executes immediately before the onDragDrop event
18355 * @method b4DragDrop
18358 b4DragDrop: function(e) { },
18361 * Abstract method called when this item is dropped on another DragDrop
18363 * @method onDragDrop
18364 * @param {Event} e the mouseup event
18365 * @param {String|DragDrop[]} id In POINT mode, the element
18366 * id this was dropped on. In INTERSECT mode, an array of dd items this
18369 onDragDrop: function(e, id) { /* override this */ },
18372 * Abstract method called when this item is dropped on an area with no
18374 * @method onInvalidDrop
18375 * @param {Event} e the mouseup event
18377 onInvalidDrop: function(e) { /* override this */ },
18380 * Code that executes immediately before the endDrag event
18381 * @method b4EndDrag
18384 b4EndDrag: function(e) { },
18387 * Fired when we are done dragging the object
18389 * @param {Event} e the mouseup event
18391 endDrag: function(e) { /* override this */ },
18394 * Code executed immediately before the onMouseDown event
18395 * @method b4MouseDown
18396 * @param {Event} e the mousedown event
18399 b4MouseDown: function(e) { },
18402 * Event handler that fires when a drag/drop obj gets a mousedown
18403 * @method onMouseDown
18404 * @param {Event} e the mousedown event
18406 onMouseDown: function(e) { /* override this */ },
18409 * Event handler that fires when a drag/drop obj gets a mouseup
18410 * @method onMouseUp
18411 * @param {Event} e the mouseup event
18413 onMouseUp: function(e) { /* override this */ },
18416 * Override the onAvailable method to do what is needed after the initial
18417 * position was determined.
18418 * @method onAvailable
18420 onAvailable: function () {
18424 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
18427 defaultPadding : {left:0, right:0, top:0, bottom:0},
18430 * Initializes the drag drop object's constraints to restrict movement to a certain element.
18434 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
18435 { dragElId: "existingProxyDiv" });
18436 dd.startDrag = function(){
18437 this.constrainTo("parent-id");
18440 * Or you can initalize it using the {@link Roo.Element} object:
18442 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
18443 startDrag : function(){
18444 this.constrainTo("parent-id");
18448 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
18449 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
18450 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
18451 * an object containing the sides to pad. For example: {right:10, bottom:10}
18452 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
18454 constrainTo : function(constrainTo, pad, inContent){
18455 if(typeof pad == "number"){
18456 pad = {left: pad, right:pad, top:pad, bottom:pad};
18458 pad = pad || this.defaultPadding;
18459 var b = Roo.get(this.getEl()).getBox();
18460 var ce = Roo.get(constrainTo);
18461 var s = ce.getScroll();
18462 var c, cd = ce.dom;
18463 if(cd == document.body){
18464 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
18467 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
18471 var topSpace = b.y - c.y;
18472 var leftSpace = b.x - c.x;
18474 this.resetConstraints();
18475 this.setXConstraint(leftSpace - (pad.left||0), // left
18476 c.width - leftSpace - b.width - (pad.right||0) //right
18478 this.setYConstraint(topSpace - (pad.top||0), //top
18479 c.height - topSpace - b.height - (pad.bottom||0) //bottom
18484 * Returns a reference to the linked element
18486 * @return {HTMLElement} the html element
18488 getEl: function() {
18489 if (!this._domRef) {
18490 this._domRef = Roo.getDom(this.id);
18493 return this._domRef;
18497 * Returns a reference to the actual element to drag. By default this is
18498 * the same as the html element, but it can be assigned to another
18499 * element. An example of this can be found in Roo.dd.DDProxy
18500 * @method getDragEl
18501 * @return {HTMLElement} the html element
18503 getDragEl: function() {
18504 return Roo.getDom(this.dragElId);
18508 * Sets up the DragDrop object. Must be called in the constructor of any
18509 * Roo.dd.DragDrop subclass
18511 * @param id the id of the linked element
18512 * @param {String} sGroup the group of related items
18513 * @param {object} config configuration attributes
18515 init: function(id, sGroup, config) {
18516 this.initTarget(id, sGroup, config);
18517 if (!Roo.isTouch) {
18518 Event.on(this.id, "mousedown", this.handleMouseDown, this);
18520 Event.on(this.id, "touchstart", this.handleMouseDown, this);
18521 // Event.on(this.id, "selectstart", Event.preventDefault);
18525 * Initializes Targeting functionality only... the object does not
18526 * get a mousedown handler.
18527 * @method initTarget
18528 * @param id the id of the linked element
18529 * @param {String} sGroup the group of related items
18530 * @param {object} config configuration attributes
18532 initTarget: function(id, sGroup, config) {
18534 // configuration attributes
18535 this.config = config || {};
18537 // create a local reference to the drag and drop manager
18538 this.DDM = Roo.dd.DDM;
18539 // initialize the groups array
18542 // assume that we have an element reference instead of an id if the
18543 // parameter is not a string
18544 if (typeof id !== "string") {
18551 // add to an interaction group
18552 this.addToGroup((sGroup) ? sGroup : "default");
18554 // We don't want to register this as the handle with the manager
18555 // so we just set the id rather than calling the setter.
18556 this.handleElId = id;
18558 // the linked element is the element that gets dragged by default
18559 this.setDragElId(id);
18561 // by default, clicked anchors will not start drag operations.
18562 this.invalidHandleTypes = { A: "A" };
18563 this.invalidHandleIds = {};
18564 this.invalidHandleClasses = [];
18566 this.applyConfig();
18568 this.handleOnAvailable();
18572 * Applies the configuration parameters that were passed into the constructor.
18573 * This is supposed to happen at each level through the inheritance chain. So
18574 * a DDProxy implentation will execute apply config on DDProxy, DD, and
18575 * DragDrop in order to get all of the parameters that are available in
18577 * @method applyConfig
18579 applyConfig: function() {
18581 // configurable properties:
18582 // padding, isTarget, maintainOffset, primaryButtonOnly
18583 this.padding = this.config.padding || [0, 0, 0, 0];
18584 this.isTarget = (this.config.isTarget !== false);
18585 this.maintainOffset = (this.config.maintainOffset);
18586 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
18591 * Executed when the linked element is available
18592 * @method handleOnAvailable
18595 handleOnAvailable: function() {
18596 this.available = true;
18597 this.resetConstraints();
18598 this.onAvailable();
18602 * Configures the padding for the target zone in px. Effectively expands
18603 * (or reduces) the virtual object size for targeting calculations.
18604 * Supports css-style shorthand; if only one parameter is passed, all sides
18605 * will have that padding, and if only two are passed, the top and bottom
18606 * will have the first param, the left and right the second.
18607 * @method setPadding
18608 * @param {int} iTop Top pad
18609 * @param {int} iRight Right pad
18610 * @param {int} iBot Bot pad
18611 * @param {int} iLeft Left pad
18613 setPadding: function(iTop, iRight, iBot, iLeft) {
18614 // this.padding = [iLeft, iRight, iTop, iBot];
18615 if (!iRight && 0 !== iRight) {
18616 this.padding = [iTop, iTop, iTop, iTop];
18617 } else if (!iBot && 0 !== iBot) {
18618 this.padding = [iTop, iRight, iTop, iRight];
18620 this.padding = [iTop, iRight, iBot, iLeft];
18625 * Stores the initial placement of the linked element.
18626 * @method setInitialPosition
18627 * @param {int} diffX the X offset, default 0
18628 * @param {int} diffY the Y offset, default 0
18630 setInitPosition: function(diffX, diffY) {
18631 var el = this.getEl();
18633 if (!this.DDM.verifyEl(el)) {
18637 var dx = diffX || 0;
18638 var dy = diffY || 0;
18640 var p = Dom.getXY( el );
18642 this.initPageX = p[0] - dx;
18643 this.initPageY = p[1] - dy;
18645 this.lastPageX = p[0];
18646 this.lastPageY = p[1];
18649 this.setStartPosition(p);
18653 * Sets the start position of the element. This is set when the obj
18654 * is initialized, the reset when a drag is started.
18655 * @method setStartPosition
18656 * @param pos current position (from previous lookup)
18659 setStartPosition: function(pos) {
18660 var p = pos || Dom.getXY( this.getEl() );
18661 this.deltaSetXY = null;
18663 this.startPageX = p[0];
18664 this.startPageY = p[1];
18668 * Add this instance to a group of related drag/drop objects. All
18669 * instances belong to at least one group, and can belong to as many
18670 * groups as needed.
18671 * @method addToGroup
18672 * @param sGroup {string} the name of the group
18674 addToGroup: function(sGroup) {
18675 this.groups[sGroup] = true;
18676 this.DDM.regDragDrop(this, sGroup);
18680 * Remove's this instance from the supplied interaction group
18681 * @method removeFromGroup
18682 * @param {string} sGroup The group to drop
18684 removeFromGroup: function(sGroup) {
18685 if (this.groups[sGroup]) {
18686 delete this.groups[sGroup];
18689 this.DDM.removeDDFromGroup(this, sGroup);
18693 * Allows you to specify that an element other than the linked element
18694 * will be moved with the cursor during a drag
18695 * @method setDragElId
18696 * @param id {string} the id of the element that will be used to initiate the drag
18698 setDragElId: function(id) {
18699 this.dragElId = id;
18703 * Allows you to specify a child of the linked element that should be
18704 * used to initiate the drag operation. An example of this would be if
18705 * you have a content div with text and links. Clicking anywhere in the
18706 * content area would normally start the drag operation. Use this method
18707 * to specify that an element inside of the content div is the element
18708 * that starts the drag operation.
18709 * @method setHandleElId
18710 * @param id {string} the id of the element that will be used to
18711 * initiate the drag.
18713 setHandleElId: function(id) {
18714 if (typeof id !== "string") {
18717 this.handleElId = id;
18718 this.DDM.regHandle(this.id, id);
18722 * Allows you to set an element outside of the linked element as a drag
18724 * @method setOuterHandleElId
18725 * @param id the id of the element that will be used to initiate the drag
18727 setOuterHandleElId: function(id) {
18728 if (typeof id !== "string") {
18731 Event.on(id, "mousedown",
18732 this.handleMouseDown, this);
18733 this.setHandleElId(id);
18735 this.hasOuterHandles = true;
18739 * Remove all drag and drop hooks for this element
18742 unreg: function() {
18743 Event.un(this.id, "mousedown",
18744 this.handleMouseDown);
18745 Event.un(this.id, "touchstart",
18746 this.handleMouseDown);
18747 this._domRef = null;
18748 this.DDM._remove(this);
18751 destroy : function(){
18756 * Returns true if this instance is locked, or the drag drop mgr is locked
18757 * (meaning that all drag/drop is disabled on the page.)
18759 * @return {boolean} true if this obj or all drag/drop is locked, else
18762 isLocked: function() {
18763 return (this.DDM.isLocked() || this.locked);
18767 * Fired when this object is clicked
18768 * @method handleMouseDown
18770 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
18773 handleMouseDown: function(e, oDD){
18775 if (!Roo.isTouch && this.primaryButtonOnly && e.button != 0) {
18776 //Roo.log('not touch/ button !=0');
18779 if (e.browserEvent.touches && e.browserEvent.touches.length != 1) {
18780 return; // double touch..
18784 if (this.isLocked()) {
18785 //Roo.log('locked');
18789 this.DDM.refreshCache(this.groups);
18790 // Roo.log([Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e)]);
18791 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
18792 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
18793 //Roo.log('no outer handes or not over target');
18796 // Roo.log('check validator');
18797 if (this.clickValidator(e)) {
18798 // Roo.log('validate success');
18799 // set the initial element position
18800 this.setStartPosition();
18803 this.b4MouseDown(e);
18804 this.onMouseDown(e);
18806 this.DDM.handleMouseDown(e, this);
18808 this.DDM.stopEvent(e);
18816 clickValidator: function(e) {
18817 var target = e.getTarget();
18818 return ( this.isValidHandleChild(target) &&
18819 (this.id == this.handleElId ||
18820 this.DDM.handleWasClicked(target, this.id)) );
18824 * Allows you to specify a tag name that should not start a drag operation
18825 * when clicked. This is designed to facilitate embedding links within a
18826 * drag handle that do something other than start the drag.
18827 * @method addInvalidHandleType
18828 * @param {string} tagName the type of element to exclude
18830 addInvalidHandleType: function(tagName) {
18831 var type = tagName.toUpperCase();
18832 this.invalidHandleTypes[type] = type;
18836 * Lets you to specify an element id for a child of a drag handle
18837 * that should not initiate a drag
18838 * @method addInvalidHandleId
18839 * @param {string} id the element id of the element you wish to ignore
18841 addInvalidHandleId: function(id) {
18842 if (typeof id !== "string") {
18845 this.invalidHandleIds[id] = id;
18849 * Lets you specify a css class of elements that will not initiate a drag
18850 * @method addInvalidHandleClass
18851 * @param {string} cssClass the class of the elements you wish to ignore
18853 addInvalidHandleClass: function(cssClass) {
18854 this.invalidHandleClasses.push(cssClass);
18858 * Unsets an excluded tag name set by addInvalidHandleType
18859 * @method removeInvalidHandleType
18860 * @param {string} tagName the type of element to unexclude
18862 removeInvalidHandleType: function(tagName) {
18863 var type = tagName.toUpperCase();
18864 // this.invalidHandleTypes[type] = null;
18865 delete this.invalidHandleTypes[type];
18869 * Unsets an invalid handle id
18870 * @method removeInvalidHandleId
18871 * @param {string} id the id of the element to re-enable
18873 removeInvalidHandleId: function(id) {
18874 if (typeof id !== "string") {
18877 delete this.invalidHandleIds[id];
18881 * Unsets an invalid css class
18882 * @method removeInvalidHandleClass
18883 * @param {string} cssClass the class of the element(s) you wish to
18886 removeInvalidHandleClass: function(cssClass) {
18887 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
18888 if (this.invalidHandleClasses[i] == cssClass) {
18889 delete this.invalidHandleClasses[i];
18895 * Checks the tag exclusion list to see if this click should be ignored
18896 * @method isValidHandleChild
18897 * @param {HTMLElement} node the HTMLElement to evaluate
18898 * @return {boolean} true if this is a valid tag type, false if not
18900 isValidHandleChild: function(node) {
18903 // var n = (node.nodeName == "#text") ? node.parentNode : node;
18906 nodeName = node.nodeName.toUpperCase();
18908 nodeName = node.nodeName;
18910 valid = valid && !this.invalidHandleTypes[nodeName];
18911 valid = valid && !this.invalidHandleIds[node.id];
18913 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
18914 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
18923 * Create the array of horizontal tick marks if an interval was specified
18924 * in setXConstraint().
18925 * @method setXTicks
18928 setXTicks: function(iStartX, iTickSize) {
18930 this.xTickSize = iTickSize;
18934 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
18936 this.xTicks[this.xTicks.length] = i;
18941 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
18943 this.xTicks[this.xTicks.length] = i;
18948 this.xTicks.sort(this.DDM.numericSort) ;
18952 * Create the array of vertical tick marks if an interval was specified in
18953 * setYConstraint().
18954 * @method setYTicks
18957 setYTicks: function(iStartY, iTickSize) {
18959 this.yTickSize = iTickSize;
18963 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
18965 this.yTicks[this.yTicks.length] = i;
18970 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
18972 this.yTicks[this.yTicks.length] = i;
18977 this.yTicks.sort(this.DDM.numericSort) ;
18981 * By default, the element can be dragged any place on the screen. Use
18982 * this method to limit the horizontal travel of the element. Pass in
18983 * 0,0 for the parameters if you want to lock the drag to the y axis.
18984 * @method setXConstraint
18985 * @param {int} iLeft the number of pixels the element can move to the left
18986 * @param {int} iRight the number of pixels the element can move to the
18988 * @param {int} iTickSize optional parameter for specifying that the
18990 * should move iTickSize pixels at a time.
18992 setXConstraint: function(iLeft, iRight, iTickSize) {
18993 this.leftConstraint = iLeft;
18994 this.rightConstraint = iRight;
18996 this.minX = this.initPageX - iLeft;
18997 this.maxX = this.initPageX + iRight;
18998 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
19000 this.constrainX = true;
19004 * Clears any constraints applied to this instance. Also clears ticks
19005 * since they can't exist independent of a constraint at this time.
19006 * @method clearConstraints
19008 clearConstraints: function() {
19009 this.constrainX = false;
19010 this.constrainY = false;
19015 * Clears any tick interval defined for this instance
19016 * @method clearTicks
19018 clearTicks: function() {
19019 this.xTicks = null;
19020 this.yTicks = null;
19021 this.xTickSize = 0;
19022 this.yTickSize = 0;
19026 * By default, the element can be dragged any place on the screen. Set
19027 * this to limit the vertical travel of the element. Pass in 0,0 for the
19028 * parameters if you want to lock the drag to the x axis.
19029 * @method setYConstraint
19030 * @param {int} iUp the number of pixels the element can move up
19031 * @param {int} iDown the number of pixels the element can move down
19032 * @param {int} iTickSize optional parameter for specifying that the
19033 * element should move iTickSize pixels at a time.
19035 setYConstraint: function(iUp, iDown, iTickSize) {
19036 this.topConstraint = iUp;
19037 this.bottomConstraint = iDown;
19039 this.minY = this.initPageY - iUp;
19040 this.maxY = this.initPageY + iDown;
19041 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
19043 this.constrainY = true;
19048 * resetConstraints must be called if you manually reposition a dd element.
19049 * @method resetConstraints
19050 * @param {boolean} maintainOffset
19052 resetConstraints: function() {
19055 // Maintain offsets if necessary
19056 if (this.initPageX || this.initPageX === 0) {
19057 // figure out how much this thing has moved
19058 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
19059 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
19061 this.setInitPosition(dx, dy);
19063 // This is the first time we have detected the element's position
19065 this.setInitPosition();
19068 if (this.constrainX) {
19069 this.setXConstraint( this.leftConstraint,
19070 this.rightConstraint,
19074 if (this.constrainY) {
19075 this.setYConstraint( this.topConstraint,
19076 this.bottomConstraint,
19082 * Normally the drag element is moved pixel by pixel, but we can specify
19083 * that it move a number of pixels at a time. This method resolves the
19084 * location when we have it set up like this.
19086 * @param {int} val where we want to place the object
19087 * @param {int[]} tickArray sorted array of valid points
19088 * @return {int} the closest tick
19091 getTick: function(val, tickArray) {
19094 // If tick interval is not defined, it is effectively 1 pixel,
19095 // so we return the value passed to us.
19097 } else if (tickArray[0] >= val) {
19098 // The value is lower than the first tick, so we return the first
19100 return tickArray[0];
19102 for (var i=0, len=tickArray.length; i<len; ++i) {
19104 if (tickArray[next] && tickArray[next] >= val) {
19105 var diff1 = val - tickArray[i];
19106 var diff2 = tickArray[next] - val;
19107 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
19111 // The value is larger than the last tick, so we return the last
19113 return tickArray[tickArray.length - 1];
19120 * @return {string} string representation of the dd obj
19122 toString: function() {
19123 return ("DragDrop " + this.id);
19131 * Ext JS Library 1.1.1
19132 * Copyright(c) 2006-2007, Ext JS, LLC.
19134 * Originally Released Under LGPL - original licence link has changed is not relivant.
19137 * <script type="text/javascript">
19142 * The drag and drop utility provides a framework for building drag and drop
19143 * applications. In addition to enabling drag and drop for specific elements,
19144 * the drag and drop elements are tracked by the manager class, and the
19145 * interactions between the various elements are tracked during the drag and
19146 * the implementing code is notified about these important moments.
19149 // Only load the library once. Rewriting the manager class would orphan
19150 // existing drag and drop instances.
19151 if (!Roo.dd.DragDropMgr) {
19154 * @class Roo.dd.DragDropMgr
19155 * DragDropMgr is a singleton that tracks the element interaction for
19156 * all DragDrop items in the window. Generally, you will not call
19157 * this class directly, but it does have helper methods that could
19158 * be useful in your DragDrop implementations.
19161 Roo.dd.DragDropMgr = function() {
19163 var Event = Roo.EventManager;
19168 * Two dimensional Array of registered DragDrop objects. The first
19169 * dimension is the DragDrop item group, the second the DragDrop
19172 * @type {string: string}
19179 * Array of element ids defined as drag handles. Used to determine
19180 * if the element that generated the mousedown event is actually the
19181 * handle and not the html element itself.
19182 * @property handleIds
19183 * @type {string: string}
19190 * the DragDrop object that is currently being dragged
19191 * @property dragCurrent
19199 * the DragDrop object(s) that are being hovered over
19200 * @property dragOvers
19208 * the X distance between the cursor and the object being dragged
19217 * the Y distance between the cursor and the object being dragged
19226 * Flag to determine if we should prevent the default behavior of the
19227 * events we define. By default this is true, but this can be set to
19228 * false if you need the default behavior (not recommended)
19229 * @property preventDefault
19233 preventDefault: true,
19236 * Flag to determine if we should stop the propagation of the events
19237 * we generate. This is true by default but you may want to set it to
19238 * false if the html element contains other features that require the
19240 * @property stopPropagation
19244 stopPropagation: true,
19247 * Internal flag that is set to true when drag and drop has been
19249 * @property initialized
19256 * All drag and drop can be disabled.
19264 * Called the first time an element is registered.
19270 this.initialized = true;
19274 * In point mode, drag and drop interaction is defined by the
19275 * location of the cursor during the drag/drop
19283 * In intersect mode, drag and drop interactio nis defined by the
19284 * overlap of two or more drag and drop objects.
19285 * @property INTERSECT
19292 * The current drag and drop mode. Default: POINT
19300 * Runs method on all drag and drop objects
19301 * @method _execOnAll
19305 _execOnAll: function(sMethod, args) {
19306 for (var i in this.ids) {
19307 for (var j in this.ids[i]) {
19308 var oDD = this.ids[i][j];
19309 if (! this.isTypeOfDD(oDD)) {
19312 oDD[sMethod].apply(oDD, args);
19318 * Drag and drop initialization. Sets up the global event handlers
19323 _onLoad: function() {
19327 if (!Roo.isTouch) {
19328 Event.on(document, "mouseup", this.handleMouseUp, this, true);
19329 Event.on(document, "mousemove", this.handleMouseMove, this, true);
19331 Event.on(document, "touchend", this.handleMouseUp, this, true);
19332 Event.on(document, "touchmove", this.handleMouseMove, this, true);
19334 Event.on(window, "unload", this._onUnload, this, true);
19335 Event.on(window, "resize", this._onResize, this, true);
19336 // Event.on(window, "mouseout", this._test);
19341 * Reset constraints on all drag and drop objs
19342 * @method _onResize
19346 _onResize: function(e) {
19347 this._execOnAll("resetConstraints", []);
19351 * Lock all drag and drop functionality
19355 lock: function() { this.locked = true; },
19358 * Unlock all drag and drop functionality
19362 unlock: function() { this.locked = false; },
19365 * Is drag and drop locked?
19367 * @return {boolean} True if drag and drop is locked, false otherwise.
19370 isLocked: function() { return this.locked; },
19373 * Location cache that is set for all drag drop objects when a drag is
19374 * initiated, cleared when the drag is finished.
19375 * @property locationCache
19382 * Set useCache to false if you want to force object the lookup of each
19383 * drag and drop linked element constantly during a drag.
19384 * @property useCache
19391 * The number of pixels that the mouse needs to move after the
19392 * mousedown before the drag is initiated. Default=3;
19393 * @property clickPixelThresh
19397 clickPixelThresh: 3,
19400 * The number of milliseconds after the mousedown event to initiate the
19401 * drag if we don't get a mouseup event. Default=1000
19402 * @property clickTimeThresh
19406 clickTimeThresh: 350,
19409 * Flag that indicates that either the drag pixel threshold or the
19410 * mousdown time threshold has been met
19411 * @property dragThreshMet
19416 dragThreshMet: false,
19419 * Timeout used for the click time threshold
19420 * @property clickTimeout
19425 clickTimeout: null,
19428 * The X position of the mousedown event stored for later use when a
19429 * drag threshold is met.
19438 * The Y position of the mousedown event stored for later use when a
19439 * drag threshold is met.
19448 * Each DragDrop instance must be registered with the DragDropMgr.
19449 * This is executed in DragDrop.init()
19450 * @method regDragDrop
19451 * @param {DragDrop} oDD the DragDrop object to register
19452 * @param {String} sGroup the name of the group this element belongs to
19455 regDragDrop: function(oDD, sGroup) {
19456 if (!this.initialized) { this.init(); }
19458 if (!this.ids[sGroup]) {
19459 this.ids[sGroup] = {};
19461 this.ids[sGroup][oDD.id] = oDD;
19465 * Removes the supplied dd instance from the supplied group. Executed
19466 * by DragDrop.removeFromGroup, so don't call this function directly.
19467 * @method removeDDFromGroup
19471 removeDDFromGroup: function(oDD, sGroup) {
19472 if (!this.ids[sGroup]) {
19473 this.ids[sGroup] = {};
19476 var obj = this.ids[sGroup];
19477 if (obj && obj[oDD.id]) {
19478 delete obj[oDD.id];
19483 * Unregisters a drag and drop item. This is executed in
19484 * DragDrop.unreg, use that method instead of calling this directly.
19489 _remove: function(oDD) {
19490 for (var g in oDD.groups) {
19491 if (g && this.ids[g][oDD.id]) {
19492 delete this.ids[g][oDD.id];
19495 delete this.handleIds[oDD.id];
19499 * Each DragDrop handle element must be registered. This is done
19500 * automatically when executing DragDrop.setHandleElId()
19501 * @method regHandle
19502 * @param {String} sDDId the DragDrop id this element is a handle for
19503 * @param {String} sHandleId the id of the element that is the drag
19507 regHandle: function(sDDId, sHandleId) {
19508 if (!this.handleIds[sDDId]) {
19509 this.handleIds[sDDId] = {};
19511 this.handleIds[sDDId][sHandleId] = sHandleId;
19515 * Utility function to determine if a given element has been
19516 * registered as a drag drop item.
19517 * @method isDragDrop
19518 * @param {String} id the element id to check
19519 * @return {boolean} true if this element is a DragDrop item,
19523 isDragDrop: function(id) {
19524 return ( this.getDDById(id) ) ? true : false;
19528 * Returns the drag and drop instances that are in all groups the
19529 * passed in instance belongs to.
19530 * @method getRelated
19531 * @param {DragDrop} p_oDD the obj to get related data for
19532 * @param {boolean} bTargetsOnly if true, only return targetable objs
19533 * @return {DragDrop[]} the related instances
19536 getRelated: function(p_oDD, bTargetsOnly) {
19538 for (var i in p_oDD.groups) {
19539 for (j in this.ids[i]) {
19540 var dd = this.ids[i][j];
19541 if (! this.isTypeOfDD(dd)) {
19544 if (!bTargetsOnly || dd.isTarget) {
19545 oDDs[oDDs.length] = dd;
19554 * Returns true if the specified dd target is a legal target for
19555 * the specifice drag obj
19556 * @method isLegalTarget
19557 * @param {DragDrop} the drag obj
19558 * @param {DragDrop} the target
19559 * @return {boolean} true if the target is a legal target for the
19563 isLegalTarget: function (oDD, oTargetDD) {
19564 var targets = this.getRelated(oDD, true);
19565 for (var i=0, len=targets.length;i<len;++i) {
19566 if (targets[i].id == oTargetDD.id) {
19575 * My goal is to be able to transparently determine if an object is
19576 * typeof DragDrop, and the exact subclass of DragDrop. typeof
19577 * returns "object", oDD.constructor.toString() always returns
19578 * "DragDrop" and not the name of the subclass. So for now it just
19579 * evaluates a well-known variable in DragDrop.
19580 * @method isTypeOfDD
19581 * @param {Object} the object to evaluate
19582 * @return {boolean} true if typeof oDD = DragDrop
19585 isTypeOfDD: function (oDD) {
19586 return (oDD && oDD.__ygDragDrop);
19590 * Utility function to determine if a given element has been
19591 * registered as a drag drop handle for the given Drag Drop object.
19593 * @param {String} id the element id to check
19594 * @return {boolean} true if this element is a DragDrop handle, false
19598 isHandle: function(sDDId, sHandleId) {
19599 return ( this.handleIds[sDDId] &&
19600 this.handleIds[sDDId][sHandleId] );
19604 * Returns the DragDrop instance for a given id
19605 * @method getDDById
19606 * @param {String} id the id of the DragDrop object
19607 * @return {DragDrop} the drag drop object, null if it is not found
19610 getDDById: function(id) {
19611 for (var i in this.ids) {
19612 if (this.ids[i][id]) {
19613 return this.ids[i][id];
19620 * Fired after a registered DragDrop object gets the mousedown event.
19621 * Sets up the events required to track the object being dragged
19622 * @method handleMouseDown
19623 * @param {Event} e the event
19624 * @param oDD the DragDrop object being dragged
19628 handleMouseDown: function(e, oDD) {
19630 Roo.QuickTips.disable();
19632 this.currentTarget = e.getTarget();
19634 this.dragCurrent = oDD;
19636 var el = oDD.getEl();
19638 // track start position
19639 this.startX = e.getPageX();
19640 this.startY = e.getPageY();
19642 this.deltaX = this.startX - el.offsetLeft;
19643 this.deltaY = this.startY - el.offsetTop;
19645 this.dragThreshMet = false;
19647 this.clickTimeout = setTimeout(
19649 var DDM = Roo.dd.DDM;
19650 DDM.startDrag(DDM.startX, DDM.startY);
19652 this.clickTimeThresh );
19656 * Fired when either the drag pixel threshol or the mousedown hold
19657 * time threshold has been met.
19658 * @method startDrag
19659 * @param x {int} the X position of the original mousedown
19660 * @param y {int} the Y position of the original mousedown
19663 startDrag: function(x, y) {
19664 clearTimeout(this.clickTimeout);
19665 if (this.dragCurrent) {
19666 this.dragCurrent.b4StartDrag(x, y);
19667 this.dragCurrent.startDrag(x, y);
19669 this.dragThreshMet = true;
19673 * Internal function to handle the mouseup event. Will be invoked
19674 * from the context of the document.
19675 * @method handleMouseUp
19676 * @param {Event} e the event
19680 handleMouseUp: function(e) {
19683 Roo.QuickTips.enable();
19685 if (! this.dragCurrent) {
19689 clearTimeout(this.clickTimeout);
19691 if (this.dragThreshMet) {
19692 this.fireEvents(e, true);
19702 * Utility to stop event propagation and event default, if these
19703 * features are turned on.
19704 * @method stopEvent
19705 * @param {Event} e the event as returned by this.getEvent()
19708 stopEvent: function(e){
19709 if(this.stopPropagation) {
19710 e.stopPropagation();
19713 if (this.preventDefault) {
19714 e.preventDefault();
19719 * Internal function to clean up event handlers after the drag
19720 * operation is complete
19722 * @param {Event} e the event
19726 stopDrag: function(e) {
19727 // Fire the drag end event for the item that was dragged
19728 if (this.dragCurrent) {
19729 if (this.dragThreshMet) {
19730 this.dragCurrent.b4EndDrag(e);
19731 this.dragCurrent.endDrag(e);
19734 this.dragCurrent.onMouseUp(e);
19737 this.dragCurrent = null;
19738 this.dragOvers = {};
19742 * Internal function to handle the mousemove event. Will be invoked
19743 * from the context of the html element.
19745 * @TODO figure out what we can do about mouse events lost when the
19746 * user drags objects beyond the window boundary. Currently we can
19747 * detect this in internet explorer by verifying that the mouse is
19748 * down during the mousemove event. Firefox doesn't give us the
19749 * button state on the mousemove event.
19750 * @method handleMouseMove
19751 * @param {Event} e the event
19755 handleMouseMove: function(e) {
19756 if (! this.dragCurrent) {
19760 // var button = e.which || e.button;
19762 // check for IE mouseup outside of page boundary
19763 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
19765 return this.handleMouseUp(e);
19768 if (!this.dragThreshMet) {
19769 var diffX = Math.abs(this.startX - e.getPageX());
19770 var diffY = Math.abs(this.startY - e.getPageY());
19771 if (diffX > this.clickPixelThresh ||
19772 diffY > this.clickPixelThresh) {
19773 this.startDrag(this.startX, this.startY);
19777 if (this.dragThreshMet) {
19778 this.dragCurrent.b4Drag(e);
19779 this.dragCurrent.onDrag(e);
19780 if(!this.dragCurrent.moveOnly){
19781 this.fireEvents(e, false);
19791 * Iterates over all of the DragDrop elements to find ones we are
19792 * hovering over or dropping on
19793 * @method fireEvents
19794 * @param {Event} e the event
19795 * @param {boolean} isDrop is this a drop op or a mouseover op?
19799 fireEvents: function(e, isDrop) {
19800 var dc = this.dragCurrent;
19802 // If the user did the mouse up outside of the window, we could
19803 // get here even though we have ended the drag.
19804 if (!dc || dc.isLocked()) {
19808 var pt = e.getPoint();
19810 // cache the previous dragOver array
19816 var enterEvts = [];
19818 // Check to see if the object(s) we were hovering over is no longer
19819 // being hovered over so we can fire the onDragOut event
19820 for (var i in this.dragOvers) {
19822 var ddo = this.dragOvers[i];
19824 if (! this.isTypeOfDD(ddo)) {
19828 if (! this.isOverTarget(pt, ddo, this.mode)) {
19829 outEvts.push( ddo );
19832 oldOvers[i] = true;
19833 delete this.dragOvers[i];
19836 for (var sGroup in dc.groups) {
19838 if ("string" != typeof sGroup) {
19842 for (i in this.ids[sGroup]) {
19843 var oDD = this.ids[sGroup][i];
19844 if (! this.isTypeOfDD(oDD)) {
19848 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
19849 if (this.isOverTarget(pt, oDD, this.mode)) {
19850 // look for drop interactions
19852 dropEvts.push( oDD );
19853 // look for drag enter and drag over interactions
19856 // initial drag over: dragEnter fires
19857 if (!oldOvers[oDD.id]) {
19858 enterEvts.push( oDD );
19859 // subsequent drag overs: dragOver fires
19861 overEvts.push( oDD );
19864 this.dragOvers[oDD.id] = oDD;
19872 if (outEvts.length) {
19873 dc.b4DragOut(e, outEvts);
19874 dc.onDragOut(e, outEvts);
19877 if (enterEvts.length) {
19878 dc.onDragEnter(e, enterEvts);
19881 if (overEvts.length) {
19882 dc.b4DragOver(e, overEvts);
19883 dc.onDragOver(e, overEvts);
19886 if (dropEvts.length) {
19887 dc.b4DragDrop(e, dropEvts);
19888 dc.onDragDrop(e, dropEvts);
19892 // fire dragout events
19894 for (i=0, len=outEvts.length; i<len; ++i) {
19895 dc.b4DragOut(e, outEvts[i].id);
19896 dc.onDragOut(e, outEvts[i].id);
19899 // fire enter events
19900 for (i=0,len=enterEvts.length; i<len; ++i) {
19901 // dc.b4DragEnter(e, oDD.id);
19902 dc.onDragEnter(e, enterEvts[i].id);
19905 // fire over events
19906 for (i=0,len=overEvts.length; i<len; ++i) {
19907 dc.b4DragOver(e, overEvts[i].id);
19908 dc.onDragOver(e, overEvts[i].id);
19911 // fire drop events
19912 for (i=0, len=dropEvts.length; i<len; ++i) {
19913 dc.b4DragDrop(e, dropEvts[i].id);
19914 dc.onDragDrop(e, dropEvts[i].id);
19919 // notify about a drop that did not find a target
19920 if (isDrop && !dropEvts.length) {
19921 dc.onInvalidDrop(e);
19927 * Helper function for getting the best match from the list of drag
19928 * and drop objects returned by the drag and drop events when we are
19929 * in INTERSECT mode. It returns either the first object that the
19930 * cursor is over, or the object that has the greatest overlap with
19931 * the dragged element.
19932 * @method getBestMatch
19933 * @param {DragDrop[]} dds The array of drag and drop objects
19935 * @return {DragDrop} The best single match
19938 getBestMatch: function(dds) {
19940 // Return null if the input is not what we expect
19941 //if (!dds || !dds.length || dds.length == 0) {
19943 // If there is only one item, it wins
19944 //} else if (dds.length == 1) {
19946 var len = dds.length;
19951 // Loop through the targeted items
19952 for (var i=0; i<len; ++i) {
19954 // If the cursor is over the object, it wins. If the
19955 // cursor is over multiple matches, the first one we come
19957 if (dd.cursorIsOver) {
19960 // Otherwise the object with the most overlap wins
19963 winner.overlap.getArea() < dd.overlap.getArea()) {
19974 * Refreshes the cache of the top-left and bottom-right points of the
19975 * drag and drop objects in the specified group(s). This is in the
19976 * format that is stored in the drag and drop instance, so typical
19979 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
19983 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
19985 * @TODO this really should be an indexed array. Alternatively this
19986 * method could accept both.
19987 * @method refreshCache
19988 * @param {Object} groups an associative array of groups to refresh
19991 refreshCache: function(groups) {
19992 for (var sGroup in groups) {
19993 if ("string" != typeof sGroup) {
19996 for (var i in this.ids[sGroup]) {
19997 var oDD = this.ids[sGroup][i];
19999 if (this.isTypeOfDD(oDD)) {
20000 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
20001 var loc = this.getLocation(oDD);
20003 this.locationCache[oDD.id] = loc;
20005 delete this.locationCache[oDD.id];
20006 // this will unregister the drag and drop object if
20007 // the element is not in a usable state
20016 * This checks to make sure an element exists and is in the DOM. The
20017 * main purpose is to handle cases where innerHTML is used to remove
20018 * drag and drop objects from the DOM. IE provides an 'unspecified
20019 * error' when trying to access the offsetParent of such an element
20021 * @param {HTMLElement} el the element to check
20022 * @return {boolean} true if the element looks usable
20025 verifyEl: function(el) {
20030 parent = el.offsetParent;
20033 parent = el.offsetParent;
20044 * Returns a Region object containing the drag and drop element's position
20045 * and size, including the padding configured for it
20046 * @method getLocation
20047 * @param {DragDrop} oDD the drag and drop object to get the
20049 * @return {Roo.lib.Region} a Region object representing the total area
20050 * the element occupies, including any padding
20051 * the instance is configured for.
20054 getLocation: function(oDD) {
20055 if (! this.isTypeOfDD(oDD)) {
20059 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
20062 pos= Roo.lib.Dom.getXY(el);
20070 x2 = x1 + el.offsetWidth;
20072 y2 = y1 + el.offsetHeight;
20074 t = y1 - oDD.padding[0];
20075 r = x2 + oDD.padding[1];
20076 b = y2 + oDD.padding[2];
20077 l = x1 - oDD.padding[3];
20079 return new Roo.lib.Region( t, r, b, l );
20083 * Checks the cursor location to see if it over the target
20084 * @method isOverTarget
20085 * @param {Roo.lib.Point} pt The point to evaluate
20086 * @param {DragDrop} oTarget the DragDrop object we are inspecting
20087 * @return {boolean} true if the mouse is over the target
20091 isOverTarget: function(pt, oTarget, intersect) {
20092 // use cache if available
20093 var loc = this.locationCache[oTarget.id];
20094 if (!loc || !this.useCache) {
20095 loc = this.getLocation(oTarget);
20096 this.locationCache[oTarget.id] = loc;
20104 oTarget.cursorIsOver = loc.contains( pt );
20106 // DragDrop is using this as a sanity check for the initial mousedown
20107 // in this case we are done. In POINT mode, if the drag obj has no
20108 // contraints, we are also done. Otherwise we need to evaluate the
20109 // location of the target as related to the actual location of the
20110 // dragged element.
20111 var dc = this.dragCurrent;
20112 if (!dc || !dc.getTargetCoord ||
20113 (!intersect && !dc.constrainX && !dc.constrainY)) {
20114 return oTarget.cursorIsOver;
20117 oTarget.overlap = null;
20119 // Get the current location of the drag element, this is the
20120 // location of the mouse event less the delta that represents
20121 // where the original mousedown happened on the element. We
20122 // need to consider constraints and ticks as well.
20123 var pos = dc.getTargetCoord(pt.x, pt.y);
20125 var el = dc.getDragEl();
20126 var curRegion = new Roo.lib.Region( pos.y,
20127 pos.x + el.offsetWidth,
20128 pos.y + el.offsetHeight,
20131 var overlap = curRegion.intersect(loc);
20134 oTarget.overlap = overlap;
20135 return (intersect) ? true : oTarget.cursorIsOver;
20142 * unload event handler
20143 * @method _onUnload
20147 _onUnload: function(e, me) {
20148 Roo.dd.DragDropMgr.unregAll();
20152 * Cleans up the drag and drop events and objects.
20157 unregAll: function() {
20159 if (this.dragCurrent) {
20161 this.dragCurrent = null;
20164 this._execOnAll("unreg", []);
20166 for (i in this.elementCache) {
20167 delete this.elementCache[i];
20170 this.elementCache = {};
20175 * A cache of DOM elements
20176 * @property elementCache
20183 * Get the wrapper for the DOM element specified
20184 * @method getElWrapper
20185 * @param {String} id the id of the element to get
20186 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
20188 * @deprecated This wrapper isn't that useful
20191 getElWrapper: function(id) {
20192 var oWrapper = this.elementCache[id];
20193 if (!oWrapper || !oWrapper.el) {
20194 oWrapper = this.elementCache[id] =
20195 new this.ElementWrapper(Roo.getDom(id));
20201 * Returns the actual DOM element
20202 * @method getElement
20203 * @param {String} id the id of the elment to get
20204 * @return {Object} The element
20205 * @deprecated use Roo.getDom instead
20208 getElement: function(id) {
20209 return Roo.getDom(id);
20213 * Returns the style property for the DOM element (i.e.,
20214 * document.getElById(id).style)
20216 * @param {String} id the id of the elment to get
20217 * @return {Object} The style property of the element
20218 * @deprecated use Roo.getDom instead
20221 getCss: function(id) {
20222 var el = Roo.getDom(id);
20223 return (el) ? el.style : null;
20227 * Inner class for cached elements
20228 * @class DragDropMgr.ElementWrapper
20233 ElementWrapper: function(el) {
20238 this.el = el || null;
20243 this.id = this.el && el.id;
20245 * A reference to the style property
20248 this.css = this.el && el.style;
20252 * Returns the X position of an html element
20254 * @param el the element for which to get the position
20255 * @return {int} the X coordinate
20257 * @deprecated use Roo.lib.Dom.getX instead
20260 getPosX: function(el) {
20261 return Roo.lib.Dom.getX(el);
20265 * Returns the Y position of an html element
20267 * @param el the element for which to get the position
20268 * @return {int} the Y coordinate
20269 * @deprecated use Roo.lib.Dom.getY instead
20272 getPosY: function(el) {
20273 return Roo.lib.Dom.getY(el);
20277 * Swap two nodes. In IE, we use the native method, for others we
20278 * emulate the IE behavior
20280 * @param n1 the first node to swap
20281 * @param n2 the other node to swap
20284 swapNode: function(n1, n2) {
20288 var p = n2.parentNode;
20289 var s = n2.nextSibling;
20292 p.insertBefore(n1, n2);
20293 } else if (n2 == n1.nextSibling) {
20294 p.insertBefore(n2, n1);
20296 n1.parentNode.replaceChild(n2, n1);
20297 p.insertBefore(n1, s);
20303 * Returns the current scroll position
20304 * @method getScroll
20308 getScroll: function () {
20309 var t, l, dde=document.documentElement, db=document.body;
20310 if (dde && (dde.scrollTop || dde.scrollLeft)) {
20312 l = dde.scrollLeft;
20319 return { top: t, left: l };
20323 * Returns the specified element style property
20325 * @param {HTMLElement} el the element
20326 * @param {string} styleProp the style property
20327 * @return {string} The value of the style property
20328 * @deprecated use Roo.lib.Dom.getStyle
20331 getStyle: function(el, styleProp) {
20332 return Roo.fly(el).getStyle(styleProp);
20336 * Gets the scrollTop
20337 * @method getScrollTop
20338 * @return {int} the document's scrollTop
20341 getScrollTop: function () { return this.getScroll().top; },
20344 * Gets the scrollLeft
20345 * @method getScrollLeft
20346 * @return {int} the document's scrollTop
20349 getScrollLeft: function () { return this.getScroll().left; },
20352 * Sets the x/y position of an element to the location of the
20355 * @param {HTMLElement} moveEl The element to move
20356 * @param {HTMLElement} targetEl The position reference element
20359 moveToEl: function (moveEl, targetEl) {
20360 var aCoord = Roo.lib.Dom.getXY(targetEl);
20361 Roo.lib.Dom.setXY(moveEl, aCoord);
20365 * Numeric array sort function
20366 * @method numericSort
20369 numericSort: function(a, b) { return (a - b); },
20373 * @property _timeoutCount
20380 * Trying to make the load order less important. Without this we get
20381 * an error if this file is loaded before the Event Utility.
20382 * @method _addListeners
20386 _addListeners: function() {
20387 var DDM = Roo.dd.DDM;
20388 if ( Roo.lib.Event && document ) {
20391 if (DDM._timeoutCount > 2000) {
20393 setTimeout(DDM._addListeners, 10);
20394 if (document && document.body) {
20395 DDM._timeoutCount += 1;
20402 * Recursively searches the immediate parent and all child nodes for
20403 * the handle element in order to determine wheter or not it was
20405 * @method handleWasClicked
20406 * @param node the html element to inspect
20409 handleWasClicked: function(node, id) {
20410 if (this.isHandle(id, node.id)) {
20413 // check to see if this is a text node child of the one we want
20414 var p = node.parentNode;
20417 if (this.isHandle(id, p.id)) {
20432 // shorter alias, save a few bytes
20433 Roo.dd.DDM = Roo.dd.DragDropMgr;
20434 Roo.dd.DDM._addListeners();
20438 * Ext JS Library 1.1.1
20439 * Copyright(c) 2006-2007, Ext JS, LLC.
20441 * Originally Released Under LGPL - original licence link has changed is not relivant.
20444 * <script type="text/javascript">
20449 * A DragDrop implementation where the linked element follows the
20450 * mouse cursor during a drag.
20451 * @extends Roo.dd.DragDrop
20453 * @param {String} id the id of the linked element
20454 * @param {String} sGroup the group of related DragDrop items
20455 * @param {object} config an object containing configurable attributes
20456 * Valid properties for DD:
20459 Roo.dd.DD = function(id, sGroup, config) {
20461 this.init(id, sGroup, config);
20465 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
20468 * When set to true, the utility automatically tries to scroll the browser
20469 * window wehn a drag and drop element is dragged near the viewport boundary.
20470 * Defaults to true.
20477 * Sets the pointer offset to the distance between the linked element's top
20478 * left corner and the location the element was clicked
20479 * @method autoOffset
20480 * @param {int} iPageX the X coordinate of the click
20481 * @param {int} iPageY the Y coordinate of the click
20483 autoOffset: function(iPageX, iPageY) {
20484 var x = iPageX - this.startPageX;
20485 var y = iPageY - this.startPageY;
20486 this.setDelta(x, y);
20490 * Sets the pointer offset. You can call this directly to force the
20491 * offset to be in a particular location (e.g., pass in 0,0 to set it
20492 * to the center of the object)
20494 * @param {int} iDeltaX the distance from the left
20495 * @param {int} iDeltaY the distance from the top
20497 setDelta: function(iDeltaX, iDeltaY) {
20498 this.deltaX = iDeltaX;
20499 this.deltaY = iDeltaY;
20503 * Sets the drag element to the location of the mousedown or click event,
20504 * maintaining the cursor location relative to the location on the element
20505 * that was clicked. Override this if you want to place the element in a
20506 * location other than where the cursor is.
20507 * @method setDragElPos
20508 * @param {int} iPageX the X coordinate of the mousedown or drag event
20509 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20511 setDragElPos: function(iPageX, iPageY) {
20512 // the first time we do this, we are going to check to make sure
20513 // the element has css positioning
20515 var el = this.getDragEl();
20516 this.alignElWithMouse(el, iPageX, iPageY);
20520 * Sets the element to the location of the mousedown or click event,
20521 * maintaining the cursor location relative to the location on the element
20522 * that was clicked. Override this if you want to place the element in a
20523 * location other than where the cursor is.
20524 * @method alignElWithMouse
20525 * @param {HTMLElement} el the element to move
20526 * @param {int} iPageX the X coordinate of the mousedown or drag event
20527 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20529 alignElWithMouse: function(el, iPageX, iPageY) {
20530 var oCoord = this.getTargetCoord(iPageX, iPageY);
20531 var fly = el.dom ? el : Roo.fly(el);
20532 if (!this.deltaSetXY) {
20533 var aCoord = [oCoord.x, oCoord.y];
20535 var newLeft = fly.getLeft(true);
20536 var newTop = fly.getTop(true);
20537 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
20539 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
20542 this.cachePosition(oCoord.x, oCoord.y);
20543 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
20548 * Saves the most recent position so that we can reset the constraints and
20549 * tick marks on-demand. We need to know this so that we can calculate the
20550 * number of pixels the element is offset from its original position.
20551 * @method cachePosition
20552 * @param iPageX the current x position (optional, this just makes it so we
20553 * don't have to look it up again)
20554 * @param iPageY the current y position (optional, this just makes it so we
20555 * don't have to look it up again)
20557 cachePosition: function(iPageX, iPageY) {
20559 this.lastPageX = iPageX;
20560 this.lastPageY = iPageY;
20562 var aCoord = Roo.lib.Dom.getXY(this.getEl());
20563 this.lastPageX = aCoord[0];
20564 this.lastPageY = aCoord[1];
20569 * Auto-scroll the window if the dragged object has been moved beyond the
20570 * visible window boundary.
20571 * @method autoScroll
20572 * @param {int} x the drag element's x position
20573 * @param {int} y the drag element's y position
20574 * @param {int} h the height of the drag element
20575 * @param {int} w the width of the drag element
20578 autoScroll: function(x, y, h, w) {
20581 // The client height
20582 var clientH = Roo.lib.Dom.getViewWidth();
20584 // The client width
20585 var clientW = Roo.lib.Dom.getViewHeight();
20587 // The amt scrolled down
20588 var st = this.DDM.getScrollTop();
20590 // The amt scrolled right
20591 var sl = this.DDM.getScrollLeft();
20593 // Location of the bottom of the element
20596 // Location of the right of the element
20599 // The distance from the cursor to the bottom of the visible area,
20600 // adjusted so that we don't scroll if the cursor is beyond the
20601 // element drag constraints
20602 var toBot = (clientH + st - y - this.deltaY);
20604 // The distance from the cursor to the right of the visible area
20605 var toRight = (clientW + sl - x - this.deltaX);
20608 // How close to the edge the cursor must be before we scroll
20609 // var thresh = (document.all) ? 100 : 40;
20612 // How many pixels to scroll per autoscroll op. This helps to reduce
20613 // clunky scrolling. IE is more sensitive about this ... it needs this
20614 // value to be higher.
20615 var scrAmt = (document.all) ? 80 : 30;
20617 // Scroll down if we are near the bottom of the visible page and the
20618 // obj extends below the crease
20619 if ( bot > clientH && toBot < thresh ) {
20620 window.scrollTo(sl, st + scrAmt);
20623 // Scroll up if the window is scrolled down and the top of the object
20624 // goes above the top border
20625 if ( y < st && st > 0 && y - st < thresh ) {
20626 window.scrollTo(sl, st - scrAmt);
20629 // Scroll right if the obj is beyond the right border and the cursor is
20630 // near the border.
20631 if ( right > clientW && toRight < thresh ) {
20632 window.scrollTo(sl + scrAmt, st);
20635 // Scroll left if the window has been scrolled to the right and the obj
20636 // extends past the left border
20637 if ( x < sl && sl > 0 && x - sl < thresh ) {
20638 window.scrollTo(sl - scrAmt, st);
20644 * Finds the location the element should be placed if we want to move
20645 * it to where the mouse location less the click offset would place us.
20646 * @method getTargetCoord
20647 * @param {int} iPageX the X coordinate of the click
20648 * @param {int} iPageY the Y coordinate of the click
20649 * @return an object that contains the coordinates (Object.x and Object.y)
20652 getTargetCoord: function(iPageX, iPageY) {
20655 var x = iPageX - this.deltaX;
20656 var y = iPageY - this.deltaY;
20658 if (this.constrainX) {
20659 if (x < this.minX) { x = this.minX; }
20660 if (x > this.maxX) { x = this.maxX; }
20663 if (this.constrainY) {
20664 if (y < this.minY) { y = this.minY; }
20665 if (y > this.maxY) { y = this.maxY; }
20668 x = this.getTick(x, this.xTicks);
20669 y = this.getTick(y, this.yTicks);
20676 * Sets up config options specific to this class. Overrides
20677 * Roo.dd.DragDrop, but all versions of this method through the
20678 * inheritance chain are called
20680 applyConfig: function() {
20681 Roo.dd.DD.superclass.applyConfig.call(this);
20682 this.scroll = (this.config.scroll !== false);
20686 * Event that fires prior to the onMouseDown event. Overrides
20689 b4MouseDown: function(e) {
20690 // this.resetConstraints();
20691 this.autoOffset(e.getPageX(),
20696 * Event that fires prior to the onDrag event. Overrides
20699 b4Drag: function(e) {
20700 this.setDragElPos(e.getPageX(),
20704 toString: function() {
20705 return ("DD " + this.id);
20708 //////////////////////////////////////////////////////////////////////////
20709 // Debugging ygDragDrop events that can be overridden
20710 //////////////////////////////////////////////////////////////////////////
20712 startDrag: function(x, y) {
20715 onDrag: function(e) {
20718 onDragEnter: function(e, id) {
20721 onDragOver: function(e, id) {
20724 onDragOut: function(e, id) {
20727 onDragDrop: function(e, id) {
20730 endDrag: function(e) {
20737 * Ext JS Library 1.1.1
20738 * Copyright(c) 2006-2007, Ext JS, LLC.
20740 * Originally Released Under LGPL - original licence link has changed is not relivant.
20743 * <script type="text/javascript">
20747 * @class Roo.dd.DDProxy
20748 * A DragDrop implementation that inserts an empty, bordered div into
20749 * the document that follows the cursor during drag operations. At the time of
20750 * the click, the frame div is resized to the dimensions of the linked html
20751 * element, and moved to the exact location of the linked element.
20753 * References to the "frame" element refer to the single proxy element that
20754 * was created to be dragged in place of all DDProxy elements on the
20757 * @extends Roo.dd.DD
20759 * @param {String} id the id of the linked html element
20760 * @param {String} sGroup the group of related DragDrop objects
20761 * @param {object} config an object containing configurable attributes
20762 * Valid properties for DDProxy in addition to those in DragDrop:
20763 * resizeFrame, centerFrame, dragElId
20765 Roo.dd.DDProxy = function(id, sGroup, config) {
20767 this.init(id, sGroup, config);
20773 * The default drag frame div id
20774 * @property Roo.dd.DDProxy.dragElId
20778 Roo.dd.DDProxy.dragElId = "ygddfdiv";
20780 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
20783 * By default we resize the drag frame to be the same size as the element
20784 * we want to drag (this is to get the frame effect). We can turn it off
20785 * if we want a different behavior.
20786 * @property resizeFrame
20792 * By default the frame is positioned exactly where the drag element is, so
20793 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
20794 * you do not have constraints on the obj is to have the drag frame centered
20795 * around the cursor. Set centerFrame to true for this effect.
20796 * @property centerFrame
20799 centerFrame: false,
20802 * Creates the proxy element if it does not yet exist
20803 * @method createFrame
20805 createFrame: function() {
20807 var body = document.body;
20809 if (!body || !body.firstChild) {
20810 setTimeout( function() { self.createFrame(); }, 50 );
20814 var div = this.getDragEl();
20817 div = document.createElement("div");
20818 div.id = this.dragElId;
20821 s.position = "absolute";
20822 s.visibility = "hidden";
20824 s.border = "2px solid #aaa";
20827 // appendChild can blow up IE if invoked prior to the window load event
20828 // while rendering a table. It is possible there are other scenarios
20829 // that would cause this to happen as well.
20830 body.insertBefore(div, body.firstChild);
20835 * Initialization for the drag frame element. Must be called in the
20836 * constructor of all subclasses
20837 * @method initFrame
20839 initFrame: function() {
20840 this.createFrame();
20843 applyConfig: function() {
20844 Roo.dd.DDProxy.superclass.applyConfig.call(this);
20846 this.resizeFrame = (this.config.resizeFrame !== false);
20847 this.centerFrame = (this.config.centerFrame);
20848 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
20852 * Resizes the drag frame to the dimensions of the clicked object, positions
20853 * it over the object, and finally displays it
20854 * @method showFrame
20855 * @param {int} iPageX X click position
20856 * @param {int} iPageY Y click position
20859 showFrame: function(iPageX, iPageY) {
20860 var el = this.getEl();
20861 var dragEl = this.getDragEl();
20862 var s = dragEl.style;
20864 this._resizeProxy();
20866 if (this.centerFrame) {
20867 this.setDelta( Math.round(parseInt(s.width, 10)/2),
20868 Math.round(parseInt(s.height, 10)/2) );
20871 this.setDragElPos(iPageX, iPageY);
20873 Roo.fly(dragEl).show();
20877 * The proxy is automatically resized to the dimensions of the linked
20878 * element when a drag is initiated, unless resizeFrame is set to false
20879 * @method _resizeProxy
20882 _resizeProxy: function() {
20883 if (this.resizeFrame) {
20884 var el = this.getEl();
20885 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
20889 // overrides Roo.dd.DragDrop
20890 b4MouseDown: function(e) {
20891 var x = e.getPageX();
20892 var y = e.getPageY();
20893 this.autoOffset(x, y);
20894 this.setDragElPos(x, y);
20897 // overrides Roo.dd.DragDrop
20898 b4StartDrag: function(x, y) {
20899 // show the drag frame
20900 this.showFrame(x, y);
20903 // overrides Roo.dd.DragDrop
20904 b4EndDrag: function(e) {
20905 Roo.fly(this.getDragEl()).hide();
20908 // overrides Roo.dd.DragDrop
20909 // By default we try to move the element to the last location of the frame.
20910 // This is so that the default behavior mirrors that of Roo.dd.DD.
20911 endDrag: function(e) {
20913 var lel = this.getEl();
20914 var del = this.getDragEl();
20916 // Show the drag frame briefly so we can get its position
20917 del.style.visibility = "";
20920 // Hide the linked element before the move to get around a Safari
20922 lel.style.visibility = "hidden";
20923 Roo.dd.DDM.moveToEl(lel, del);
20924 del.style.visibility = "hidden";
20925 lel.style.visibility = "";
20930 beforeMove : function(){
20934 afterDrag : function(){
20938 toString: function() {
20939 return ("DDProxy " + this.id);
20945 * Ext JS Library 1.1.1
20946 * Copyright(c) 2006-2007, Ext JS, LLC.
20948 * Originally Released Under LGPL - original licence link has changed is not relivant.
20951 * <script type="text/javascript">
20955 * @class Roo.dd.DDTarget
20956 * A DragDrop implementation that does not move, but can be a drop
20957 * target. You would get the same result by simply omitting implementation
20958 * for the event callbacks, but this way we reduce the processing cost of the
20959 * event listener and the callbacks.
20960 * @extends Roo.dd.DragDrop
20962 * @param {String} id the id of the element that is a drop target
20963 * @param {String} sGroup the group of related DragDrop objects
20964 * @param {object} config an object containing configurable attributes
20965 * Valid properties for DDTarget in addition to those in
20969 Roo.dd.DDTarget = function(id, sGroup, config) {
20971 this.initTarget(id, sGroup, config);
20973 if (config.listeners || config.events) {
20974 Roo.dd.DragDrop.superclass.constructor.call(this, {
20975 listeners : config.listeners || {},
20976 events : config.events || {}
20981 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
20982 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
20983 toString: function() {
20984 return ("DDTarget " + this.id);
20989 * Ext JS Library 1.1.1
20990 * Copyright(c) 2006-2007, Ext JS, LLC.
20992 * Originally Released Under LGPL - original licence link has changed is not relivant.
20995 * <script type="text/javascript">
21000 * @class Roo.dd.ScrollManager
21001 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
21002 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
21005 Roo.dd.ScrollManager = function(){
21006 var ddm = Roo.dd.DragDropMgr;
21013 var onStop = function(e){
21018 var triggerRefresh = function(){
21019 if(ddm.dragCurrent){
21020 ddm.refreshCache(ddm.dragCurrent.groups);
21024 var doScroll = function(){
21025 if(ddm.dragCurrent){
21026 var dds = Roo.dd.ScrollManager;
21028 if(proc.el.scroll(proc.dir, dds.increment)){
21032 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
21037 var clearProc = function(){
21039 clearInterval(proc.id);
21046 var startProc = function(el, dir){
21047 Roo.log('scroll startproc');
21051 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
21054 var onFire = function(e, isDrop){
21056 if(isDrop || !ddm.dragCurrent){ return; }
21057 var dds = Roo.dd.ScrollManager;
21058 if(!dragEl || dragEl != ddm.dragCurrent){
21059 dragEl = ddm.dragCurrent;
21060 // refresh regions on drag start
21061 dds.refreshCache();
21064 var xy = Roo.lib.Event.getXY(e);
21065 var pt = new Roo.lib.Point(xy[0], xy[1]);
21066 for(var id in els){
21067 var el = els[id], r = el._region;
21068 if(r && r.contains(pt) && el.isScrollable()){
21069 if(r.bottom - pt.y <= dds.thresh){
21071 startProc(el, "down");
21074 }else if(r.right - pt.x <= dds.thresh){
21076 startProc(el, "left");
21079 }else if(pt.y - r.top <= dds.thresh){
21081 startProc(el, "up");
21084 }else if(pt.x - r.left <= dds.thresh){
21086 startProc(el, "right");
21095 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
21096 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
21100 * Registers new overflow element(s) to auto scroll
21101 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
21103 register : function(el){
21104 if(el instanceof Array){
21105 for(var i = 0, len = el.length; i < len; i++) {
21106 this.register(el[i]);
21112 Roo.dd.ScrollManager.els = els;
21116 * Unregisters overflow element(s) so they are no longer scrolled
21117 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
21119 unregister : function(el){
21120 if(el instanceof Array){
21121 for(var i = 0, len = el.length; i < len; i++) {
21122 this.unregister(el[i]);
21131 * The number of pixels from the edge of a container the pointer needs to be to
21132 * trigger scrolling (defaults to 25)
21138 * The number of pixels to scroll in each scroll increment (defaults to 50)
21144 * The frequency of scrolls in milliseconds (defaults to 500)
21150 * True to animate the scroll (defaults to true)
21156 * The animation duration in seconds -
21157 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
21163 * Manually trigger a cache refresh.
21165 refreshCache : function(){
21166 for(var id in els){
21167 if(typeof els[id] == 'object'){ // for people extending the object prototype
21168 els[id]._region = els[id].getRegion();
21175 * Ext JS Library 1.1.1
21176 * Copyright(c) 2006-2007, Ext JS, LLC.
21178 * Originally Released Under LGPL - original licence link has changed is not relivant.
21181 * <script type="text/javascript">
21186 * @class Roo.dd.Registry
21187 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
21188 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
21191 Roo.dd.Registry = function(){
21194 var autoIdSeed = 0;
21196 var getId = function(el, autogen){
21197 if(typeof el == "string"){
21201 if(!id && autogen !== false){
21202 id = "roodd-" + (++autoIdSeed);
21210 * Register a drag drop element
21211 * @param {String|HTMLElement} element The id or DOM node to register
21212 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
21213 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
21214 * knows how to interpret, plus there are some specific properties known to the Registry that should be
21215 * populated in the data object (if applicable):
21217 Value Description<br />
21218 --------- ------------------------------------------<br />
21219 handles Array of DOM nodes that trigger dragging<br />
21220 for the element being registered<br />
21221 isHandle True if the element passed in triggers<br />
21222 dragging itself, else false
21225 register : function(el, data){
21227 if(typeof el == "string"){
21228 el = document.getElementById(el);
21231 elements[getId(el)] = data;
21232 if(data.isHandle !== false){
21233 handles[data.ddel.id] = data;
21236 var hs = data.handles;
21237 for(var i = 0, len = hs.length; i < len; i++){
21238 handles[getId(hs[i])] = data;
21244 * Unregister a drag drop element
21245 * @param {String|HTMLElement} element The id or DOM node to unregister
21247 unregister : function(el){
21248 var id = getId(el, false);
21249 var data = elements[id];
21251 delete elements[id];
21253 var hs = data.handles;
21254 for(var i = 0, len = hs.length; i < len; i++){
21255 delete handles[getId(hs[i], false)];
21262 * Returns the handle registered for a DOM Node by id
21263 * @param {String|HTMLElement} id The DOM node or id to look up
21264 * @return {Object} handle The custom handle data
21266 getHandle : function(id){
21267 if(typeof id != "string"){ // must be element?
21270 return handles[id];
21274 * Returns the handle that is registered for the DOM node that is the target of the event
21275 * @param {Event} e The event
21276 * @return {Object} handle The custom handle data
21278 getHandleFromEvent : function(e){
21279 var t = Roo.lib.Event.getTarget(e);
21280 return t ? handles[t.id] : null;
21284 * Returns a custom data object that is registered for a DOM node by id
21285 * @param {String|HTMLElement} id The DOM node or id to look up
21286 * @return {Object} data The custom data
21288 getTarget : function(id){
21289 if(typeof id != "string"){ // must be element?
21292 return elements[id];
21296 * Returns a custom data object that is registered for the DOM node that is the target of the event
21297 * @param {Event} e The event
21298 * @return {Object} data The custom data
21300 getTargetFromEvent : function(e){
21301 var t = Roo.lib.Event.getTarget(e);
21302 return t ? elements[t.id] || handles[t.id] : null;
21307 * Ext JS Library 1.1.1
21308 * Copyright(c) 2006-2007, Ext JS, LLC.
21310 * Originally Released Under LGPL - original licence link has changed is not relivant.
21313 * <script type="text/javascript">
21318 * @class Roo.dd.StatusProxy
21319 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
21320 * default drag proxy used by all Roo.dd components.
21322 * @param {Object} config
21324 Roo.dd.StatusProxy = function(config){
21325 Roo.apply(this, config);
21326 this.id = this.id || Roo.id();
21327 this.el = new Roo.Layer({
21329 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
21330 {tag: "div", cls: "x-dd-drop-icon"},
21331 {tag: "div", cls: "x-dd-drag-ghost"}
21334 shadow: !config || config.shadow !== false
21336 this.ghost = Roo.get(this.el.dom.childNodes[1]);
21337 this.dropStatus = this.dropNotAllowed;
21340 Roo.dd.StatusProxy.prototype = {
21342 * @cfg {String} dropAllowed
21343 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
21345 dropAllowed : "x-dd-drop-ok",
21347 * @cfg {String} dropNotAllowed
21348 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
21350 dropNotAllowed : "x-dd-drop-nodrop",
21353 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
21354 * over the current target element.
21355 * @param {String} cssClass The css class for the new drop status indicator image
21357 setStatus : function(cssClass){
21358 cssClass = cssClass || this.dropNotAllowed;
21359 if(this.dropStatus != cssClass){
21360 this.el.replaceClass(this.dropStatus, cssClass);
21361 this.dropStatus = cssClass;
21366 * Resets the status indicator to the default dropNotAllowed value
21367 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
21369 reset : function(clearGhost){
21370 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
21371 this.dropStatus = this.dropNotAllowed;
21373 this.ghost.update("");
21378 * Updates the contents of the ghost element
21379 * @param {String} html The html that will replace the current innerHTML of the ghost element
21381 update : function(html){
21382 if(typeof html == "string"){
21383 this.ghost.update(html);
21385 this.ghost.update("");
21386 html.style.margin = "0";
21387 this.ghost.dom.appendChild(html);
21389 // ensure float = none set?? cant remember why though.
21390 var el = this.ghost.dom.firstChild;
21392 Roo.fly(el).setStyle('float', 'none');
21397 * Returns the underlying proxy {@link Roo.Layer}
21398 * @return {Roo.Layer} el
21400 getEl : function(){
21405 * Returns the ghost element
21406 * @return {Roo.Element} el
21408 getGhost : function(){
21414 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
21416 hide : function(clear){
21424 * Stops the repair animation if it's currently running
21427 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
21433 * Displays this proxy
21440 * Force the Layer to sync its shadow and shim positions to the element
21447 * Causes the proxy to return to its position of origin via an animation. Should be called after an
21448 * invalid drop operation by the item being dragged.
21449 * @param {Array} xy The XY position of the element ([x, y])
21450 * @param {Function} callback The function to call after the repair is complete
21451 * @param {Object} scope The scope in which to execute the callback
21453 repair : function(xy, callback, scope){
21454 this.callback = callback;
21455 this.scope = scope;
21456 if(xy && this.animRepair !== false){
21457 this.el.addClass("x-dd-drag-repair");
21458 this.el.hideUnders(true);
21459 this.anim = this.el.shift({
21460 duration: this.repairDuration || .5,
21464 callback: this.afterRepair,
21468 this.afterRepair();
21473 afterRepair : function(){
21475 if(typeof this.callback == "function"){
21476 this.callback.call(this.scope || this);
21478 this.callback = null;
21483 * Ext JS Library 1.1.1
21484 * Copyright(c) 2006-2007, Ext JS, LLC.
21486 * Originally Released Under LGPL - original licence link has changed is not relivant.
21489 * <script type="text/javascript">
21493 * @class Roo.dd.DragSource
21494 * @extends Roo.dd.DDProxy
21495 * A simple class that provides the basic implementation needed to make any element draggable.
21497 * @param {String/HTMLElement/Element} el The container element
21498 * @param {Object} config
21500 Roo.dd.DragSource = function(el, config){
21501 this.el = Roo.get(el);
21502 this.dragData = {};
21504 Roo.apply(this, config);
21507 this.proxy = new Roo.dd.StatusProxy();
21510 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
21511 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
21513 this.dragging = false;
21516 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
21518 * @cfg {String} dropAllowed
21519 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21521 dropAllowed : "x-dd-drop-ok",
21523 * @cfg {String} dropNotAllowed
21524 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21526 dropNotAllowed : "x-dd-drop-nodrop",
21529 * Returns the data object associated with this drag source
21530 * @return {Object} data An object containing arbitrary data
21532 getDragData : function(e){
21533 return this.dragData;
21537 onDragEnter : function(e, id){
21538 var target = Roo.dd.DragDropMgr.getDDById(id);
21539 this.cachedTarget = target;
21540 if(this.beforeDragEnter(target, e, id) !== false){
21541 if(target.isNotifyTarget){
21542 var status = target.notifyEnter(this, e, this.dragData);
21543 this.proxy.setStatus(status);
21545 this.proxy.setStatus(this.dropAllowed);
21548 if(this.afterDragEnter){
21550 * An empty function by default, but provided so that you can perform a custom action
21551 * when the dragged item enters the drop target by providing an implementation.
21552 * @param {Roo.dd.DragDrop} target The drop target
21553 * @param {Event} e The event object
21554 * @param {String} id The id of the dragged element
21555 * @method afterDragEnter
21557 this.afterDragEnter(target, e, id);
21563 * An empty function by default, but provided so that you can perform a custom action
21564 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
21565 * @param {Roo.dd.DragDrop} target The drop target
21566 * @param {Event} e The event object
21567 * @param {String} id The id of the dragged element
21568 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21570 beforeDragEnter : function(target, e, id){
21575 alignElWithMouse: function() {
21576 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
21581 onDragOver : function(e, id){
21582 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21583 if(this.beforeDragOver(target, e, id) !== false){
21584 if(target.isNotifyTarget){
21585 var status = target.notifyOver(this, e, this.dragData);
21586 this.proxy.setStatus(status);
21589 if(this.afterDragOver){
21591 * An empty function by default, but provided so that you can perform a custom action
21592 * while the dragged item is over the drop target by providing an implementation.
21593 * @param {Roo.dd.DragDrop} target The drop target
21594 * @param {Event} e The event object
21595 * @param {String} id The id of the dragged element
21596 * @method afterDragOver
21598 this.afterDragOver(target, e, id);
21604 * An empty function by default, but provided so that you can perform a custom action
21605 * while the dragged item is over the drop target and optionally cancel the onDragOver.
21606 * @param {Roo.dd.DragDrop} target The drop target
21607 * @param {Event} e The event object
21608 * @param {String} id The id of the dragged element
21609 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21611 beforeDragOver : function(target, e, id){
21616 onDragOut : function(e, id){
21617 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21618 if(this.beforeDragOut(target, e, id) !== false){
21619 if(target.isNotifyTarget){
21620 target.notifyOut(this, e, this.dragData);
21622 this.proxy.reset();
21623 if(this.afterDragOut){
21625 * An empty function by default, but provided so that you can perform a custom action
21626 * after the dragged item is dragged out of the target without dropping.
21627 * @param {Roo.dd.DragDrop} target The drop target
21628 * @param {Event} e The event object
21629 * @param {String} id The id of the dragged element
21630 * @method afterDragOut
21632 this.afterDragOut(target, e, id);
21635 this.cachedTarget = null;
21639 * An empty function by default, but provided so that you can perform a custom action before the dragged
21640 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
21641 * @param {Roo.dd.DragDrop} target The drop target
21642 * @param {Event} e The event object
21643 * @param {String} id The id of the dragged element
21644 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21646 beforeDragOut : function(target, e, id){
21651 onDragDrop : function(e, id){
21652 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21653 if(this.beforeDragDrop(target, e, id) !== false){
21654 if(target.isNotifyTarget){
21655 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
21656 this.onValidDrop(target, e, id);
21658 this.onInvalidDrop(target, e, id);
21661 this.onValidDrop(target, e, id);
21664 if(this.afterDragDrop){
21666 * An empty function by default, but provided so that you can perform a custom action
21667 * after a valid drag drop has occurred by providing an implementation.
21668 * @param {Roo.dd.DragDrop} target The drop target
21669 * @param {Event} e The event object
21670 * @param {String} id The id of the dropped element
21671 * @method afterDragDrop
21673 this.afterDragDrop(target, e, id);
21676 delete this.cachedTarget;
21680 * An empty function by default, but provided so that you can perform a custom action before the dragged
21681 * item is dropped onto the target and optionally cancel the onDragDrop.
21682 * @param {Roo.dd.DragDrop} target The drop target
21683 * @param {Event} e The event object
21684 * @param {String} id The id of the dragged element
21685 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
21687 beforeDragDrop : function(target, e, id){
21692 onValidDrop : function(target, e, id){
21694 if(this.afterValidDrop){
21696 * An empty function by default, but provided so that you can perform a custom action
21697 * after a valid drop has occurred by providing an implementation.
21698 * @param {Object} target The target DD
21699 * @param {Event} e The event object
21700 * @param {String} id The id of the dropped element
21701 * @method afterInvalidDrop
21703 this.afterValidDrop(target, e, id);
21708 getRepairXY : function(e, data){
21709 return this.el.getXY();
21713 onInvalidDrop : function(target, e, id){
21714 this.beforeInvalidDrop(target, e, id);
21715 if(this.cachedTarget){
21716 if(this.cachedTarget.isNotifyTarget){
21717 this.cachedTarget.notifyOut(this, e, this.dragData);
21719 this.cacheTarget = null;
21721 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
21723 if(this.afterInvalidDrop){
21725 * An empty function by default, but provided so that you can perform a custom action
21726 * after an invalid drop has occurred by providing an implementation.
21727 * @param {Event} e The event object
21728 * @param {String} id The id of the dropped element
21729 * @method afterInvalidDrop
21731 this.afterInvalidDrop(e, id);
21736 afterRepair : function(){
21738 this.el.highlight(this.hlColor || "c3daf9");
21740 this.dragging = false;
21744 * An empty function by default, but provided so that you can perform a custom action after an invalid
21745 * drop has occurred.
21746 * @param {Roo.dd.DragDrop} target The drop target
21747 * @param {Event} e The event object
21748 * @param {String} id The id of the dragged element
21749 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
21751 beforeInvalidDrop : function(target, e, id){
21756 handleMouseDown : function(e){
21757 if(this.dragging) {
21760 var data = this.getDragData(e);
21761 if(data && this.onBeforeDrag(data, e) !== false){
21762 this.dragData = data;
21764 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
21769 * An empty function by default, but provided so that you can perform a custom action before the initial
21770 * drag event begins and optionally cancel it.
21771 * @param {Object} data An object containing arbitrary data to be shared with drop targets
21772 * @param {Event} e The event object
21773 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21775 onBeforeDrag : function(data, e){
21780 * An empty function by default, but provided so that you can perform a custom action once the initial
21781 * drag event has begun. The drag cannot be canceled from this function.
21782 * @param {Number} x The x position of the click on the dragged object
21783 * @param {Number} y The y position of the click on the dragged object
21785 onStartDrag : Roo.emptyFn,
21787 // private - YUI override
21788 startDrag : function(x, y){
21789 this.proxy.reset();
21790 this.dragging = true;
21791 this.proxy.update("");
21792 this.onInitDrag(x, y);
21797 onInitDrag : function(x, y){
21798 var clone = this.el.dom.cloneNode(true);
21799 clone.id = Roo.id(); // prevent duplicate ids
21800 this.proxy.update(clone);
21801 this.onStartDrag(x, y);
21806 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
21807 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
21809 getProxy : function(){
21814 * Hides the drag source's {@link Roo.dd.StatusProxy}
21816 hideProxy : function(){
21818 this.proxy.reset(true);
21819 this.dragging = false;
21823 triggerCacheRefresh : function(){
21824 Roo.dd.DDM.refreshCache(this.groups);
21827 // private - override to prevent hiding
21828 b4EndDrag: function(e) {
21831 // private - override to prevent moving
21832 endDrag : function(e){
21833 this.onEndDrag(this.dragData, e);
21837 onEndDrag : function(data, e){
21840 // private - pin to cursor
21841 autoOffset : function(x, y) {
21842 this.setDelta(-12, -20);
21846 * Ext JS Library 1.1.1
21847 * Copyright(c) 2006-2007, Ext JS, LLC.
21849 * Originally Released Under LGPL - original licence link has changed is not relivant.
21852 * <script type="text/javascript">
21857 * @class Roo.dd.DropTarget
21858 * @extends Roo.dd.DDTarget
21859 * A simple class that provides the basic implementation needed to make any element a drop target that can have
21860 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
21862 * @param {String/HTMLElement/Element} el The container element
21863 * @param {Object} config
21865 Roo.dd.DropTarget = function(el, config){
21866 this.el = Roo.get(el);
21868 var listeners = false; ;
21869 if (config && config.listeners) {
21870 listeners= config.listeners;
21871 delete config.listeners;
21873 Roo.apply(this, config);
21875 if(this.containerScroll){
21876 Roo.dd.ScrollManager.register(this.el);
21880 * @scope Roo.dd.DropTarget
21885 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
21886 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
21887 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
21889 * IMPORTANT : it should set this.overClass and this.dropAllowed
21891 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21892 * @param {Event} e The event
21893 * @param {Object} data An object containing arbitrary data supplied by the drag source
21899 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
21900 * This method will be called on every mouse movement while the drag source is over the drop target.
21901 * This default implementation simply returns the dropAllowed config value.
21903 * IMPORTANT : it should set this.dropAllowed
21905 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21906 * @param {Event} e The event
21907 * @param {Object} data An object containing arbitrary data supplied by the drag source
21913 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
21914 * out of the target without dropping. This default implementation simply removes the CSS class specified by
21915 * overClass (if any) from the drop element.
21917 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21918 * @param {Event} e The event
21919 * @param {Object} data An object containing arbitrary data supplied by the drag source
21925 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
21926 * been dropped on it. This method has no default implementation and returns false, so you must provide an
21927 * implementation that does something to process the drop event and returns true so that the drag source's
21928 * repair action does not run.
21930 * IMPORTANT : it should set this.success
21932 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21933 * @param {Event} e The event
21934 * @param {Object} data An object containing arbitrary data supplied by the drag source
21940 Roo.dd.DropTarget.superclass.constructor.call( this,
21942 this.ddGroup || this.group,
21945 listeners : listeners || {}
21953 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
21955 * @cfg {String} overClass
21956 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
21959 * @cfg {String} ddGroup
21960 * The drag drop group to handle drop events for
21964 * @cfg {String} dropAllowed
21965 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21967 dropAllowed : "x-dd-drop-ok",
21969 * @cfg {String} dropNotAllowed
21970 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21972 dropNotAllowed : "x-dd-drop-nodrop",
21974 * @cfg {boolean} success
21975 * set this after drop listener..
21979 * @cfg {boolean|String} valid true/false or string (ok-add/ok-sub/ok/nodrop)
21980 * if the drop point is valid for over/enter..
21987 isNotifyTarget : true,
21992 notifyEnter : function(dd, e, data)
21995 this.fireEvent('enter', dd, e, data);
21996 if(this.overClass){
21997 this.el.addClass(this.overClass);
21999 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
22000 this.valid ? this.dropAllowed : this.dropNotAllowed
22007 notifyOver : function(dd, e, data)
22010 this.fireEvent('over', dd, e, data);
22011 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
22012 this.valid ? this.dropAllowed : this.dropNotAllowed
22019 notifyOut : function(dd, e, data)
22021 this.fireEvent('out', dd, e, data);
22022 if(this.overClass){
22023 this.el.removeClass(this.overClass);
22030 notifyDrop : function(dd, e, data)
22032 this.success = false;
22033 this.fireEvent('drop', dd, e, data);
22034 return this.success;
22038 * Ext JS Library 1.1.1
22039 * Copyright(c) 2006-2007, Ext JS, LLC.
22041 * Originally Released Under LGPL - original licence link has changed is not relivant.
22044 * <script type="text/javascript">
22049 * @class Roo.dd.DragZone
22050 * @extends Roo.dd.DragSource
22051 * This class provides a container DD instance that proxies for multiple child node sources.<br />
22052 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
22054 * @param {String/HTMLElement/Element} el The container element
22055 * @param {Object} config
22057 Roo.dd.DragZone = function(el, config){
22058 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
22059 if(this.containerScroll){
22060 Roo.dd.ScrollManager.register(this.el);
22064 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
22066 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
22067 * for auto scrolling during drag operations.
22070 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
22071 * method after a failed drop (defaults to "c3daf9" - light blue)
22075 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
22076 * for a valid target to drag based on the mouse down. Override this method
22077 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
22078 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
22079 * @param {EventObject} e The mouse down event
22080 * @return {Object} The dragData
22082 getDragData : function(e){
22083 return Roo.dd.Registry.getHandleFromEvent(e);
22087 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
22088 * this.dragData.ddel
22089 * @param {Number} x The x position of the click on the dragged object
22090 * @param {Number} y The y position of the click on the dragged object
22091 * @return {Boolean} true to continue the drag, false to cancel
22093 onInitDrag : function(x, y){
22094 this.proxy.update(this.dragData.ddel.cloneNode(true));
22095 this.onStartDrag(x, y);
22100 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
22102 afterRepair : function(){
22104 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
22106 this.dragging = false;
22110 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
22111 * the XY of this.dragData.ddel
22112 * @param {EventObject} e The mouse up event
22113 * @return {Array} The xy location (e.g. [100, 200])
22115 getRepairXY : function(e){
22116 return Roo.Element.fly(this.dragData.ddel).getXY();
22120 * Ext JS Library 1.1.1
22121 * Copyright(c) 2006-2007, Ext JS, LLC.
22123 * Originally Released Under LGPL - original licence link has changed is not relivant.
22126 * <script type="text/javascript">
22129 * @class Roo.dd.DropZone
22130 * @extends Roo.dd.DropTarget
22131 * This class provides a container DD instance that proxies for multiple child node targets.<br />
22132 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
22134 * @param {String/HTMLElement/Element} el The container element
22135 * @param {Object} config
22137 Roo.dd.DropZone = function(el, config){
22138 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
22141 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
22143 * Returns a custom data object associated with the DOM node that is the target of the event. By default
22144 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
22145 * provide your own custom lookup.
22146 * @param {Event} e The event
22147 * @return {Object} data The custom data
22149 getTargetFromEvent : function(e){
22150 return Roo.dd.Registry.getTargetFromEvent(e);
22154 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
22155 * that it has registered. This method has no default implementation and should be overridden to provide
22156 * node-specific processing if necessary.
22157 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22158 * {@link #getTargetFromEvent} for this node)
22159 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22160 * @param {Event} e The event
22161 * @param {Object} data An object containing arbitrary data supplied by the drag source
22163 onNodeEnter : function(n, dd, e, data){
22168 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
22169 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
22170 * overridden to provide the proper feedback.
22171 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22172 * {@link #getTargetFromEvent} for this node)
22173 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22174 * @param {Event} e The event
22175 * @param {Object} data An object containing arbitrary data supplied by the drag source
22176 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22177 * underlying {@link Roo.dd.StatusProxy} can be updated
22179 onNodeOver : function(n, dd, e, data){
22180 return this.dropAllowed;
22184 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
22185 * the drop node without dropping. This method has no default implementation and should be overridden to provide
22186 * node-specific processing if necessary.
22187 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22188 * {@link #getTargetFromEvent} for this node)
22189 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22190 * @param {Event} e The event
22191 * @param {Object} data An object containing arbitrary data supplied by the drag source
22193 onNodeOut : function(n, dd, e, data){
22198 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
22199 * the drop node. The default implementation returns false, so it should be overridden to provide the
22200 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
22201 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22202 * {@link #getTargetFromEvent} for this node)
22203 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22204 * @param {Event} e The event
22205 * @param {Object} data An object containing arbitrary data supplied by the drag source
22206 * @return {Boolean} True if the drop was valid, else false
22208 onNodeDrop : function(n, dd, e, data){
22213 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
22214 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
22215 * it should be overridden to provide the proper feedback if necessary.
22216 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22217 * @param {Event} e The event
22218 * @param {Object} data An object containing arbitrary data supplied by the drag source
22219 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22220 * underlying {@link Roo.dd.StatusProxy} can be updated
22222 onContainerOver : function(dd, e, data){
22223 return this.dropNotAllowed;
22227 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
22228 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
22229 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
22230 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
22231 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22232 * @param {Event} e The event
22233 * @param {Object} data An object containing arbitrary data supplied by the drag source
22234 * @return {Boolean} True if the drop was valid, else false
22236 onContainerDrop : function(dd, e, data){
22241 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
22242 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
22243 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
22244 * you should override this method and provide a custom implementation.
22245 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22246 * @param {Event} e The event
22247 * @param {Object} data An object containing arbitrary data supplied by the drag source
22248 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22249 * underlying {@link Roo.dd.StatusProxy} can be updated
22251 notifyEnter : function(dd, e, data){
22252 return this.dropNotAllowed;
22256 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
22257 * This method will be called on every mouse movement while the drag source is over the drop zone.
22258 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
22259 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
22260 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
22261 * registered node, it will call {@link #onContainerOver}.
22262 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22263 * @param {Event} e The event
22264 * @param {Object} data An object containing arbitrary data supplied by the drag source
22265 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22266 * underlying {@link Roo.dd.StatusProxy} can be updated
22268 notifyOver : function(dd, e, data){
22269 var n = this.getTargetFromEvent(e);
22270 if(!n){ // not over valid drop target
22271 if(this.lastOverNode){
22272 this.onNodeOut(this.lastOverNode, dd, e, data);
22273 this.lastOverNode = null;
22275 return this.onContainerOver(dd, e, data);
22277 if(this.lastOverNode != n){
22278 if(this.lastOverNode){
22279 this.onNodeOut(this.lastOverNode, dd, e, data);
22281 this.onNodeEnter(n, dd, e, data);
22282 this.lastOverNode = n;
22284 return this.onNodeOver(n, dd, e, data);
22288 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
22289 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
22290 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
22291 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
22292 * @param {Event} e The event
22293 * @param {Object} data An object containing arbitrary data supplied by the drag zone
22295 notifyOut : function(dd, e, data){
22296 if(this.lastOverNode){
22297 this.onNodeOut(this.lastOverNode, dd, e, data);
22298 this.lastOverNode = null;
22303 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
22304 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
22305 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
22306 * otherwise it will call {@link #onContainerDrop}.
22307 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22308 * @param {Event} e The event
22309 * @param {Object} data An object containing arbitrary data supplied by the drag source
22310 * @return {Boolean} True if the drop was valid, else false
22312 notifyDrop : function(dd, e, data){
22313 if(this.lastOverNode){
22314 this.onNodeOut(this.lastOverNode, dd, e, data);
22315 this.lastOverNode = null;
22317 var n = this.getTargetFromEvent(e);
22319 this.onNodeDrop(n, dd, e, data) :
22320 this.onContainerDrop(dd, e, data);
22324 triggerCacheRefresh : function(){
22325 Roo.dd.DDM.refreshCache(this.groups);