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.isGecko ? "roo-gecko"
6632 : Roo.isOpera ? "roo-opera"
6633 : Roo.isSafari ? "roo-safari" : ""];
6636 cls.push("roo-mac");
6639 cls.push("roo-linux");
6642 cls.push("roo-ios");
6645 cls.push("roo-touch");
6647 if(Roo.isBorderBox){
6648 cls.push('roo-border-box');
6650 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6651 var p = bd.dom.parentNode;
6653 p.className += ' roo-strict';
6656 bd.addClass(cls.join(' '));
6660 * @class Roo.EventObject
6661 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6662 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6665 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6667 var target = e.getTarget();
6670 var myDiv = Roo.get("myDiv");
6671 myDiv.on("click", handleClick);
6673 Roo.EventManager.on("myDiv", 'click', handleClick);
6674 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6678 Roo.EventObject = function(){
6680 var E = Roo.lib.Event;
6682 // safari keypress events for special keys return bad keycodes
6685 63235 : 39, // right
6688 63276 : 33, // page up
6689 63277 : 34, // page down
6690 63272 : 46, // delete
6695 // normalize button clicks
6696 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6697 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6699 Roo.EventObjectImpl = function(e){
6701 this.setEvent(e.browserEvent || e);
6704 Roo.EventObjectImpl.prototype = {
6706 * Used to fix doc tools.
6707 * @scope Roo.EventObject.prototype
6713 /** The normal browser event */
6714 browserEvent : null,
6715 /** The button pressed in a mouse event */
6717 /** True if the shift key was down during the event */
6719 /** True if the control key was down during the event */
6721 /** True if the alt key was down during the event */
6780 setEvent : function(e){
6781 if(e == this || (e && e.browserEvent)){ // already wrapped
6784 this.browserEvent = e;
6786 // normalize buttons
6787 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6788 if(e.type == 'click' && this.button == -1){
6792 this.shiftKey = e.shiftKey;
6793 // mac metaKey behaves like ctrlKey
6794 this.ctrlKey = e.ctrlKey || e.metaKey;
6795 this.altKey = e.altKey;
6796 // in getKey these will be normalized for the mac
6797 this.keyCode = e.keyCode;
6798 // keyup warnings on firefox.
6799 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6800 // cache the target for the delayed and or buffered events
6801 this.target = E.getTarget(e);
6803 this.xy = E.getXY(e);
6806 this.shiftKey = false;
6807 this.ctrlKey = false;
6808 this.altKey = false;
6818 * Stop the event (preventDefault and stopPropagation)
6820 stopEvent : function(){
6821 if(this.browserEvent){
6822 if(this.browserEvent.type == 'mousedown'){
6823 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6825 E.stopEvent(this.browserEvent);
6830 * Prevents the browsers default handling of the event.
6832 preventDefault : function(){
6833 if(this.browserEvent){
6834 E.preventDefault(this.browserEvent);
6839 isNavKeyPress : function(){
6840 var k = this.keyCode;
6841 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6842 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6845 isSpecialKey : function(){
6846 var k = this.keyCode;
6847 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6848 (k == 16) || (k == 17) ||
6849 (k >= 18 && k <= 20) ||
6850 (k >= 33 && k <= 35) ||
6851 (k >= 36 && k <= 39) ||
6852 (k >= 44 && k <= 45);
6855 * Cancels bubbling of the event.
6857 stopPropagation : function(){
6858 if(this.browserEvent){
6859 if(this.type == 'mousedown'){
6860 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6862 E.stopPropagation(this.browserEvent);
6867 * Gets the key code for the event.
6870 getCharCode : function(){
6871 return this.charCode || this.keyCode;
6875 * Returns a normalized keyCode for the event.
6876 * @return {Number} The key code
6878 getKey : function(){
6879 var k = this.keyCode || this.charCode;
6880 return Roo.isSafari ? (safariKeys[k] || k) : k;
6884 * Gets the x coordinate of the event.
6887 getPageX : function(){
6892 * Gets the y coordinate of the event.
6895 getPageY : function(){
6900 * Gets the time of the event.
6903 getTime : function(){
6904 if(this.browserEvent){
6905 return E.getTime(this.browserEvent);
6911 * Gets the page coordinates of the event.
6912 * @return {Array} The xy values like [x, y]
6919 * Gets the target for the event.
6920 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6921 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6922 search as a number or element (defaults to 10 || document.body)
6923 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6924 * @return {HTMLelement}
6926 getTarget : function(selector, maxDepth, returnEl){
6927 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6930 * Gets the related target.
6931 * @return {HTMLElement}
6933 getRelatedTarget : function(){
6934 if(this.browserEvent){
6935 return E.getRelatedTarget(this.browserEvent);
6941 * Normalizes mouse wheel delta across browsers
6942 * @return {Number} The delta
6944 getWheelDelta : function(){
6945 var e = this.browserEvent;
6947 if(e.wheelDelta){ /* IE/Opera. */
6948 delta = e.wheelDelta/120;
6949 }else if(e.detail){ /* Mozilla case. */
6950 delta = -e.detail/3;
6956 * Returns true if the control, meta, shift or alt key was pressed during this event.
6959 hasModifier : function(){
6960 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6964 * Returns true if the target of this event equals el or is a child of el
6965 * @param {String/HTMLElement/Element} el
6966 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6969 within : function(el, related){
6970 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6971 return t && Roo.fly(el).contains(t);
6974 getPoint : function(){
6975 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6979 return new Roo.EventObjectImpl();
6984 * Ext JS Library 1.1.1
6985 * Copyright(c) 2006-2007, Ext JS, LLC.
6987 * Originally Released Under LGPL - original licence link has changed is not relivant.
6990 * <script type="text/javascript">
6994 // was in Composite Element!??!?!
6997 var D = Roo.lib.Dom;
6998 var E = Roo.lib.Event;
6999 var A = Roo.lib.Anim;
7001 // local style camelizing for speed
7003 var camelRe = /(-[a-z])/gi;
7004 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
7005 var view = document.defaultView;
7008 * @class Roo.Element
7009 * Represents an Element in the DOM.<br><br>
7012 var el = Roo.get("my-div");
7015 var el = getEl("my-div");
7017 // or with a DOM element
7018 var el = Roo.get(myDivElement);
7020 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
7021 * each call instead of constructing a new one.<br><br>
7022 * <b>Animations</b><br />
7023 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
7024 * should either be a boolean (true) or an object literal with animation options. The animation options are:
7026 Option Default Description
7027 --------- -------- ---------------------------------------------
7028 duration .35 The duration of the animation in seconds
7029 easing easeOut The YUI easing method
7030 callback none A function to execute when the anim completes
7031 scope this The scope (this) of the callback function
7033 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
7034 * manipulate the animation. Here's an example:
7036 var el = Roo.get("my-div");
7041 // default animation
7042 el.setWidth(100, true);
7044 // animation with some options set
7051 // using the "anim" property to get the Anim object
7057 el.setWidth(100, opt);
7059 if(opt.anim.isAnimated()){
7063 * <b> Composite (Collections of) Elements</b><br />
7064 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
7065 * @constructor Create a new Element directly.
7066 * @param {String/HTMLElement} element
7067 * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
7069 Roo.Element = function(element, forceNew){
7070 var dom = typeof element == "string" ?
7071 document.getElementById(element) : element;
7072 if(!dom){ // invalid id/element
7076 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7077 return Roo.Element.cache[id];
7087 * The DOM element ID
7090 this.id = id || Roo.id(dom);
7093 var El = Roo.Element;
7097 * The element's default display mode (defaults to "")
7100 originalDisplay : "",
7104 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7110 * Sets the element's visibility mode. When setVisible() is called it
7111 * will use this to determine whether to set the visibility or the display property.
7112 * @param visMode Element.VISIBILITY or Element.DISPLAY
7113 * @return {Roo.Element} this
7115 setVisibilityMode : function(visMode){
7116 this.visibilityMode = visMode;
7120 * Convenience method for setVisibilityMode(Element.DISPLAY)
7121 * @param {String} display (optional) What to set display to when visible
7122 * @return {Roo.Element} this
7124 enableDisplayMode : function(display){
7125 this.setVisibilityMode(El.DISPLAY);
7126 if(typeof display != "undefined") { this.originalDisplay = display; }
7131 * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7132 * @param {String} selector The simple selector to test
7133 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7134 search as a number or element (defaults to 10 || document.body)
7135 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7136 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7138 findParent : function(simpleSelector, maxDepth, returnEl){
7139 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7140 maxDepth = maxDepth || 50;
7141 if(typeof maxDepth != "number"){
7142 stopEl = Roo.getDom(maxDepth);
7145 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7146 if(dq.is(p, simpleSelector)){
7147 return returnEl ? Roo.get(p) : p;
7157 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7158 * @param {String} selector The simple selector to test
7159 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7160 search as a number or element (defaults to 10 || document.body)
7161 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7162 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7164 findParentNode : function(simpleSelector, maxDepth, returnEl){
7165 var p = Roo.fly(this.dom.parentNode, '_internal');
7166 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7170 * Looks at the scrollable parent element
7172 findScrollableParent : function()
7174 var overflowRegex = /(auto|scroll)/;
7176 if(this.getStyle('position') === 'fixed'){
7177 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7180 var excludeStaticParent = this.getStyle('position') === "absolute";
7182 for (var parent = this; (parent = Roo.get(parent.dom.parentNode));){
7184 if (excludeStaticParent && parent.getStyle('position') === "static") {
7188 if (overflowRegex.test(parent.getStyle('overflow') + parent.getStyle('overflow-x') + parent.getStyle('overflow-y'))){
7192 if(parent.dom.nodeName.toLowerCase() == 'body'){
7193 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7197 alert('is android : ' + Roo.isAndroid);
7198 alert('is ios : ' + Roo.isIOS);
7201 alert('Is Android');
7202 return Roo.get(document.documentElement);
7206 alert('not android');
7209 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7213 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7214 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7215 * @param {String} selector The simple selector to test
7216 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7217 search as a number or element (defaults to 10 || document.body)
7218 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7220 up : function(simpleSelector, maxDepth){
7221 return this.findParentNode(simpleSelector, maxDepth, true);
7227 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7228 * @param {String} selector The simple selector to test
7229 * @return {Boolean} True if this element matches the selector, else false
7231 is : function(simpleSelector){
7232 return Roo.DomQuery.is(this.dom, simpleSelector);
7236 * Perform animation on this element.
7237 * @param {Object} args The YUI animation control args
7238 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7239 * @param {Function} onComplete (optional) Function to call when animation completes
7240 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7241 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7242 * @return {Roo.Element} this
7244 animate : function(args, duration, onComplete, easing, animType){
7245 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7250 * @private Internal animation call
7252 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7253 animType = animType || 'run';
7255 var anim = Roo.lib.Anim[animType](
7257 (opt.duration || defaultDur) || .35,
7258 (opt.easing || defaultEase) || 'easeOut',
7260 Roo.callback(cb, this);
7261 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7269 // private legacy anim prep
7270 preanim : function(a, i){
7271 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7275 * Removes worthless text nodes
7276 * @param {Boolean} forceReclean (optional) By default the element
7277 * keeps track if it has been cleaned already so
7278 * you can call this over and over. However, if you update the element and
7279 * need to force a reclean, you can pass true.
7281 clean : function(forceReclean){
7282 if(this.isCleaned && forceReclean !== true){
7286 var d = this.dom, n = d.firstChild, ni = -1;
7288 var nx = n.nextSibling;
7289 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7296 this.isCleaned = true;
7301 calcOffsetsTo : function(el){
7304 var restorePos = false;
7305 if(el.getStyle('position') == 'static'){
7306 el.position('relative');
7311 while(op && op != d && op.tagName != 'HTML'){
7314 op = op.offsetParent;
7317 el.position('static');
7323 * Scrolls this element into view within the passed container.
7324 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7325 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7326 * @return {Roo.Element} this
7328 scrollIntoView : function(container, hscroll){
7329 var c = Roo.getDom(container) || document.body;
7332 var o = this.calcOffsetsTo(c),
7335 b = t+el.offsetHeight,
7336 r = l+el.offsetWidth;
7338 var ch = c.clientHeight;
7339 var ct = parseInt(c.scrollTop, 10);
7340 var cl = parseInt(c.scrollLeft, 10);
7342 var cr = cl + c.clientWidth;
7350 if(hscroll !== false){
7354 c.scrollLeft = r-c.clientWidth;
7361 scrollChildIntoView : function(child, hscroll){
7362 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7366 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7367 * the new height may not be available immediately.
7368 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7369 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7370 * @param {Function} onComplete (optional) Function to call when animation completes
7371 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7372 * @return {Roo.Element} this
7374 autoHeight : function(animate, duration, onComplete, easing){
7375 var oldHeight = this.getHeight();
7377 this.setHeight(1); // force clipping
7378 setTimeout(function(){
7379 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7381 this.setHeight(height);
7383 if(typeof onComplete == "function"){
7387 this.setHeight(oldHeight); // restore original height
7388 this.setHeight(height, animate, duration, function(){
7390 if(typeof onComplete == "function") { onComplete(); }
7391 }.createDelegate(this), easing);
7393 }.createDelegate(this), 0);
7398 * Returns true if this element is an ancestor of the passed element
7399 * @param {HTMLElement/String} el The element to check
7400 * @return {Boolean} True if this element is an ancestor of el, else false
7402 contains : function(el){
7403 if(!el){return false;}
7404 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7408 * Checks whether the element is currently visible using both visibility and display properties.
7409 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7410 * @return {Boolean} True if the element is currently visible, else false
7412 isVisible : function(deep) {
7413 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7414 if(deep !== true || !vis){
7417 var p = this.dom.parentNode;
7418 while(p && p.tagName.toLowerCase() != "body"){
7419 if(!Roo.fly(p, '_isVisible').isVisible()){
7428 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7429 * @param {String} selector The CSS selector
7430 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7431 * @return {CompositeElement/CompositeElementLite} The composite element
7433 select : function(selector, unique){
7434 return El.select(selector, unique, this.dom);
7438 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7439 * @param {String} selector The CSS selector
7440 * @return {Array} An array of the matched nodes
7442 query : function(selector, unique){
7443 return Roo.DomQuery.select(selector, this.dom);
7447 * Selects a single child at any depth below this element 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 child : function(selector, returnDom){
7453 var n = Roo.DomQuery.selectNode(selector, this.dom);
7454 return returnDom ? n : Roo.get(n);
7458 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7459 * @param {String} selector The CSS selector
7460 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7461 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7463 down : function(selector, returnDom){
7464 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7465 return returnDom ? n : Roo.get(n);
7469 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7470 * @param {String} group The group the DD object is member of
7471 * @param {Object} config The DD config object
7472 * @param {Object} overrides An object containing methods to override/implement on the DD object
7473 * @return {Roo.dd.DD} The DD object
7475 initDD : function(group, config, overrides){
7476 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7477 return Roo.apply(dd, overrides);
7481 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7482 * @param {String} group The group the DDProxy object is member of
7483 * @param {Object} config The DDProxy config object
7484 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7485 * @return {Roo.dd.DDProxy} The DDProxy object
7487 initDDProxy : function(group, config, overrides){
7488 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7489 return Roo.apply(dd, overrides);
7493 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7494 * @param {String} group The group the DDTarget object is member of
7495 * @param {Object} config The DDTarget config object
7496 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7497 * @return {Roo.dd.DDTarget} The DDTarget object
7499 initDDTarget : function(group, config, overrides){
7500 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7501 return Roo.apply(dd, overrides);
7505 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7506 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7507 * @param {Boolean} visible Whether the element is visible
7508 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7509 * @return {Roo.Element} this
7511 setVisible : function(visible, animate){
7513 if(this.visibilityMode == El.DISPLAY){
7514 this.setDisplayed(visible);
7517 this.dom.style.visibility = visible ? "visible" : "hidden";
7520 // closure for composites
7522 var visMode = this.visibilityMode;
7524 this.setOpacity(.01);
7525 this.setVisible(true);
7527 this.anim({opacity: { to: (visible?1:0) }},
7528 this.preanim(arguments, 1),
7529 null, .35, 'easeIn', function(){
7531 if(visMode == El.DISPLAY){
7532 dom.style.display = "none";
7534 dom.style.visibility = "hidden";
7536 Roo.get(dom).setOpacity(1);
7544 * Returns true if display is not "none"
7547 isDisplayed : function() {
7548 return this.getStyle("display") != "none";
7552 * Toggles the element's visibility or display, depending on visibility mode.
7553 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7554 * @return {Roo.Element} this
7556 toggle : function(animate){
7557 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7562 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7563 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7564 * @return {Roo.Element} this
7566 setDisplayed : function(value) {
7567 if(typeof value == "boolean"){
7568 value = value ? this.originalDisplay : "none";
7570 this.setStyle("display", value);
7575 * Tries to focus the element. Any exceptions are caught and ignored.
7576 * @return {Roo.Element} this
7578 focus : function() {
7586 * Tries to blur the element. Any exceptions are caught and ignored.
7587 * @return {Roo.Element} this
7597 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7598 * @param {String/Array} className The CSS class to add, or an array of classes
7599 * @return {Roo.Element} this
7601 addClass : function(className){
7602 if(className instanceof Array){
7603 for(var i = 0, len = className.length; i < len; i++) {
7604 this.addClass(className[i]);
7607 if(className && !this.hasClass(className)){
7608 this.dom.className = this.dom.className + " " + className;
7615 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7616 * @param {String/Array} className The CSS class to add, or an array of classes
7617 * @return {Roo.Element} this
7619 radioClass : function(className){
7620 var siblings = this.dom.parentNode.childNodes;
7621 for(var i = 0; i < siblings.length; i++) {
7622 var s = siblings[i];
7623 if(s.nodeType == 1){
7624 Roo.get(s).removeClass(className);
7627 this.addClass(className);
7632 * Removes one or more CSS classes from the element.
7633 * @param {String/Array} className The CSS class to remove, or an array of classes
7634 * @return {Roo.Element} this
7636 removeClass : function(className){
7637 if(!className || !this.dom.className){
7640 if(className instanceof Array){
7641 for(var i = 0, len = className.length; i < len; i++) {
7642 this.removeClass(className[i]);
7645 if(this.hasClass(className)){
7646 var re = this.classReCache[className];
7648 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7649 this.classReCache[className] = re;
7651 this.dom.className =
7652 this.dom.className.replace(re, " ");
7662 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7663 * @param {String} className The CSS class to toggle
7664 * @return {Roo.Element} this
7666 toggleClass : function(className){
7667 if(this.hasClass(className)){
7668 this.removeClass(className);
7670 this.addClass(className);
7676 * Checks if the specified CSS class exists on this element's DOM node.
7677 * @param {String} className The CSS class to check for
7678 * @return {Boolean} True if the class exists, else false
7680 hasClass : function(className){
7681 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7685 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7686 * @param {String} oldClassName The CSS class to replace
7687 * @param {String} newClassName The replacement CSS class
7688 * @return {Roo.Element} this
7690 replaceClass : function(oldClassName, newClassName){
7691 this.removeClass(oldClassName);
7692 this.addClass(newClassName);
7697 * Returns an object with properties matching the styles requested.
7698 * For example, el.getStyles('color', 'font-size', 'width') might return
7699 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7700 * @param {String} style1 A style name
7701 * @param {String} style2 A style name
7702 * @param {String} etc.
7703 * @return {Object} The style object
7705 getStyles : function(){
7706 var a = arguments, len = a.length, r = {};
7707 for(var i = 0; i < len; i++){
7708 r[a[i]] = this.getStyle(a[i]);
7714 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7715 * @param {String} property The style property whose value is returned.
7716 * @return {String} The current value of the style property for this element.
7718 getStyle : function(){
7719 return view && view.getComputedStyle ?
7721 var el = this.dom, v, cs, camel;
7722 if(prop == 'float'){
7725 if(el.style && (v = el.style[prop])){
7728 if(cs = view.getComputedStyle(el, "")){
7729 if(!(camel = propCache[prop])){
7730 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7737 var el = this.dom, v, cs, camel;
7738 if(prop == 'opacity'){
7739 if(typeof el.style.filter == 'string'){
7740 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7742 var fv = parseFloat(m[1]);
7744 return fv ? fv / 100 : 0;
7749 }else if(prop == 'float'){
7750 prop = "styleFloat";
7752 if(!(camel = propCache[prop])){
7753 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7755 if(v = el.style[camel]){
7758 if(cs = el.currentStyle){
7766 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7767 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7768 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7769 * @return {Roo.Element} this
7771 setStyle : function(prop, value){
7772 if(typeof prop == "string"){
7774 if (prop == 'float') {
7775 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7780 if(!(camel = propCache[prop])){
7781 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7784 if(camel == 'opacity') {
7785 this.setOpacity(value);
7787 this.dom.style[camel] = value;
7790 for(var style in prop){
7791 if(typeof prop[style] != "function"){
7792 this.setStyle(style, prop[style]);
7800 * More flexible version of {@link #setStyle} for setting style properties.
7801 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7802 * a function which returns such a specification.
7803 * @return {Roo.Element} this
7805 applyStyles : function(style){
7806 Roo.DomHelper.applyStyles(this.dom, style);
7811 * 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).
7812 * @return {Number} The X position of the element
7815 return D.getX(this.dom);
7819 * 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).
7820 * @return {Number} The Y position of the element
7823 return D.getY(this.dom);
7827 * 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).
7828 * @return {Array} The XY position of the element
7831 return D.getXY(this.dom);
7835 * 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).
7836 * @param {Number} The X position of the element
7837 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7838 * @return {Roo.Element} this
7840 setX : function(x, animate){
7842 D.setX(this.dom, x);
7844 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7850 * 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).
7851 * @param {Number} The Y position of the element
7852 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7853 * @return {Roo.Element} this
7855 setY : function(y, animate){
7857 D.setY(this.dom, y);
7859 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7865 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7866 * @param {String} left The left CSS property value
7867 * @return {Roo.Element} this
7869 setLeft : function(left){
7870 this.setStyle("left", this.addUnits(left));
7875 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7876 * @param {String} top The top CSS property value
7877 * @return {Roo.Element} this
7879 setTop : function(top){
7880 this.setStyle("top", this.addUnits(top));
7885 * Sets the element's CSS right style.
7886 * @param {String} right The right CSS property value
7887 * @return {Roo.Element} this
7889 setRight : function(right){
7890 this.setStyle("right", this.addUnits(right));
7895 * Sets the element's CSS bottom style.
7896 * @param {String} bottom The bottom CSS property value
7897 * @return {Roo.Element} this
7899 setBottom : function(bottom){
7900 this.setStyle("bottom", this.addUnits(bottom));
7905 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7906 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7907 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7908 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7909 * @return {Roo.Element} this
7911 setXY : function(pos, animate){
7913 D.setXY(this.dom, pos);
7915 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7921 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7922 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7923 * @param {Number} x X value for new position (coordinates are page-based)
7924 * @param {Number} y Y value for new position (coordinates are page-based)
7925 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7926 * @return {Roo.Element} this
7928 setLocation : function(x, y, animate){
7929 this.setXY([x, y], this.preanim(arguments, 2));
7934 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7935 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7936 * @param {Number} x X value for new position (coordinates are page-based)
7937 * @param {Number} y Y value for new position (coordinates are page-based)
7938 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7939 * @return {Roo.Element} this
7941 moveTo : function(x, y, animate){
7942 this.setXY([x, y], this.preanim(arguments, 2));
7947 * Returns the region of the given element.
7948 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7949 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7951 getRegion : function(){
7952 return D.getRegion(this.dom);
7956 * Returns the offset height of the element
7957 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7958 * @return {Number} The element's height
7960 getHeight : function(contentHeight){
7961 var h = this.dom.offsetHeight || 0;
7962 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7966 * Returns the offset width of the element
7967 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7968 * @return {Number} The element's width
7970 getWidth : function(contentWidth){
7971 var w = this.dom.offsetWidth || 0;
7972 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7976 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7977 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7978 * if a height has not been set using CSS.
7981 getComputedHeight : function(){
7982 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7984 h = parseInt(this.getStyle('height'), 10) || 0;
7985 if(!this.isBorderBox()){
7986 h += this.getFrameWidth('tb');
7993 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7994 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7995 * if a width has not been set using CSS.
7998 getComputedWidth : function(){
7999 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
8001 w = parseInt(this.getStyle('width'), 10) || 0;
8002 if(!this.isBorderBox()){
8003 w += this.getFrameWidth('lr');
8010 * Returns the size of the element.
8011 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
8012 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
8014 getSize : function(contentSize){
8015 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
8019 * Returns the width and height of the viewport.
8020 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
8022 getViewSize : function(){
8023 var d = this.dom, doc = document, aw = 0, ah = 0;
8024 if(d == doc || d == doc.body){
8025 return {width : D.getViewWidth(), height: D.getViewHeight()};
8028 width : d.clientWidth,
8029 height: d.clientHeight
8035 * Returns the value of the "value" attribute
8036 * @param {Boolean} asNumber true to parse the value as a number
8037 * @return {String/Number}
8039 getValue : function(asNumber){
8040 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
8044 adjustWidth : function(width){
8045 if(typeof width == "number"){
8046 if(this.autoBoxAdjust && !this.isBorderBox()){
8047 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8057 adjustHeight : function(height){
8058 if(typeof height == "number"){
8059 if(this.autoBoxAdjust && !this.isBorderBox()){
8060 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8070 * Set the width of the element
8071 * @param {Number} width The new width
8072 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8073 * @return {Roo.Element} this
8075 setWidth : function(width, animate){
8076 width = this.adjustWidth(width);
8078 this.dom.style.width = this.addUnits(width);
8080 this.anim({width: {to: width}}, this.preanim(arguments, 1));
8086 * Set the height of the element
8087 * @param {Number} height The new height
8088 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8089 * @return {Roo.Element} this
8091 setHeight : function(height, animate){
8092 height = this.adjustHeight(height);
8094 this.dom.style.height = this.addUnits(height);
8096 this.anim({height: {to: height}}, this.preanim(arguments, 1));
8102 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
8103 * @param {Number} width The new width
8104 * @param {Number} height The new height
8105 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8106 * @return {Roo.Element} this
8108 setSize : function(width, height, animate){
8109 if(typeof width == "object"){ // in case of object from getSize()
8110 height = width.height; width = width.width;
8112 width = this.adjustWidth(width); height = this.adjustHeight(height);
8114 this.dom.style.width = this.addUnits(width);
8115 this.dom.style.height = this.addUnits(height);
8117 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8123 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8124 * @param {Number} x X value for new position (coordinates are page-based)
8125 * @param {Number} y Y value for new position (coordinates are page-based)
8126 * @param {Number} width The new width
8127 * @param {Number} height The new height
8128 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8129 * @return {Roo.Element} this
8131 setBounds : function(x, y, width, height, animate){
8133 this.setSize(width, height);
8134 this.setLocation(x, y);
8136 width = this.adjustWidth(width); height = this.adjustHeight(height);
8137 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8138 this.preanim(arguments, 4), 'motion');
8144 * 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.
8145 * @param {Roo.lib.Region} region The region to fill
8146 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8147 * @return {Roo.Element} this
8149 setRegion : function(region, animate){
8150 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8155 * Appends an event handler
8157 * @param {String} eventName The type of event to append
8158 * @param {Function} fn The method the event invokes
8159 * @param {Object} scope (optional) The scope (this object) of the fn
8160 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8162 addListener : function(eventName, fn, scope, options){
8164 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8169 * Removes an event handler from this element
8170 * @param {String} eventName the type of event to remove
8171 * @param {Function} fn the method the event invokes
8172 * @return {Roo.Element} this
8174 removeListener : function(eventName, fn){
8175 Roo.EventManager.removeListener(this.dom, eventName, fn);
8180 * Removes all previous added listeners from this element
8181 * @return {Roo.Element} this
8183 removeAllListeners : function(){
8184 E.purgeElement(this.dom);
8188 relayEvent : function(eventName, observable){
8189 this.on(eventName, function(e){
8190 observable.fireEvent(eventName, e);
8195 * Set the opacity of the element
8196 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8197 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8198 * @return {Roo.Element} this
8200 setOpacity : function(opacity, animate){
8202 var s = this.dom.style;
8205 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8206 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8208 s.opacity = opacity;
8211 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8217 * Gets the left X coordinate
8218 * @param {Boolean} local True to get the local css position instead of page coordinate
8221 getLeft : function(local){
8225 return parseInt(this.getStyle("left"), 10) || 0;
8230 * Gets the right X coordinate of the element (element X position + element width)
8231 * @param {Boolean} local True to get the local css position instead of page coordinate
8234 getRight : function(local){
8236 return this.getX() + this.getWidth();
8238 return (this.getLeft(true) + this.getWidth()) || 0;
8243 * Gets the top Y coordinate
8244 * @param {Boolean} local True to get the local css position instead of page coordinate
8247 getTop : function(local) {
8251 return parseInt(this.getStyle("top"), 10) || 0;
8256 * Gets the bottom Y coordinate of the element (element Y position + element height)
8257 * @param {Boolean} local True to get the local css position instead of page coordinate
8260 getBottom : function(local){
8262 return this.getY() + this.getHeight();
8264 return (this.getTop(true) + this.getHeight()) || 0;
8269 * Initializes positioning on this element. If a desired position is not passed, it will make the
8270 * the element positioned relative IF it is not already positioned.
8271 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8272 * @param {Number} zIndex (optional) The zIndex to apply
8273 * @param {Number} x (optional) Set the page X position
8274 * @param {Number} y (optional) Set the page Y position
8276 position : function(pos, zIndex, x, y){
8278 if(this.getStyle('position') == 'static'){
8279 this.setStyle('position', 'relative');
8282 this.setStyle("position", pos);
8285 this.setStyle("z-index", zIndex);
8287 if(x !== undefined && y !== undefined){
8289 }else if(x !== undefined){
8291 }else if(y !== undefined){
8297 * Clear positioning back to the default when the document was loaded
8298 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8299 * @return {Roo.Element} this
8301 clearPositioning : function(value){
8309 "position" : "static"
8315 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8316 * snapshot before performing an update and then restoring the element.
8319 getPositioning : function(){
8320 var l = this.getStyle("left");
8321 var t = this.getStyle("top");
8323 "position" : this.getStyle("position"),
8325 "right" : l ? "" : this.getStyle("right"),
8327 "bottom" : t ? "" : this.getStyle("bottom"),
8328 "z-index" : this.getStyle("z-index")
8333 * Gets the width of the border(s) for the specified side(s)
8334 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8335 * passing lr would get the border (l)eft width + the border (r)ight width.
8336 * @return {Number} The width of the sides passed added together
8338 getBorderWidth : function(side){
8339 return this.addStyles(side, El.borders);
8343 * Gets the width of the padding(s) for the specified side(s)
8344 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8345 * passing lr would get the padding (l)eft + the padding (r)ight.
8346 * @return {Number} The padding of the sides passed added together
8348 getPadding : function(side){
8349 return this.addStyles(side, El.paddings);
8353 * Set positioning with an object returned by getPositioning().
8354 * @param {Object} posCfg
8355 * @return {Roo.Element} this
8357 setPositioning : function(pc){
8358 this.applyStyles(pc);
8359 if(pc.right == "auto"){
8360 this.dom.style.right = "";
8362 if(pc.bottom == "auto"){
8363 this.dom.style.bottom = "";
8369 fixDisplay : function(){
8370 if(this.getStyle("display") == "none"){
8371 this.setStyle("visibility", "hidden");
8372 this.setStyle("display", this.originalDisplay); // first try reverting to default
8373 if(this.getStyle("display") == "none"){ // if that fails, default to block
8374 this.setStyle("display", "block");
8380 * Quick set left and top adding default units
8381 * @param {String} left The left CSS property value
8382 * @param {String} top The top CSS property value
8383 * @return {Roo.Element} this
8385 setLeftTop : function(left, top){
8386 this.dom.style.left = this.addUnits(left);
8387 this.dom.style.top = this.addUnits(top);
8392 * Move this element relative to its current position.
8393 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8394 * @param {Number} distance How far to move the element in pixels
8395 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8396 * @return {Roo.Element} this
8398 move : function(direction, distance, animate){
8399 var xy = this.getXY();
8400 direction = direction.toLowerCase();
8404 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8408 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8413 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8418 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8425 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8426 * @return {Roo.Element} this
8429 if(!this.isClipped){
8430 this.isClipped = true;
8431 this.originalClip = {
8432 "o": this.getStyle("overflow"),
8433 "x": this.getStyle("overflow-x"),
8434 "y": this.getStyle("overflow-y")
8436 this.setStyle("overflow", "hidden");
8437 this.setStyle("overflow-x", "hidden");
8438 this.setStyle("overflow-y", "hidden");
8444 * Return clipping (overflow) to original clipping before clip() was called
8445 * @return {Roo.Element} this
8447 unclip : function(){
8449 this.isClipped = false;
8450 var o = this.originalClip;
8451 if(o.o){this.setStyle("overflow", o.o);}
8452 if(o.x){this.setStyle("overflow-x", o.x);}
8453 if(o.y){this.setStyle("overflow-y", o.y);}
8460 * Gets the x,y coordinates specified by the anchor position on the element.
8461 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8462 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8463 * {width: (target width), height: (target height)} (defaults to the element's current size)
8464 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8465 * @return {Array} [x, y] An array containing the element's x and y coordinates
8467 getAnchorXY : function(anchor, local, s){
8468 //Passing a different size is useful for pre-calculating anchors,
8469 //especially for anchored animations that change the el size.
8471 var w, h, vp = false;
8474 if(d == document.body || d == document){
8476 w = D.getViewWidth(); h = D.getViewHeight();
8478 w = this.getWidth(); h = this.getHeight();
8481 w = s.width; h = s.height;
8483 var x = 0, y = 0, r = Math.round;
8484 switch((anchor || "tl").toLowerCase()){
8526 var sc = this.getScroll();
8527 return [x + sc.left, y + sc.top];
8529 //Add the element's offset xy
8530 var o = this.getXY();
8531 return [x+o[0], y+o[1]];
8535 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8536 * supported position values.
8537 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8538 * @param {String} position The position to align to.
8539 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8540 * @return {Array} [x, y]
8542 getAlignToXY : function(el, p, o){
8546 throw "Element.alignTo with an element that doesn't exist";
8548 var c = false; //constrain to viewport
8549 var p1 = "", p2 = "";
8556 }else if(p.indexOf("-") == -1){
8559 p = p.toLowerCase();
8560 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8562 throw "Element.alignTo with an invalid alignment " + p;
8564 p1 = m[1]; p2 = m[2]; c = !!m[3];
8566 //Subtract the aligned el's internal xy from the target's offset xy
8567 //plus custom offset to get the aligned el's new offset xy
8568 var a1 = this.getAnchorXY(p1, true);
8569 var a2 = el.getAnchorXY(p2, false);
8570 var x = a2[0] - a1[0] + o[0];
8571 var y = a2[1] - a1[1] + o[1];
8573 //constrain the aligned el to viewport if necessary
8574 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8575 // 5px of margin for ie
8576 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8578 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8579 //perpendicular to the vp border, allow the aligned el to slide on that border,
8580 //otherwise swap the aligned el to the opposite border of the target.
8581 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8582 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8583 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8584 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8587 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8588 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8590 if((x+w) > dw + scrollX){
8591 x = swapX ? r.left-w : dw+scrollX-w;
8594 x = swapX ? r.right : scrollX;
8596 if((y+h) > dh + scrollY){
8597 y = swapY ? r.top-h : dh+scrollY-h;
8600 y = swapY ? r.bottom : scrollY;
8607 getConstrainToXY : function(){
8608 var os = {top:0, left:0, bottom:0, right: 0};
8610 return function(el, local, offsets, proposedXY){
8612 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8614 var vw, vh, vx = 0, vy = 0;
8615 if(el.dom == document.body || el.dom == document){
8616 vw = Roo.lib.Dom.getViewWidth();
8617 vh = Roo.lib.Dom.getViewHeight();
8619 vw = el.dom.clientWidth;
8620 vh = el.dom.clientHeight;
8622 var vxy = el.getXY();
8628 var s = el.getScroll();
8630 vx += offsets.left + s.left;
8631 vy += offsets.top + s.top;
8633 vw -= offsets.right;
8634 vh -= offsets.bottom;
8639 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8640 var x = xy[0], y = xy[1];
8641 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8643 // only move it if it needs it
8646 // first validate right/bottom
8655 // then make sure top/left isn't negative
8664 return moved ? [x, y] : false;
8669 adjustForConstraints : function(xy, parent, offsets){
8670 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8674 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8675 * document it aligns it to the viewport.
8676 * The position parameter is optional, and can be specified in any one of the following formats:
8678 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8679 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8680 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8681 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8682 * <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
8683 * element's anchor point, and the second value is used as the target's anchor point.</li>
8685 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8686 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8687 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8688 * that specified in order to enforce the viewport constraints.
8689 * Following are all of the supported anchor positions:
8692 ----- -----------------------------
8693 tl The top left corner (default)
8694 t The center of the top edge
8695 tr The top right corner
8696 l The center of the left edge
8697 c In the center of the element
8698 r The center of the right edge
8699 bl The bottom left corner
8700 b The center of the bottom edge
8701 br The bottom right corner
8705 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8706 el.alignTo("other-el");
8708 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8709 el.alignTo("other-el", "tr?");
8711 // align the bottom right corner of el with the center left edge of other-el
8712 el.alignTo("other-el", "br-l?");
8714 // align the center of el with the bottom left corner of other-el and
8715 // adjust the x position by -6 pixels (and the y position by 0)
8716 el.alignTo("other-el", "c-bl", [-6, 0]);
8718 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8719 * @param {String} position The position to align to.
8720 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8721 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8722 * @return {Roo.Element} this
8724 alignTo : function(element, position, offsets, animate){
8725 var xy = this.getAlignToXY(element, position, offsets);
8726 this.setXY(xy, this.preanim(arguments, 3));
8731 * Anchors an element to another element and realigns it when the window is resized.
8732 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8733 * @param {String} position The position to align to.
8734 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8735 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8736 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8737 * is a number, it is used as the buffer delay (defaults to 50ms).
8738 * @param {Function} callback The function to call after the animation finishes
8739 * @return {Roo.Element} this
8741 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8742 var action = function(){
8743 this.alignTo(el, alignment, offsets, animate);
8744 Roo.callback(callback, this);
8746 Roo.EventManager.onWindowResize(action, this);
8747 var tm = typeof monitorScroll;
8748 if(tm != 'undefined'){
8749 Roo.EventManager.on(window, 'scroll', action, this,
8750 {buffer: tm == 'number' ? monitorScroll : 50});
8752 action.call(this); // align immediately
8756 * Clears any opacity settings from this element. Required in some cases for IE.
8757 * @return {Roo.Element} this
8759 clearOpacity : function(){
8760 if (window.ActiveXObject) {
8761 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8762 this.dom.style.filter = "";
8765 this.dom.style.opacity = "";
8766 this.dom.style["-moz-opacity"] = "";
8767 this.dom.style["-khtml-opacity"] = "";
8773 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8774 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8775 * @return {Roo.Element} this
8777 hide : function(animate){
8778 this.setVisible(false, this.preanim(arguments, 0));
8783 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8784 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8785 * @return {Roo.Element} this
8787 show : function(animate){
8788 this.setVisible(true, this.preanim(arguments, 0));
8793 * @private Test if size has a unit, otherwise appends the default
8795 addUnits : function(size){
8796 return Roo.Element.addUnits(size, this.defaultUnit);
8800 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8801 * @return {Roo.Element} this
8803 beginMeasure : function(){
8805 if(el.offsetWidth || el.offsetHeight){
8806 return this; // offsets work already
8809 var p = this.dom, b = document.body; // start with this element
8810 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8811 var pe = Roo.get(p);
8812 if(pe.getStyle('display') == 'none'){
8813 changed.push({el: p, visibility: pe.getStyle("visibility")});
8814 p.style.visibility = "hidden";
8815 p.style.display = "block";
8819 this._measureChanged = changed;
8825 * Restores displays to before beginMeasure was called
8826 * @return {Roo.Element} this
8828 endMeasure : function(){
8829 var changed = this._measureChanged;
8831 for(var i = 0, len = changed.length; i < len; i++) {
8833 r.el.style.visibility = r.visibility;
8834 r.el.style.display = "none";
8836 this._measureChanged = null;
8842 * Update the innerHTML of this element, optionally searching for and processing scripts
8843 * @param {String} html The new HTML
8844 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8845 * @param {Function} callback For async script loading you can be noticed when the update completes
8846 * @return {Roo.Element} this
8848 update : function(html, loadScripts, callback){
8849 if(typeof html == "undefined"){
8852 if(loadScripts !== true){
8853 this.dom.innerHTML = html;
8854 if(typeof callback == "function"){
8862 html += '<span id="' + id + '"></span>';
8864 E.onAvailable(id, function(){
8865 var hd = document.getElementsByTagName("head")[0];
8866 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8867 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8868 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8871 while(match = re.exec(html)){
8872 var attrs = match[1];
8873 var srcMatch = attrs ? attrs.match(srcRe) : false;
8874 if(srcMatch && srcMatch[2]){
8875 var s = document.createElement("script");
8876 s.src = srcMatch[2];
8877 var typeMatch = attrs.match(typeRe);
8878 if(typeMatch && typeMatch[2]){
8879 s.type = typeMatch[2];
8882 }else if(match[2] && match[2].length > 0){
8883 if(window.execScript) {
8884 window.execScript(match[2]);
8892 window.eval(match[2]);
8896 var el = document.getElementById(id);
8897 if(el){el.parentNode.removeChild(el);}
8898 if(typeof callback == "function"){
8902 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8907 * Direct access to the UpdateManager update() method (takes the same parameters).
8908 * @param {String/Function} url The url for this request or a function to call to get the url
8909 * @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}
8910 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8911 * @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.
8912 * @return {Roo.Element} this
8915 var um = this.getUpdateManager();
8916 um.update.apply(um, arguments);
8921 * Gets this element's UpdateManager
8922 * @return {Roo.UpdateManager} The UpdateManager
8924 getUpdateManager : function(){
8925 if(!this.updateManager){
8926 this.updateManager = new Roo.UpdateManager(this);
8928 return this.updateManager;
8932 * Disables text selection for this element (normalized across browsers)
8933 * @return {Roo.Element} this
8935 unselectable : function(){
8936 this.dom.unselectable = "on";
8937 this.swallowEvent("selectstart", true);
8938 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8939 this.addClass("x-unselectable");
8944 * Calculates the x, y to center this element on the screen
8945 * @return {Array} The x, y values [x, y]
8947 getCenterXY : function(){
8948 return this.getAlignToXY(document, 'c-c');
8952 * Centers the Element in either the viewport, or another Element.
8953 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8955 center : function(centerIn){
8956 this.alignTo(centerIn || document, 'c-c');
8961 * Tests various css rules/browsers to determine if this element uses a border box
8964 isBorderBox : function(){
8965 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8969 * Return a box {x, y, width, height} that can be used to set another elements
8970 * size/location to match this element.
8971 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8972 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8973 * @return {Object} box An object in the format {x, y, width, height}
8975 getBox : function(contentBox, local){
8980 var left = parseInt(this.getStyle("left"), 10) || 0;
8981 var top = parseInt(this.getStyle("top"), 10) || 0;
8984 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8986 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8988 var l = this.getBorderWidth("l")+this.getPadding("l");
8989 var r = this.getBorderWidth("r")+this.getPadding("r");
8990 var t = this.getBorderWidth("t")+this.getPadding("t");
8991 var b = this.getBorderWidth("b")+this.getPadding("b");
8992 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)};
8994 bx.right = bx.x + bx.width;
8995 bx.bottom = bx.y + bx.height;
9000 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
9001 for more information about the sides.
9002 * @param {String} sides
9005 getFrameWidth : function(sides, onlyContentBox){
9006 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
9010 * 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.
9011 * @param {Object} box The box to fill {x, y, width, height}
9012 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
9013 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9014 * @return {Roo.Element} this
9016 setBox : function(box, adjust, animate){
9017 var w = box.width, h = box.height;
9018 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
9019 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
9020 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
9022 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
9027 * Forces the browser to repaint this element
9028 * @return {Roo.Element} this
9030 repaint : function(){
9032 this.addClass("x-repaint");
9033 setTimeout(function(){
9034 Roo.get(dom).removeClass("x-repaint");
9040 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
9041 * then it returns the calculated width of the sides (see getPadding)
9042 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
9043 * @return {Object/Number}
9045 getMargins : function(side){
9048 top: parseInt(this.getStyle("margin-top"), 10) || 0,
9049 left: parseInt(this.getStyle("margin-left"), 10) || 0,
9050 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
9051 right: parseInt(this.getStyle("margin-right"), 10) || 0
9054 return this.addStyles(side, El.margins);
9059 addStyles : function(sides, styles){
9061 for(var i = 0, len = sides.length; i < len; i++){
9062 v = this.getStyle(styles[sides.charAt(i)]);
9064 w = parseInt(v, 10);
9072 * Creates a proxy element of this element
9073 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
9074 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
9075 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
9076 * @return {Roo.Element} The new proxy element
9078 createProxy : function(config, renderTo, matchBox){
9080 renderTo = Roo.getDom(renderTo);
9082 renderTo = document.body;
9084 config = typeof config == "object" ?
9085 config : {tag : "div", cls: config};
9086 var proxy = Roo.DomHelper.append(renderTo, config, true);
9088 proxy.setBox(this.getBox());
9094 * Puts a mask over this element to disable user interaction. Requires core.css.
9095 * This method can only be applied to elements which accept child nodes.
9096 * @param {String} msg (optional) A message to display in the mask
9097 * @param {String} msgCls (optional) A css class to apply to the msg element
9098 * @return {Element} The mask element
9100 mask : function(msg, msgCls)
9102 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
9103 this.setStyle("position", "relative");
9106 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
9108 this.addClass("x-masked");
9109 this._mask.setDisplayed(true);
9114 while (dom && dom.style) {
9115 if (!isNaN(parseInt(dom.style.zIndex))) {
9116 z = Math.max(z, parseInt(dom.style.zIndex));
9118 dom = dom.parentNode;
9120 // if we are masking the body - then it hides everything..
9121 if (this.dom == document.body) {
9123 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9124 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9127 if(typeof msg == 'string'){
9129 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9131 var mm = this._maskMsg;
9132 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9133 if (mm.dom.firstChild) { // weird IE issue?
9134 mm.dom.firstChild.innerHTML = msg;
9136 mm.setDisplayed(true);
9138 mm.setStyle('z-index', z + 102);
9140 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9141 this._mask.setHeight(this.getHeight());
9143 this._mask.setStyle('z-index', z + 100);
9149 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9150 * it is cached for reuse.
9152 unmask : function(removeEl){
9154 if(removeEl === true){
9155 this._mask.remove();
9158 this._maskMsg.remove();
9159 delete this._maskMsg;
9162 this._mask.setDisplayed(false);
9164 this._maskMsg.setDisplayed(false);
9168 this.removeClass("x-masked");
9172 * Returns true if this element is masked
9175 isMasked : function(){
9176 return this._mask && this._mask.isVisible();
9180 * Creates an iframe shim for this element to keep selects and other windowed objects from
9182 * @return {Roo.Element} The new shim element
9184 createShim : function(){
9185 var el = document.createElement('iframe');
9186 el.frameBorder = 'no';
9187 el.className = 'roo-shim';
9188 if(Roo.isIE && Roo.isSecure){
9189 el.src = Roo.SSL_SECURE_URL;
9191 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9192 shim.autoBoxAdjust = false;
9197 * Removes this element from the DOM and deletes it from the cache
9199 remove : function(){
9200 if(this.dom.parentNode){
9201 this.dom.parentNode.removeChild(this.dom);
9203 delete El.cache[this.dom.id];
9207 * Sets up event handlers to add and remove a css class when the mouse is over this element
9208 * @param {String} className
9209 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9210 * mouseout events for children elements
9211 * @return {Roo.Element} this
9213 addClassOnOver : function(className, preventFlicker){
9214 this.on("mouseover", function(){
9215 Roo.fly(this, '_internal').addClass(className);
9217 var removeFn = function(e){
9218 if(preventFlicker !== true || !e.within(this, true)){
9219 Roo.fly(this, '_internal').removeClass(className);
9222 this.on("mouseout", removeFn, this.dom);
9227 * Sets up event handlers to add and remove a css class when this element has the focus
9228 * @param {String} className
9229 * @return {Roo.Element} this
9231 addClassOnFocus : function(className){
9232 this.on("focus", function(){
9233 Roo.fly(this, '_internal').addClass(className);
9235 this.on("blur", function(){
9236 Roo.fly(this, '_internal').removeClass(className);
9241 * 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)
9242 * @param {String} className
9243 * @return {Roo.Element} this
9245 addClassOnClick : function(className){
9247 this.on("mousedown", function(){
9248 Roo.fly(dom, '_internal').addClass(className);
9249 var d = Roo.get(document);
9250 var fn = function(){
9251 Roo.fly(dom, '_internal').removeClass(className);
9252 d.removeListener("mouseup", fn);
9254 d.on("mouseup", fn);
9260 * Stops the specified event from bubbling and optionally prevents the default action
9261 * @param {String} eventName
9262 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9263 * @return {Roo.Element} this
9265 swallowEvent : function(eventName, preventDefault){
9266 var fn = function(e){
9267 e.stopPropagation();
9272 if(eventName instanceof Array){
9273 for(var i = 0, len = eventName.length; i < len; i++){
9274 this.on(eventName[i], fn);
9278 this.on(eventName, fn);
9285 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9288 * Sizes this element to its parent element's dimensions performing
9289 * neccessary box adjustments.
9290 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9291 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9292 * @return {Roo.Element} this
9294 fitToParent : function(monitorResize, targetParent) {
9295 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9296 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9297 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9300 var p = Roo.get(targetParent || this.dom.parentNode);
9301 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9302 if (monitorResize === true) {
9303 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9304 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9310 * Gets the next sibling, skipping text nodes
9311 * @return {HTMLElement} The next sibling or null
9313 getNextSibling : function(){
9314 var n = this.dom.nextSibling;
9315 while(n && n.nodeType != 1){
9322 * Gets the previous sibling, skipping text nodes
9323 * @return {HTMLElement} The previous sibling or null
9325 getPrevSibling : function(){
9326 var n = this.dom.previousSibling;
9327 while(n && n.nodeType != 1){
9328 n = n.previousSibling;
9335 * Appends the passed element(s) to this element
9336 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9337 * @return {Roo.Element} this
9339 appendChild: function(el){
9346 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9347 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9348 * automatically generated with the specified attributes.
9349 * @param {HTMLElement} insertBefore (optional) a child element of this element
9350 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9351 * @return {Roo.Element} The new child element
9353 createChild: function(config, insertBefore, returnDom){
9354 config = config || {tag:'div'};
9356 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9358 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9362 * Appends this element to the passed element
9363 * @param {String/HTMLElement/Element} el The new parent element
9364 * @return {Roo.Element} this
9366 appendTo: function(el){
9367 el = Roo.getDom(el);
9368 el.appendChild(this.dom);
9373 * Inserts this element before the passed element in the DOM
9374 * @param {String/HTMLElement/Element} el The element to insert before
9375 * @return {Roo.Element} this
9377 insertBefore: function(el){
9378 el = Roo.getDom(el);
9379 el.parentNode.insertBefore(this.dom, el);
9384 * Inserts this element after the passed element in the DOM
9385 * @param {String/HTMLElement/Element} el The element to insert after
9386 * @return {Roo.Element} this
9388 insertAfter: function(el){
9389 el = Roo.getDom(el);
9390 el.parentNode.insertBefore(this.dom, el.nextSibling);
9395 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9396 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9397 * @return {Roo.Element} The new child
9399 insertFirst: function(el, returnDom){
9401 if(typeof el == 'object' && !el.nodeType){ // dh config
9402 return this.createChild(el, this.dom.firstChild, returnDom);
9404 el = Roo.getDom(el);
9405 this.dom.insertBefore(el, this.dom.firstChild);
9406 return !returnDom ? Roo.get(el) : el;
9411 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9412 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9413 * @param {String} where (optional) 'before' or 'after' defaults to before
9414 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9415 * @return {Roo.Element} the inserted Element
9417 insertSibling: function(el, where, returnDom){
9418 where = where ? where.toLowerCase() : 'before';
9420 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9422 if(typeof el == 'object' && !el.nodeType){ // dh config
9423 if(where == 'after' && !this.dom.nextSibling){
9424 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9426 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9430 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9431 where == 'before' ? this.dom : this.dom.nextSibling);
9440 * Creates and wraps this element with another element
9441 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9442 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9443 * @return {HTMLElement/Element} The newly created wrapper element
9445 wrap: function(config, returnDom){
9447 config = {tag: "div"};
9449 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9450 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9455 * Replaces the passed element with this element
9456 * @param {String/HTMLElement/Element} el The element to replace
9457 * @return {Roo.Element} this
9459 replace: function(el){
9461 this.insertBefore(el);
9467 * Inserts an html fragment into this element
9468 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9469 * @param {String} html The HTML fragment
9470 * @param {Boolean} returnEl True to return an Roo.Element
9471 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9473 insertHtml : function(where, html, returnEl){
9474 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9475 return returnEl ? Roo.get(el) : el;
9479 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9480 * @param {Object} o The object with the attributes
9481 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9482 * @return {Roo.Element} this
9484 set : function(o, useSet){
9486 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9488 if(attr == "style" || typeof o[attr] == "function") { continue; }
9490 el.className = o["cls"];
9493 el.setAttribute(attr, o[attr]);
9500 Roo.DomHelper.applyStyles(el, o.style);
9506 * Convenience method for constructing a KeyMap
9507 * @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:
9508 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9509 * @param {Function} fn The function to call
9510 * @param {Object} scope (optional) The scope of the function
9511 * @return {Roo.KeyMap} The KeyMap created
9513 addKeyListener : function(key, fn, scope){
9515 if(typeof key != "object" || key instanceof Array){
9531 return new Roo.KeyMap(this, config);
9535 * Creates a KeyMap for this element
9536 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9537 * @return {Roo.KeyMap} The KeyMap created
9539 addKeyMap : function(config){
9540 return new Roo.KeyMap(this, config);
9544 * Returns true if this element is scrollable.
9547 isScrollable : function(){
9549 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9553 * 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().
9554 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9555 * @param {Number} value The new scroll value
9556 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9557 * @return {Element} this
9560 scrollTo : function(side, value, animate){
9561 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9563 this.dom[prop] = value;
9565 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9566 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9572 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9573 * within this element's scrollable range.
9574 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9575 * @param {Number} distance How far to scroll the element in pixels
9576 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9577 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9578 * was scrolled as far as it could go.
9580 scroll : function(direction, distance, animate){
9581 if(!this.isScrollable()){
9585 var l = el.scrollLeft, t = el.scrollTop;
9586 var w = el.scrollWidth, h = el.scrollHeight;
9587 var cw = el.clientWidth, ch = el.clientHeight;
9588 direction = direction.toLowerCase();
9589 var scrolled = false;
9590 var a = this.preanim(arguments, 2);
9595 var v = Math.min(l + distance, w-cw);
9596 this.scrollTo("left", v, a);
9603 var v = Math.max(l - distance, 0);
9604 this.scrollTo("left", v, a);
9612 var v = Math.max(t - distance, 0);
9613 this.scrollTo("top", v, a);
9621 var v = Math.min(t + distance, h-ch);
9622 this.scrollTo("top", v, a);
9631 * Translates the passed page coordinates into left/top css values for this element
9632 * @param {Number/Array} x The page x or an array containing [x, y]
9633 * @param {Number} y The page y
9634 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9636 translatePoints : function(x, y){
9637 if(typeof x == 'object' || x instanceof Array){
9640 var p = this.getStyle('position');
9641 var o = this.getXY();
9643 var l = parseInt(this.getStyle('left'), 10);
9644 var t = parseInt(this.getStyle('top'), 10);
9647 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9650 t = (p == "relative") ? 0 : this.dom.offsetTop;
9653 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9657 * Returns the current scroll position of the element.
9658 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9660 getScroll : function(){
9661 var d = this.dom, doc = document;
9662 if(d == doc || d == doc.body){
9663 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9664 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9665 return {left: l, top: t};
9667 return {left: d.scrollLeft, top: d.scrollTop};
9672 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9673 * are convert to standard 6 digit hex color.
9674 * @param {String} attr The css attribute
9675 * @param {String} defaultValue The default value to use when a valid color isn't found
9676 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9679 getColor : function(attr, defaultValue, prefix){
9680 var v = this.getStyle(attr);
9681 if(!v || v == "transparent" || v == "inherit") {
9682 return defaultValue;
9684 var color = typeof prefix == "undefined" ? "#" : prefix;
9685 if(v.substr(0, 4) == "rgb("){
9686 var rvs = v.slice(4, v.length -1).split(",");
9687 for(var i = 0; i < 3; i++){
9688 var h = parseInt(rvs[i]).toString(16);
9695 if(v.substr(0, 1) == "#"){
9697 for(var i = 1; i < 4; i++){
9698 var c = v.charAt(i);
9701 }else if(v.length == 7){
9702 color += v.substr(1);
9706 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9710 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9711 * gradient background, rounded corners and a 4-way shadow.
9712 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9713 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9714 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9715 * @return {Roo.Element} this
9717 boxWrap : function(cls){
9718 cls = cls || 'x-box';
9719 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9720 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9725 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9726 * @param {String} namespace The namespace in which to look for the attribute
9727 * @param {String} name The attribute name
9728 * @return {String} The attribute value
9730 getAttributeNS : Roo.isIE ? function(ns, name){
9732 var type = typeof d[ns+":"+name];
9733 if(type != 'undefined' && type != 'unknown'){
9734 return d[ns+":"+name];
9737 } : function(ns, name){
9739 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9744 * Sets or Returns the value the dom attribute value
9745 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9746 * @param {String} value (optional) The value to set the attribute to
9747 * @return {String} The attribute value
9749 attr : function(name){
9750 if (arguments.length > 1) {
9751 this.dom.setAttribute(name, arguments[1]);
9752 return arguments[1];
9754 if (typeof(name) == 'object') {
9755 for(var i in name) {
9756 this.attr(i, name[i]);
9762 if (!this.dom.hasAttribute(name)) {
9765 return this.dom.getAttribute(name);
9772 var ep = El.prototype;
9775 * Appends an event handler (Shorthand for addListener)
9776 * @param {String} eventName The type of event to append
9777 * @param {Function} fn The method the event invokes
9778 * @param {Object} scope (optional) The scope (this object) of the fn
9779 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9782 ep.on = ep.addListener;
9784 ep.mon = ep.addListener;
9787 * Removes an event handler from this element (shorthand for removeListener)
9788 * @param {String} eventName the type of event to remove
9789 * @param {Function} fn the method the event invokes
9790 * @return {Roo.Element} this
9793 ep.un = ep.removeListener;
9796 * true to automatically adjust width and height settings for box-model issues (default to true)
9798 ep.autoBoxAdjust = true;
9801 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9804 El.addUnits = function(v, defaultUnit){
9805 if(v === "" || v == "auto"){
9808 if(v === undefined){
9811 if(typeof v == "number" || !El.unitPattern.test(v)){
9812 return v + (defaultUnit || 'px');
9817 // special markup used throughout Roo when box wrapping elements
9818 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>';
9820 * Visibility mode constant - Use visibility to hide element
9826 * Visibility mode constant - Use display to hide element
9832 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9833 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9834 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9846 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9847 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9848 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9849 * @return {Element} The Element object
9852 El.get = function(el){
9854 if(!el){ return null; }
9855 if(typeof el == "string"){ // element id
9856 if(!(elm = document.getElementById(el))){
9859 if(ex = El.cache[el]){
9862 ex = El.cache[el] = new El(elm);
9865 }else if(el.tagName){ // dom element
9869 if(ex = El.cache[id]){
9872 ex = El.cache[id] = new El(el);
9875 }else if(el instanceof El){
9877 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9878 // catch case where it hasn't been appended
9879 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9882 }else if(el.isComposite){
9884 }else if(el instanceof Array){
9885 return El.select(el);
9886 }else if(el == document){
9887 // create a bogus element object representing the document object
9889 var f = function(){};
9890 f.prototype = El.prototype;
9892 docEl.dom = document;
9900 El.uncache = function(el){
9901 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9903 delete El.cache[a[i].id || a[i]];
9909 // Garbage collection - uncache elements/purge listeners on orphaned elements
9910 // so we don't hold a reference and cause the browser to retain them
9911 El.garbageCollect = function(){
9912 if(!Roo.enableGarbageCollector){
9913 clearInterval(El.collectorThread);
9916 for(var eid in El.cache){
9917 var el = El.cache[eid], d = el.dom;
9918 // -------------------------------------------------------
9919 // Determining what is garbage:
9920 // -------------------------------------------------------
9922 // dom node is null, definitely garbage
9923 // -------------------------------------------------------
9925 // no parentNode == direct orphan, definitely garbage
9926 // -------------------------------------------------------
9927 // !d.offsetParent && !document.getElementById(eid)
9928 // display none elements have no offsetParent so we will
9929 // also try to look it up by it's id. However, check
9930 // offsetParent first so we don't do unneeded lookups.
9931 // This enables collection of elements that are not orphans
9932 // directly, but somewhere up the line they have an orphan
9934 // -------------------------------------------------------
9935 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9936 delete El.cache[eid];
9937 if(d && Roo.enableListenerCollection){
9943 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9947 El.Flyweight = function(dom){
9950 El.Flyweight.prototype = El.prototype;
9952 El._flyweights = {};
9954 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9955 * the dom node can be overwritten by other code.
9956 * @param {String/HTMLElement} el The dom node or id
9957 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9958 * prevent conflicts (e.g. internally Roo uses "_internal")
9960 * @return {Element} The shared Element object
9962 El.fly = function(el, named){
9963 named = named || '_global';
9964 el = Roo.getDom(el);
9968 if(!El._flyweights[named]){
9969 El._flyweights[named] = new El.Flyweight();
9971 El._flyweights[named].dom = el;
9972 return El._flyweights[named];
9976 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9977 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9978 * Shorthand of {@link Roo.Element#get}
9979 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9980 * @return {Element} The Element object
9986 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9987 * the dom node can be overwritten by other code.
9988 * Shorthand of {@link Roo.Element#fly}
9989 * @param {String/HTMLElement} el The dom node or id
9990 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9991 * prevent conflicts (e.g. internally Roo uses "_internal")
9993 * @return {Element} The shared Element object
9999 // speedy lookup for elements never to box adjust
10000 var noBoxAdjust = Roo.isStrict ? {
10003 input:1, select:1, textarea:1
10005 if(Roo.isIE || Roo.isGecko){
10006 noBoxAdjust['button'] = 1;
10010 Roo.EventManager.on(window, 'unload', function(){
10012 delete El._flyweights;
10020 Roo.Element.selectorFunction = Roo.DomQuery.select;
10023 Roo.Element.select = function(selector, unique, root){
10025 if(typeof selector == "string"){
10026 els = Roo.Element.selectorFunction(selector, root);
10027 }else if(selector.length !== undefined){
10030 throw "Invalid selector";
10032 if(unique === true){
10033 return new Roo.CompositeElement(els);
10035 return new Roo.CompositeElementLite(els);
10039 * Selects elements based on the passed CSS selector to enable working on them as 1.
10040 * @param {String/Array} selector The CSS selector or an array of elements
10041 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
10042 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
10043 * @return {CompositeElementLite/CompositeElement}
10047 Roo.select = Roo.Element.select;
10064 * Ext JS Library 1.1.1
10065 * Copyright(c) 2006-2007, Ext JS, LLC.
10067 * Originally Released Under LGPL - original licence link has changed is not relivant.
10070 * <script type="text/javascript">
10075 //Notifies Element that fx methods are available
10076 Roo.enableFx = true;
10080 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
10081 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
10082 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
10083 * Element effects to work.</p><br/>
10085 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
10086 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
10087 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
10088 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
10089 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
10090 * expected results and should be done with care.</p><br/>
10092 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
10093 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
10096 ----- -----------------------------
10097 tl The top left corner
10098 t The center of the top edge
10099 tr The top right corner
10100 l The center of the left edge
10101 r The center of the right edge
10102 bl The bottom left corner
10103 b The center of the bottom edge
10104 br The bottom right corner
10106 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
10107 * below are common options that can be passed to any Fx method.</b>
10108 * @cfg {Function} callback A function called when the effect is finished
10109 * @cfg {Object} scope The scope of the effect function
10110 * @cfg {String} easing A valid Easing value for the effect
10111 * @cfg {String} afterCls A css class to apply after the effect
10112 * @cfg {Number} duration The length of time (in seconds) that the effect should last
10113 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
10114 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
10115 * effects that end with the element being visually hidden, ignored otherwise)
10116 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
10117 * a function which returns such a specification that will be applied to the Element after the effect finishes
10118 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
10119 * @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
10120 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10124 * Slides the element into view. An anchor point can be optionally passed to set the point of
10125 * origin for the slide effect. This function automatically handles wrapping the element with
10126 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10129 // default: slide the element in from the top
10132 // custom: slide the element in from the right with a 2-second duration
10133 el.slideIn('r', { duration: 2 });
10135 // common config options shown with default values
10141 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10142 * @param {Object} options (optional) Object literal with any of the Fx config options
10143 * @return {Roo.Element} The Element
10145 slideIn : function(anchor, o){
10146 var el = this.getFxEl();
10149 el.queueFx(o, function(){
10151 anchor = anchor || "t";
10153 // fix display to visibility
10156 // restore values after effect
10157 var r = this.getFxRestore();
10158 var b = this.getBox();
10159 // fixed size for slide
10163 var wrap = this.fxWrap(r.pos, o, "hidden");
10165 var st = this.dom.style;
10166 st.visibility = "visible";
10167 st.position = "absolute";
10169 // clear out temp styles after slide and unwrap
10170 var after = function(){
10171 el.fxUnwrap(wrap, r.pos, o);
10172 st.width = r.width;
10173 st.height = r.height;
10176 // time to calc the positions
10177 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10179 switch(anchor.toLowerCase()){
10181 wrap.setSize(b.width, 0);
10182 st.left = st.bottom = "0";
10186 wrap.setSize(0, b.height);
10187 st.right = st.top = "0";
10191 wrap.setSize(0, b.height);
10192 wrap.setX(b.right);
10193 st.left = st.top = "0";
10194 a = {width: bw, points: pt};
10197 wrap.setSize(b.width, 0);
10198 wrap.setY(b.bottom);
10199 st.left = st.top = "0";
10200 a = {height: bh, points: pt};
10203 wrap.setSize(0, 0);
10204 st.right = st.bottom = "0";
10205 a = {width: bw, height: bh};
10208 wrap.setSize(0, 0);
10209 wrap.setY(b.y+b.height);
10210 st.right = st.top = "0";
10211 a = {width: bw, height: bh, points: pt};
10214 wrap.setSize(0, 0);
10215 wrap.setXY([b.right, b.bottom]);
10216 st.left = st.top = "0";
10217 a = {width: bw, height: bh, points: pt};
10220 wrap.setSize(0, 0);
10221 wrap.setX(b.x+b.width);
10222 st.left = st.bottom = "0";
10223 a = {width: bw, height: bh, points: pt};
10226 this.dom.style.visibility = "visible";
10229 arguments.callee.anim = wrap.fxanim(a,
10239 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10240 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10241 * 'hidden') but block elements will still take up space in the document. The element must be removed
10242 * from the DOM using the 'remove' config option if desired. This function automatically handles
10243 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10246 // default: slide the element out to the top
10249 // custom: slide the element out to the right with a 2-second duration
10250 el.slideOut('r', { duration: 2 });
10252 // common config options shown with default values
10260 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10261 * @param {Object} options (optional) Object literal with any of the Fx config options
10262 * @return {Roo.Element} The Element
10264 slideOut : function(anchor, o){
10265 var el = this.getFxEl();
10268 el.queueFx(o, function(){
10270 anchor = anchor || "t";
10272 // restore values after effect
10273 var r = this.getFxRestore();
10275 var b = this.getBox();
10276 // fixed size for slide
10280 var wrap = this.fxWrap(r.pos, o, "visible");
10282 var st = this.dom.style;
10283 st.visibility = "visible";
10284 st.position = "absolute";
10288 var after = function(){
10290 el.setDisplayed(false);
10295 el.fxUnwrap(wrap, r.pos, o);
10297 st.width = r.width;
10298 st.height = r.height;
10303 var a, zero = {to: 0};
10304 switch(anchor.toLowerCase()){
10306 st.left = st.bottom = "0";
10307 a = {height: zero};
10310 st.right = st.top = "0";
10314 st.left = st.top = "0";
10315 a = {width: zero, points: {to:[b.right, b.y]}};
10318 st.left = st.top = "0";
10319 a = {height: zero, points: {to:[b.x, b.bottom]}};
10322 st.right = st.bottom = "0";
10323 a = {width: zero, height: zero};
10326 st.right = st.top = "0";
10327 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10330 st.left = st.top = "0";
10331 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10334 st.left = st.bottom = "0";
10335 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10339 arguments.callee.anim = wrap.fxanim(a,
10349 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10350 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10351 * The element must be removed from the DOM using the 'remove' config option if desired.
10357 // common config options shown with default values
10365 * @param {Object} options (optional) Object literal with any of the Fx config options
10366 * @return {Roo.Element} The Element
10368 puff : function(o){
10369 var el = this.getFxEl();
10372 el.queueFx(o, function(){
10373 this.clearOpacity();
10376 // restore values after effect
10377 var r = this.getFxRestore();
10378 var st = this.dom.style;
10380 var after = function(){
10382 el.setDisplayed(false);
10389 el.setPositioning(r.pos);
10390 st.width = r.width;
10391 st.height = r.height;
10396 var width = this.getWidth();
10397 var height = this.getHeight();
10399 arguments.callee.anim = this.fxanim({
10400 width : {to: this.adjustWidth(width * 2)},
10401 height : {to: this.adjustHeight(height * 2)},
10402 points : {by: [-(width * .5), -(height * .5)]},
10404 fontSize: {to:200, unit: "%"}
10415 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10416 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10417 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10423 // all config options shown with default values
10431 * @param {Object} options (optional) Object literal with any of the Fx config options
10432 * @return {Roo.Element} The Element
10434 switchOff : function(o){
10435 var el = this.getFxEl();
10438 el.queueFx(o, function(){
10439 this.clearOpacity();
10442 // restore values after effect
10443 var r = this.getFxRestore();
10444 var st = this.dom.style;
10446 var after = function(){
10448 el.setDisplayed(false);
10454 el.setPositioning(r.pos);
10455 st.width = r.width;
10456 st.height = r.height;
10461 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10462 this.clearOpacity();
10466 points:{by:[0, this.getHeight() * .5]}
10467 }, o, 'motion', 0.3, 'easeIn', after);
10468 }).defer(100, this);
10475 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10476 * changed using the "attr" config option) and then fading back to the original color. If no original
10477 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10480 // default: highlight background to yellow
10483 // custom: highlight foreground text to blue for 2 seconds
10484 el.highlight("0000ff", { attr: 'color', duration: 2 });
10486 // common config options shown with default values
10487 el.highlight("ffff9c", {
10488 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10489 endColor: (current color) or "ffffff",
10494 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10495 * @param {Object} options (optional) Object literal with any of the Fx config options
10496 * @return {Roo.Element} The Element
10498 highlight : function(color, o){
10499 var el = this.getFxEl();
10502 el.queueFx(o, function(){
10503 color = color || "ffff9c";
10504 attr = o.attr || "backgroundColor";
10506 this.clearOpacity();
10509 var origColor = this.getColor(attr);
10510 var restoreColor = this.dom.style[attr];
10511 endColor = (o.endColor || origColor) || "ffffff";
10513 var after = function(){
10514 el.dom.style[attr] = restoreColor;
10519 a[attr] = {from: color, to: endColor};
10520 arguments.callee.anim = this.fxanim(a,
10530 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10533 // default: a single light blue ripple
10536 // custom: 3 red ripples lasting 3 seconds total
10537 el.frame("ff0000", 3, { duration: 3 });
10539 // common config options shown with default values
10540 el.frame("C3DAF9", 1, {
10541 duration: 1 //duration of entire animation (not each individual ripple)
10542 // Note: Easing is not configurable and will be ignored if included
10545 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10546 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10547 * @param {Object} options (optional) Object literal with any of the Fx config options
10548 * @return {Roo.Element} The Element
10550 frame : function(color, count, o){
10551 var el = this.getFxEl();
10554 el.queueFx(o, function(){
10555 color = color || "#C3DAF9";
10556 if(color.length == 6){
10557 color = "#" + color;
10559 count = count || 1;
10560 duration = o.duration || 1;
10563 var b = this.getBox();
10564 var animFn = function(){
10565 var proxy = this.createProxy({
10568 visbility:"hidden",
10569 position:"absolute",
10570 "z-index":"35000", // yee haw
10571 border:"0px solid " + color
10574 var scale = Roo.isBorderBox ? 2 : 1;
10576 top:{from:b.y, to:b.y - 20},
10577 left:{from:b.x, to:b.x - 20},
10578 borderWidth:{from:0, to:10},
10579 opacity:{from:1, to:0},
10580 height:{from:b.height, to:(b.height + (20*scale))},
10581 width:{from:b.width, to:(b.width + (20*scale))}
10582 }, duration, function(){
10586 animFn.defer((duration/2)*1000, this);
10597 * Creates a pause before any subsequent queued effects begin. If there are
10598 * no effects queued after the pause it will have no effect.
10603 * @param {Number} seconds The length of time to pause (in seconds)
10604 * @return {Roo.Element} The Element
10606 pause : function(seconds){
10607 var el = this.getFxEl();
10610 el.queueFx(o, function(){
10611 setTimeout(function(){
10613 }, seconds * 1000);
10619 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10620 * using the "endOpacity" config option.
10623 // default: fade in from opacity 0 to 100%
10626 // custom: fade in from opacity 0 to 75% over 2 seconds
10627 el.fadeIn({ endOpacity: .75, duration: 2});
10629 // common config options shown with default values
10631 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10636 * @param {Object} options (optional) Object literal with any of the Fx config options
10637 * @return {Roo.Element} The Element
10639 fadeIn : function(o){
10640 var el = this.getFxEl();
10642 el.queueFx(o, function(){
10643 this.setOpacity(0);
10645 this.dom.style.visibility = 'visible';
10646 var to = o.endOpacity || 1;
10647 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10648 o, null, .5, "easeOut", function(){
10650 this.clearOpacity();
10659 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10660 * using the "endOpacity" config option.
10663 // default: fade out from the element's current opacity to 0
10666 // custom: fade out from the element's current opacity to 25% over 2 seconds
10667 el.fadeOut({ endOpacity: .25, duration: 2});
10669 // common config options shown with default values
10671 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10678 * @param {Object} options (optional) Object literal with any of the Fx config options
10679 * @return {Roo.Element} The Element
10681 fadeOut : function(o){
10682 var el = this.getFxEl();
10684 el.queueFx(o, function(){
10685 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10686 o, null, .5, "easeOut", function(){
10687 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10688 this.dom.style.display = "none";
10690 this.dom.style.visibility = "hidden";
10692 this.clearOpacity();
10700 * Animates the transition of an element's dimensions from a starting height/width
10701 * to an ending height/width.
10704 // change height and width to 100x100 pixels
10705 el.scale(100, 100);
10707 // common config options shown with default values. The height and width will default to
10708 // the element's existing values if passed as null.
10711 [element's height], {
10716 * @param {Number} width The new width (pass undefined to keep the original width)
10717 * @param {Number} height The new height (pass undefined to keep the original height)
10718 * @param {Object} options (optional) Object literal with any of the Fx config options
10719 * @return {Roo.Element} The Element
10721 scale : function(w, h, o){
10722 this.shift(Roo.apply({}, o, {
10730 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10731 * Any of these properties not specified in the config object will not be changed. This effect
10732 * requires that at least one new dimension, position or opacity setting must be passed in on
10733 * the config object in order for the function to have any effect.
10736 // slide the element horizontally to x position 200 while changing the height and opacity
10737 el.shift({ x: 200, height: 50, opacity: .8 });
10739 // common config options shown with default values.
10741 width: [element's width],
10742 height: [element's height],
10743 x: [element's x position],
10744 y: [element's y position],
10745 opacity: [element's opacity],
10750 * @param {Object} options Object literal with any of the Fx config options
10751 * @return {Roo.Element} The Element
10753 shift : function(o){
10754 var el = this.getFxEl();
10756 el.queueFx(o, function(){
10757 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10758 if(w !== undefined){
10759 a.width = {to: this.adjustWidth(w)};
10761 if(h !== undefined){
10762 a.height = {to: this.adjustHeight(h)};
10764 if(x !== undefined || y !== undefined){
10766 x !== undefined ? x : this.getX(),
10767 y !== undefined ? y : this.getY()
10770 if(op !== undefined){
10771 a.opacity = {to: op};
10773 if(o.xy !== undefined){
10774 a.points = {to: o.xy};
10776 arguments.callee.anim = this.fxanim(a,
10777 o, 'motion', .35, "easeOut", function(){
10785 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10786 * ending point of the effect.
10789 // default: slide the element downward while fading out
10792 // custom: slide the element out to the right with a 2-second duration
10793 el.ghost('r', { duration: 2 });
10795 // common config options shown with default values
10803 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10804 * @param {Object} options (optional) Object literal with any of the Fx config options
10805 * @return {Roo.Element} The Element
10807 ghost : function(anchor, o){
10808 var el = this.getFxEl();
10811 el.queueFx(o, function(){
10812 anchor = anchor || "b";
10814 // restore values after effect
10815 var r = this.getFxRestore();
10816 var w = this.getWidth(),
10817 h = this.getHeight();
10819 var st = this.dom.style;
10821 var after = function(){
10823 el.setDisplayed(false);
10829 el.setPositioning(r.pos);
10830 st.width = r.width;
10831 st.height = r.height;
10836 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10837 switch(anchor.toLowerCase()){
10864 arguments.callee.anim = this.fxanim(a,
10874 * Ensures that all effects queued after syncFx is called on the element are
10875 * run concurrently. This is the opposite of {@link #sequenceFx}.
10876 * @return {Roo.Element} The Element
10878 syncFx : function(){
10879 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10888 * Ensures that all effects queued after sequenceFx is called on the element are
10889 * run in sequence. This is the opposite of {@link #syncFx}.
10890 * @return {Roo.Element} The Element
10892 sequenceFx : function(){
10893 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10895 concurrent : false,
10902 nextFx : function(){
10903 var ef = this.fxQueue[0];
10910 * Returns true if the element has any effects actively running or queued, else returns false.
10911 * @return {Boolean} True if element has active effects, else false
10913 hasActiveFx : function(){
10914 return this.fxQueue && this.fxQueue[0];
10918 * Stops any running effects and clears the element's internal effects queue if it contains
10919 * any additional effects that haven't started yet.
10920 * @return {Roo.Element} The Element
10922 stopFx : function(){
10923 if(this.hasActiveFx()){
10924 var cur = this.fxQueue[0];
10925 if(cur && cur.anim && cur.anim.isAnimated()){
10926 this.fxQueue = [cur]; // clear out others
10927 cur.anim.stop(true);
10934 beforeFx : function(o){
10935 if(this.hasActiveFx() && !o.concurrent){
10946 * Returns true if the element is currently blocking so that no other effect can be queued
10947 * until this effect is finished, else returns false if blocking is not set. This is commonly
10948 * used to ensure that an effect initiated by a user action runs to completion prior to the
10949 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10950 * @return {Boolean} True if blocking, else false
10952 hasFxBlock : function(){
10953 var q = this.fxQueue;
10954 return q && q[0] && q[0].block;
10958 queueFx : function(o, fn){
10962 if(!this.hasFxBlock()){
10963 Roo.applyIf(o, this.fxDefaults);
10965 var run = this.beforeFx(o);
10966 fn.block = o.block;
10967 this.fxQueue.push(fn);
10979 fxWrap : function(pos, o, vis){
10981 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10984 wrapXY = this.getXY();
10986 var div = document.createElement("div");
10987 div.style.visibility = vis;
10988 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10989 wrap.setPositioning(pos);
10990 if(wrap.getStyle("position") == "static"){
10991 wrap.position("relative");
10993 this.clearPositioning('auto');
10995 wrap.dom.appendChild(this.dom);
10997 wrap.setXY(wrapXY);
11004 fxUnwrap : function(wrap, pos, o){
11005 this.clearPositioning();
11006 this.setPositioning(pos);
11008 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
11014 getFxRestore : function(){
11015 var st = this.dom.style;
11016 return {pos: this.getPositioning(), width: st.width, height : st.height};
11020 afterFx : function(o){
11022 this.applyStyles(o.afterStyle);
11025 this.addClass(o.afterCls);
11027 if(o.remove === true){
11030 Roo.callback(o.callback, o.scope, [this]);
11032 this.fxQueue.shift();
11038 getFxEl : function(){ // support for composite element fx
11039 return Roo.get(this.dom);
11043 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
11044 animType = animType || 'run';
11046 var anim = Roo.lib.Anim[animType](
11048 (opt.duration || defaultDur) || .35,
11049 (opt.easing || defaultEase) || 'easeOut',
11051 Roo.callback(cb, this);
11060 // backwords compat
11061 Roo.Fx.resize = Roo.Fx.scale;
11063 //When included, Roo.Fx is automatically applied to Element so that all basic
11064 //effects are available directly via the Element API
11065 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
11067 * Ext JS Library 1.1.1
11068 * Copyright(c) 2006-2007, Ext JS, LLC.
11070 * Originally Released Under LGPL - original licence link has changed is not relivant.
11073 * <script type="text/javascript">
11078 * @class Roo.CompositeElement
11079 * Standard composite class. Creates a Roo.Element for every element in the collection.
11081 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11082 * actions will be performed on all the elements in this collection.</b>
11084 * All methods return <i>this</i> and can be chained.
11086 var els = Roo.select("#some-el div.some-class", true);
11087 // or select directly from an existing element
11088 var el = Roo.get('some-el');
11089 el.select('div.some-class', true);
11091 els.setWidth(100); // all elements become 100 width
11092 els.hide(true); // all elements fade out and hide
11094 els.setWidth(100).hide(true);
11097 Roo.CompositeElement = function(els){
11098 this.elements = [];
11099 this.addElements(els);
11101 Roo.CompositeElement.prototype = {
11103 addElements : function(els){
11107 if(typeof els == "string"){
11108 els = Roo.Element.selectorFunction(els);
11110 var yels = this.elements;
11111 var index = yels.length-1;
11112 for(var i = 0, len = els.length; i < len; i++) {
11113 yels[++index] = Roo.get(els[i]);
11119 * Clears this composite and adds the elements returned by the passed selector.
11120 * @param {String/Array} els A string CSS selector, an array of elements or an element
11121 * @return {CompositeElement} this
11123 fill : function(els){
11124 this.elements = [];
11130 * Filters this composite to only elements that match the passed selector.
11131 * @param {String} selector A string CSS selector
11132 * @param {Boolean} inverse return inverse filter (not matches)
11133 * @return {CompositeElement} this
11135 filter : function(selector, inverse){
11137 inverse = inverse || false;
11138 this.each(function(el){
11139 var match = inverse ? !el.is(selector) : el.is(selector);
11141 els[els.length] = el.dom;
11148 invoke : function(fn, args){
11149 var els = this.elements;
11150 for(var i = 0, len = els.length; i < len; i++) {
11151 Roo.Element.prototype[fn].apply(els[i], args);
11156 * Adds elements to this composite.
11157 * @param {String/Array} els A string CSS selector, an array of elements or an element
11158 * @return {CompositeElement} this
11160 add : function(els){
11161 if(typeof els == "string"){
11162 this.addElements(Roo.Element.selectorFunction(els));
11163 }else if(els.length !== undefined){
11164 this.addElements(els);
11166 this.addElements([els]);
11171 * Calls the passed function passing (el, this, index) for each element in this composite.
11172 * @param {Function} fn The function to call
11173 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11174 * @return {CompositeElement} this
11176 each : function(fn, scope){
11177 var els = this.elements;
11178 for(var i = 0, len = els.length; i < len; i++){
11179 if(fn.call(scope || els[i], els[i], this, i) === false) {
11187 * Returns the Element object at the specified index
11188 * @param {Number} index
11189 * @return {Roo.Element}
11191 item : function(index){
11192 return this.elements[index] || null;
11196 * Returns the first Element
11197 * @return {Roo.Element}
11199 first : function(){
11200 return this.item(0);
11204 * Returns the last Element
11205 * @return {Roo.Element}
11208 return this.item(this.elements.length-1);
11212 * Returns the number of elements in this composite
11215 getCount : function(){
11216 return this.elements.length;
11220 * Returns true if this composite contains the passed element
11223 contains : function(el){
11224 return this.indexOf(el) !== -1;
11228 * Returns true if this composite contains the passed element
11231 indexOf : function(el){
11232 return this.elements.indexOf(Roo.get(el));
11237 * Removes the specified element(s).
11238 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11239 * or an array of any of those.
11240 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11241 * @return {CompositeElement} this
11243 removeElement : function(el, removeDom){
11244 if(el instanceof Array){
11245 for(var i = 0, len = el.length; i < len; i++){
11246 this.removeElement(el[i]);
11250 var index = typeof el == 'number' ? el : this.indexOf(el);
11253 var d = this.elements[index];
11257 d.parentNode.removeChild(d);
11260 this.elements.splice(index, 1);
11266 * Replaces the specified element with the passed element.
11267 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11269 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11270 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11271 * @return {CompositeElement} this
11273 replaceElement : function(el, replacement, domReplace){
11274 var index = typeof el == 'number' ? el : this.indexOf(el);
11277 this.elements[index].replaceWith(replacement);
11279 this.elements.splice(index, 1, Roo.get(replacement))
11286 * Removes all elements.
11288 clear : function(){
11289 this.elements = [];
11293 Roo.CompositeElement.createCall = function(proto, fnName){
11294 if(!proto[fnName]){
11295 proto[fnName] = function(){
11296 return this.invoke(fnName, arguments);
11300 for(var fnName in Roo.Element.prototype){
11301 if(typeof Roo.Element.prototype[fnName] == "function"){
11302 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11308 * Ext JS Library 1.1.1
11309 * Copyright(c) 2006-2007, Ext JS, LLC.
11311 * Originally Released Under LGPL - original licence link has changed is not relivant.
11314 * <script type="text/javascript">
11318 * @class Roo.CompositeElementLite
11319 * @extends Roo.CompositeElement
11320 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11322 var els = Roo.select("#some-el div.some-class");
11323 // or select directly from an existing element
11324 var el = Roo.get('some-el');
11325 el.select('div.some-class');
11327 els.setWidth(100); // all elements become 100 width
11328 els.hide(true); // all elements fade out and hide
11330 els.setWidth(100).hide(true);
11331 </code></pre><br><br>
11332 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11333 * actions will be performed on all the elements in this collection.</b>
11335 Roo.CompositeElementLite = function(els){
11336 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11337 this.el = new Roo.Element.Flyweight();
11339 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11340 addElements : function(els){
11342 if(els instanceof Array){
11343 this.elements = this.elements.concat(els);
11345 var yels = this.elements;
11346 var index = yels.length-1;
11347 for(var i = 0, len = els.length; i < len; i++) {
11348 yels[++index] = els[i];
11354 invoke : function(fn, args){
11355 var els = this.elements;
11357 for(var i = 0, len = els.length; i < len; i++) {
11359 Roo.Element.prototype[fn].apply(el, args);
11364 * Returns a flyweight Element of the dom element object at the specified index
11365 * @param {Number} index
11366 * @return {Roo.Element}
11368 item : function(index){
11369 if(!this.elements[index]){
11372 this.el.dom = this.elements[index];
11376 // fixes scope with flyweight
11377 addListener : function(eventName, handler, scope, opt){
11378 var els = this.elements;
11379 for(var i = 0, len = els.length; i < len; i++) {
11380 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11386 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11387 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11388 * a reference to the dom node, use el.dom.</b>
11389 * @param {Function} fn The function to call
11390 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11391 * @return {CompositeElement} this
11393 each : function(fn, scope){
11394 var els = this.elements;
11396 for(var i = 0, len = els.length; i < len; i++){
11398 if(fn.call(scope || el, el, this, i) === false){
11405 indexOf : function(el){
11406 return this.elements.indexOf(Roo.getDom(el));
11409 replaceElement : function(el, replacement, domReplace){
11410 var index = typeof el == 'number' ? el : this.indexOf(el);
11412 replacement = Roo.getDom(replacement);
11414 var d = this.elements[index];
11415 d.parentNode.insertBefore(replacement, d);
11416 d.parentNode.removeChild(d);
11418 this.elements.splice(index, 1, replacement);
11423 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11427 * Ext JS Library 1.1.1
11428 * Copyright(c) 2006-2007, Ext JS, LLC.
11430 * Originally Released Under LGPL - original licence link has changed is not relivant.
11433 * <script type="text/javascript">
11439 * @class Roo.data.Connection
11440 * @extends Roo.util.Observable
11441 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11442 * either to a configured URL, or to a URL specified at request time.<br><br>
11444 * Requests made by this class are asynchronous, and will return immediately. No data from
11445 * the server will be available to the statement immediately following the {@link #request} call.
11446 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11448 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11449 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11450 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11451 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11452 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11453 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11454 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11455 * standard DOM methods.
11457 * @param {Object} config a configuration object.
11459 Roo.data.Connection = function(config){
11460 Roo.apply(this, config);
11463 * @event beforerequest
11464 * Fires before a network request is made to retrieve a data object.
11465 * @param {Connection} conn This Connection object.
11466 * @param {Object} options The options config object passed to the {@link #request} method.
11468 "beforerequest" : true,
11470 * @event requestcomplete
11471 * Fires if the request was successfully completed.
11472 * @param {Connection} conn This Connection object.
11473 * @param {Object} response The XHR object containing the response data.
11474 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11475 * @param {Object} options The options config object passed to the {@link #request} method.
11477 "requestcomplete" : true,
11479 * @event requestexception
11480 * Fires if an error HTTP status was returned from the server.
11481 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11482 * @param {Connection} conn This Connection object.
11483 * @param {Object} response The XHR object containing the response data.
11484 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11485 * @param {Object} options The options config object passed to the {@link #request} method.
11487 "requestexception" : true
11489 Roo.data.Connection.superclass.constructor.call(this);
11492 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11494 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11497 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11498 * extra parameters to each request made by this object. (defaults to undefined)
11501 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11502 * to each request made by this object. (defaults to undefined)
11505 * @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)
11508 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11512 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11518 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11521 disableCaching: true,
11524 * Sends an HTTP request to a remote server.
11525 * @param {Object} options An object which may contain the following properties:<ul>
11526 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11527 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11528 * request, a url encoded string or a function to call to get either.</li>
11529 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11530 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11531 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11532 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11533 * <li>options {Object} The parameter to the request call.</li>
11534 * <li>success {Boolean} True if the request succeeded.</li>
11535 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11537 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11538 * The callback is passed the following parameters:<ul>
11539 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11540 * <li>options {Object} The parameter to the request call.</li>
11542 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11543 * The callback is passed the following parameters:<ul>
11544 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11545 * <li>options {Object} The parameter to the request call.</li>
11547 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11548 * for the callback function. Defaults to the browser window.</li>
11549 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11550 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11551 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11552 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11553 * params for the post data. Any params will be appended to the URL.</li>
11554 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11556 * @return {Number} transactionId
11558 request : function(o){
11559 if(this.fireEvent("beforerequest", this, o) !== false){
11562 if(typeof p == "function"){
11563 p = p.call(o.scope||window, o);
11565 if(typeof p == "object"){
11566 p = Roo.urlEncode(o.params);
11568 if(this.extraParams){
11569 var extras = Roo.urlEncode(this.extraParams);
11570 p = p ? (p + '&' + extras) : extras;
11573 var url = o.url || this.url;
11574 if(typeof url == 'function'){
11575 url = url.call(o.scope||window, o);
11579 var form = Roo.getDom(o.form);
11580 url = url || form.action;
11582 var enctype = form.getAttribute("enctype");
11583 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11584 return this.doFormUpload(o, p, url);
11586 var f = Roo.lib.Ajax.serializeForm(form);
11587 p = p ? (p + '&' + f) : f;
11590 var hs = o.headers;
11591 if(this.defaultHeaders){
11592 hs = Roo.apply(hs || {}, this.defaultHeaders);
11599 success: this.handleResponse,
11600 failure: this.handleFailure,
11602 argument: {options: o},
11603 timeout : o.timeout || this.timeout
11606 var method = o.method||this.method||(p ? "POST" : "GET");
11608 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11609 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11612 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11616 }else if(this.autoAbort !== false){
11620 if((method == 'GET' && p) || o.xmlData){
11621 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11624 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11625 return this.transId;
11627 Roo.callback(o.callback, o.scope, [o, null, null]);
11633 * Determine whether this object has a request outstanding.
11634 * @param {Number} transactionId (Optional) defaults to the last transaction
11635 * @return {Boolean} True if there is an outstanding request.
11637 isLoading : function(transId){
11639 return Roo.lib.Ajax.isCallInProgress(transId);
11641 return this.transId ? true : false;
11646 * Aborts any outstanding request.
11647 * @param {Number} transactionId (Optional) defaults to the last transaction
11649 abort : function(transId){
11650 if(transId || this.isLoading()){
11651 Roo.lib.Ajax.abort(transId || this.transId);
11656 handleResponse : function(response){
11657 this.transId = false;
11658 var options = response.argument.options;
11659 response.argument = options ? options.argument : null;
11660 this.fireEvent("requestcomplete", this, response, options);
11661 Roo.callback(options.success, options.scope, [response, options]);
11662 Roo.callback(options.callback, options.scope, [options, true, response]);
11666 handleFailure : function(response, e){
11667 this.transId = false;
11668 var options = response.argument.options;
11669 response.argument = options ? options.argument : null;
11670 this.fireEvent("requestexception", this, response, options, e);
11671 Roo.callback(options.failure, options.scope, [response, options]);
11672 Roo.callback(options.callback, options.scope, [options, false, response]);
11676 doFormUpload : function(o, ps, url){
11678 var frame = document.createElement('iframe');
11681 frame.className = 'x-hidden';
11683 frame.src = Roo.SSL_SECURE_URL;
11685 document.body.appendChild(frame);
11688 document.frames[id].name = id;
11691 var form = Roo.getDom(o.form);
11693 form.method = 'POST';
11694 form.enctype = form.encoding = 'multipart/form-data';
11700 if(ps){ // add dynamic params
11702 ps = Roo.urlDecode(ps, false);
11704 if(ps.hasOwnProperty(k)){
11705 hd = document.createElement('input');
11706 hd.type = 'hidden';
11709 form.appendChild(hd);
11716 var r = { // bogus response object
11721 r.argument = o ? o.argument : null;
11726 doc = frame.contentWindow.document;
11728 doc = (frame.contentDocument || window.frames[id].document);
11730 if(doc && doc.body){
11731 r.responseText = doc.body.innerHTML;
11733 if(doc && doc.XMLDocument){
11734 r.responseXML = doc.XMLDocument;
11736 r.responseXML = doc;
11743 Roo.EventManager.removeListener(frame, 'load', cb, this);
11745 this.fireEvent("requestcomplete", this, r, o);
11746 Roo.callback(o.success, o.scope, [r, o]);
11747 Roo.callback(o.callback, o.scope, [o, true, r]);
11749 setTimeout(function(){document.body.removeChild(frame);}, 100);
11752 Roo.EventManager.on(frame, 'load', cb, this);
11755 if(hiddens){ // remove dynamic params
11756 for(var i = 0, len = hiddens.length; i < len; i++){
11757 form.removeChild(hiddens[i]);
11764 * Ext JS Library 1.1.1
11765 * Copyright(c) 2006-2007, Ext JS, LLC.
11767 * Originally Released Under LGPL - original licence link has changed is not relivant.
11770 * <script type="text/javascript">
11774 * Global Ajax request class.
11777 * @extends Roo.data.Connection
11780 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11781 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11782 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11783 * @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)
11784 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11785 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11786 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11788 Roo.Ajax = new Roo.data.Connection({
11797 * Serialize the passed form into a url encoded string
11799 * @param {String/HTMLElement} form
11802 serializeForm : function(form){
11803 return Roo.lib.Ajax.serializeForm(form);
11807 * Ext JS Library 1.1.1
11808 * Copyright(c) 2006-2007, Ext JS, LLC.
11810 * Originally Released Under LGPL - original licence link has changed is not relivant.
11813 * <script type="text/javascript">
11818 * @class Roo.UpdateManager
11819 * @extends Roo.util.Observable
11820 * Provides AJAX-style update for Element object.<br><br>
11823 * // Get it from a Roo.Element object
11824 * var el = Roo.get("foo");
11825 * var mgr = el.getUpdateManager();
11826 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11828 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11830 * // or directly (returns the same UpdateManager instance)
11831 * var mgr = new Roo.UpdateManager("myElementId");
11832 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11833 * mgr.on("update", myFcnNeedsToKnow);
11835 // short handed call directly from the element object
11836 Roo.get("foo").load({
11840 text: "Loading Foo..."
11844 * Create new UpdateManager directly.
11845 * @param {String/HTMLElement/Roo.Element} el The element to update
11846 * @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).
11848 Roo.UpdateManager = function(el, forceNew){
11850 if(!forceNew && el.updateManager){
11851 return el.updateManager;
11854 * The Element object
11855 * @type Roo.Element
11859 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11862 this.defaultUrl = null;
11866 * @event beforeupdate
11867 * Fired before an update is made, return false from your handler and the update is cancelled.
11868 * @param {Roo.Element} el
11869 * @param {String/Object/Function} url
11870 * @param {String/Object} params
11872 "beforeupdate": true,
11875 * Fired after successful update is made.
11876 * @param {Roo.Element} el
11877 * @param {Object} oResponseObject The response Object
11882 * Fired on update failure.
11883 * @param {Roo.Element} el
11884 * @param {Object} oResponseObject The response Object
11888 var d = Roo.UpdateManager.defaults;
11890 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11893 this.sslBlankUrl = d.sslBlankUrl;
11895 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11898 this.disableCaching = d.disableCaching;
11900 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11903 this.indicatorText = d.indicatorText;
11905 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11908 this.showLoadIndicator = d.showLoadIndicator;
11910 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11913 this.timeout = d.timeout;
11916 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11919 this.loadScripts = d.loadScripts;
11922 * Transaction object of current executing transaction
11924 this.transaction = null;
11929 this.autoRefreshProcId = null;
11931 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11934 this.refreshDelegate = this.refresh.createDelegate(this);
11936 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11939 this.updateDelegate = this.update.createDelegate(this);
11941 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11944 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11948 this.successDelegate = this.processSuccess.createDelegate(this);
11952 this.failureDelegate = this.processFailure.createDelegate(this);
11954 if(!this.renderer){
11956 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11958 this.renderer = new Roo.UpdateManager.BasicRenderer();
11961 Roo.UpdateManager.superclass.constructor.call(this);
11964 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11966 * Get the Element this UpdateManager is bound to
11967 * @return {Roo.Element} The element
11969 getEl : function(){
11973 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11974 * @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:
11977 url: "your-url.php",<br/>
11978 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11979 callback: yourFunction,<br/>
11980 scope: yourObject, //(optional scope) <br/>
11981 discardUrl: false, <br/>
11982 nocache: false,<br/>
11983 text: "Loading...",<br/>
11985 scripts: false<br/>
11988 * The only required property is url. The optional properties nocache, text and scripts
11989 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11990 * @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}
11991 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11992 * @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.
11994 update : function(url, params, callback, discardUrl){
11995 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11996 var method = this.method,
11998 if(typeof url == "object"){ // must be config object
12001 params = params || cfg.params;
12002 callback = callback || cfg.callback;
12003 discardUrl = discardUrl || cfg.discardUrl;
12004 if(callback && cfg.scope){
12005 callback = callback.createDelegate(cfg.scope);
12007 if(typeof cfg.method != "undefined"){method = cfg.method;};
12008 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
12009 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
12010 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
12011 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
12013 this.showLoading();
12015 this.defaultUrl = url;
12017 if(typeof url == "function"){
12018 url = url.call(this);
12021 method = method || (params ? "POST" : "GET");
12022 if(method == "GET"){
12023 url = this.prepareUrl(url);
12026 var o = Roo.apply(cfg ||{}, {
12029 success: this.successDelegate,
12030 failure: this.failureDelegate,
12031 callback: undefined,
12032 timeout: (this.timeout*1000),
12033 argument: {"url": url, "form": null, "callback": callback, "params": params}
12035 Roo.log("updated manager called with timeout of " + o.timeout);
12036 this.transaction = Roo.Ajax.request(o);
12041 * 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.
12042 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
12043 * @param {String/HTMLElement} form The form Id or form element
12044 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
12045 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
12046 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
12048 formUpdate : function(form, url, reset, callback){
12049 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
12050 if(typeof url == "function"){
12051 url = url.call(this);
12053 form = Roo.getDom(form);
12054 this.transaction = Roo.Ajax.request({
12057 success: this.successDelegate,
12058 failure: this.failureDelegate,
12059 timeout: (this.timeout*1000),
12060 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
12062 this.showLoading.defer(1, this);
12067 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
12068 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12070 refresh : function(callback){
12071 if(this.defaultUrl == null){
12074 this.update(this.defaultUrl, null, callback, true);
12078 * Set this element to auto refresh.
12079 * @param {Number} interval How often to update (in seconds).
12080 * @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)
12081 * @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}
12082 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12083 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
12085 startAutoRefresh : function(interval, url, params, callback, refreshNow){
12087 this.update(url || this.defaultUrl, params, callback, true);
12089 if(this.autoRefreshProcId){
12090 clearInterval(this.autoRefreshProcId);
12092 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
12096 * Stop auto refresh on this element.
12098 stopAutoRefresh : function(){
12099 if(this.autoRefreshProcId){
12100 clearInterval(this.autoRefreshProcId);
12101 delete this.autoRefreshProcId;
12105 isAutoRefreshing : function(){
12106 return this.autoRefreshProcId ? true : false;
12109 * Called to update the element to "Loading" state. Override to perform custom action.
12111 showLoading : function(){
12112 if(this.showLoadIndicator){
12113 this.el.update(this.indicatorText);
12118 * Adds unique parameter to query string if disableCaching = true
12121 prepareUrl : function(url){
12122 if(this.disableCaching){
12123 var append = "_dc=" + (new Date().getTime());
12124 if(url.indexOf("?") !== -1){
12125 url += "&" + append;
12127 url += "?" + append;
12136 processSuccess : function(response){
12137 this.transaction = null;
12138 if(response.argument.form && response.argument.reset){
12139 try{ // put in try/catch since some older FF releases had problems with this
12140 response.argument.form.reset();
12143 if(this.loadScripts){
12144 this.renderer.render(this.el, response, this,
12145 this.updateComplete.createDelegate(this, [response]));
12147 this.renderer.render(this.el, response, this);
12148 this.updateComplete(response);
12152 updateComplete : function(response){
12153 this.fireEvent("update", this.el, response);
12154 if(typeof response.argument.callback == "function"){
12155 response.argument.callback(this.el, true, response);
12162 processFailure : function(response){
12163 this.transaction = null;
12164 this.fireEvent("failure", this.el, response);
12165 if(typeof response.argument.callback == "function"){
12166 response.argument.callback(this.el, false, response);
12171 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12172 * @param {Object} renderer The object implementing the render() method
12174 setRenderer : function(renderer){
12175 this.renderer = renderer;
12178 getRenderer : function(){
12179 return this.renderer;
12183 * Set the defaultUrl used for updates
12184 * @param {String/Function} defaultUrl The url or a function to call to get the url
12186 setDefaultUrl : function(defaultUrl){
12187 this.defaultUrl = defaultUrl;
12191 * Aborts the executing transaction
12193 abort : function(){
12194 if(this.transaction){
12195 Roo.Ajax.abort(this.transaction);
12200 * Returns true if an update is in progress
12201 * @return {Boolean}
12203 isUpdating : function(){
12204 if(this.transaction){
12205 return Roo.Ajax.isLoading(this.transaction);
12212 * @class Roo.UpdateManager.defaults
12213 * @static (not really - but it helps the doc tool)
12214 * The defaults collection enables customizing the default properties of UpdateManager
12216 Roo.UpdateManager.defaults = {
12218 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12224 * True to process scripts by default (Defaults to false).
12227 loadScripts : false,
12230 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12233 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12235 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12238 disableCaching : false,
12240 * Whether to show indicatorText when loading (Defaults to true).
12243 showLoadIndicator : true,
12245 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12248 indicatorText : '<div class="loading-indicator">Loading...</div>'
12252 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12254 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12255 * @param {String/HTMLElement/Roo.Element} el The element to update
12256 * @param {String} url The url
12257 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12258 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12261 * @member Roo.UpdateManager
12263 Roo.UpdateManager.updateElement = function(el, url, params, options){
12264 var um = Roo.get(el, true).getUpdateManager();
12265 Roo.apply(um, options);
12266 um.update(url, params, options ? options.callback : null);
12268 // alias for backwards compat
12269 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12271 * @class Roo.UpdateManager.BasicRenderer
12272 * Default Content renderer. Updates the elements innerHTML with the responseText.
12274 Roo.UpdateManager.BasicRenderer = function(){};
12276 Roo.UpdateManager.BasicRenderer.prototype = {
12278 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12279 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12280 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12281 * @param {Roo.Element} el The element being rendered
12282 * @param {Object} response The YUI Connect response object
12283 * @param {UpdateManager} updateManager The calling update manager
12284 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12286 render : function(el, response, updateManager, callback){
12287 el.update(response.responseText, updateManager.loadScripts, callback);
12293 * (c)) Alan Knowles
12299 * @class Roo.DomTemplate
12300 * @extends Roo.Template
12301 * An effort at a dom based template engine..
12303 * Similar to XTemplate, except it uses dom parsing to create the template..
12305 * Supported features:
12310 {a_variable} - output encoded.
12311 {a_variable.format:("Y-m-d")} - call a method on the variable
12312 {a_variable:raw} - unencoded output
12313 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12314 {a_variable:this.method_on_template(...)} - call a method on the template object.
12319 <div roo-for="a_variable or condition.."></div>
12320 <div roo-if="a_variable or condition"></div>
12321 <div roo-exec="some javascript"></div>
12322 <div roo-name="named_template"></div>
12327 Roo.DomTemplate = function()
12329 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12336 Roo.extend(Roo.DomTemplate, Roo.Template, {
12338 * id counter for sub templates.
12342 * flag to indicate if dom parser is inside a pre,
12343 * it will strip whitespace if not.
12348 * The various sub templates
12356 * basic tag replacing syntax
12359 * // you can fake an object call by doing this
12363 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12364 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12366 iterChild : function (node, method) {
12368 var oldPre = this.inPre;
12369 if (node.tagName == 'PRE') {
12372 for( var i = 0; i < node.childNodes.length; i++) {
12373 method.call(this, node.childNodes[i]);
12375 this.inPre = oldPre;
12381 * compile the template
12383 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12386 compile: function()
12390 // covert the html into DOM...
12394 doc = document.implementation.createHTMLDocument("");
12395 doc.documentElement.innerHTML = this.html ;
12396 div = doc.documentElement;
12398 // old IE... - nasty -- it causes all sorts of issues.. with
12399 // images getting pulled from server..
12400 div = document.createElement('div');
12401 div.innerHTML = this.html;
12403 //doc.documentElement.innerHTML = htmlBody
12409 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12411 var tpls = this.tpls;
12413 // create a top level template from the snippet..
12415 //Roo.log(div.innerHTML);
12422 body : div.innerHTML,
12435 Roo.each(tpls, function(tp){
12436 this.compileTpl(tp);
12437 this.tpls[tp.id] = tp;
12440 this.master = tpls[0];
12446 compileNode : function(node, istop) {
12451 // skip anything not a tag..
12452 if (node.nodeType != 1) {
12453 if (node.nodeType == 3 && !this.inPre) {
12454 // reduce white space..
12455 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12478 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12479 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12480 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12481 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12487 // just itterate children..
12488 this.iterChild(node,this.compileNode);
12491 tpl.uid = this.id++;
12492 tpl.value = node.getAttribute('roo-' + tpl.attr);
12493 node.removeAttribute('roo-'+ tpl.attr);
12494 if (tpl.attr != 'name') {
12495 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12496 node.parentNode.replaceChild(placeholder, node);
12499 var placeholder = document.createElement('span');
12500 placeholder.className = 'roo-tpl-' + tpl.value;
12501 node.parentNode.replaceChild(placeholder, node);
12504 // parent now sees '{domtplXXXX}
12505 this.iterChild(node,this.compileNode);
12507 // we should now have node body...
12508 var div = document.createElement('div');
12509 div.appendChild(node);
12511 // this has the unfortunate side effect of converting tagged attributes
12512 // eg. href="{...}" into %7C...%7D
12513 // this has been fixed by searching for those combo's although it's a bit hacky..
12516 tpl.body = div.innerHTML;
12523 switch (tpl.value) {
12524 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12525 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12526 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12531 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12535 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12539 tpl.id = tpl.value; // replace non characters???
12545 this.tpls.push(tpl);
12555 * Compile a segment of the template into a 'sub-template'
12561 compileTpl : function(tpl)
12563 var fm = Roo.util.Format;
12564 var useF = this.disableFormats !== true;
12566 var sep = Roo.isGecko ? "+\n" : ",\n";
12568 var undef = function(str) {
12569 Roo.debug && Roo.log("Property not found :" + str);
12573 //Roo.log(tpl.body);
12577 var fn = function(m, lbrace, name, format, args)
12580 //Roo.log(arguments);
12581 args = args ? args.replace(/\\'/g,"'") : args;
12582 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12583 if (typeof(format) == 'undefined') {
12584 format = 'htmlEncode';
12586 if (format == 'raw' ) {
12590 if(name.substr(0, 6) == 'domtpl'){
12591 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12594 // build an array of options to determine if value is undefined..
12596 // basically get 'xxxx.yyyy' then do
12597 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12598 // (function () { Roo.log("Property not found"); return ''; })() :
12603 Roo.each(name.split('.'), function(st) {
12604 lookfor += (lookfor.length ? '.': '') + st;
12605 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12608 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12611 if(format && useF){
12613 args = args ? ',' + args : "";
12615 if(format.substr(0, 5) != "this."){
12616 format = "fm." + format + '(';
12618 format = 'this.call("'+ format.substr(5) + '", ';
12622 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12625 if (args && args.length) {
12626 // called with xxyx.yuu:(test,test)
12628 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12630 // raw.. - :raw modifier..
12631 return "'"+ sep + udef_st + name + ")"+sep+"'";
12635 // branched to use + in gecko and [].join() in others
12637 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12638 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12641 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12642 body.push(tpl.body.replace(/(\r\n|\n)/g,
12643 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12644 body.push("'].join('');};};");
12645 body = body.join('');
12648 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12650 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12657 * same as applyTemplate, except it's done to one of the subTemplates
12658 * when using named templates, you can do:
12660 * var str = pl.applySubTemplate('your-name', values);
12663 * @param {Number} id of the template
12664 * @param {Object} values to apply to template
12665 * @param {Object} parent (normaly the instance of this object)
12667 applySubTemplate : function(id, values, parent)
12671 var t = this.tpls[id];
12675 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12676 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12680 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12687 if(t.execCall && t.execCall.call(this, values, parent)){
12691 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12697 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12698 parent = t.target ? values : parent;
12699 if(t.forCall && vs instanceof Array){
12701 for(var i = 0, len = vs.length; i < len; i++){
12703 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12705 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12707 //Roo.log(t.compiled);
12711 return buf.join('');
12714 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12719 return t.compiled.call(this, vs, parent);
12721 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12723 //Roo.log(t.compiled);
12731 applyTemplate : function(values){
12732 return this.master.compiled.call(this, values, {});
12733 //var s = this.subs;
12736 apply : function(){
12737 return this.applyTemplate.apply(this, arguments);
12742 Roo.DomTemplate.from = function(el){
12743 el = Roo.getDom(el);
12744 return new Roo.Domtemplate(el.value || el.innerHTML);
12747 * Ext JS Library 1.1.1
12748 * Copyright(c) 2006-2007, Ext JS, LLC.
12750 * Originally Released Under LGPL - original licence link has changed is not relivant.
12753 * <script type="text/javascript">
12757 * @class Roo.util.DelayedTask
12758 * Provides a convenient method of performing setTimeout where a new
12759 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12760 * You can use this class to buffer
12761 * the keypress events for a certain number of milliseconds, and perform only if they stop
12762 * for that amount of time.
12763 * @constructor The parameters to this constructor serve as defaults and are not required.
12764 * @param {Function} fn (optional) The default function to timeout
12765 * @param {Object} scope (optional) The default scope of that timeout
12766 * @param {Array} args (optional) The default Array of arguments
12768 Roo.util.DelayedTask = function(fn, scope, args){
12769 var id = null, d, t;
12771 var call = function(){
12772 var now = new Date().getTime();
12776 fn.apply(scope, args || []);
12780 * Cancels any pending timeout and queues a new one
12781 * @param {Number} delay The milliseconds to delay
12782 * @param {Function} newFn (optional) Overrides function passed to constructor
12783 * @param {Object} newScope (optional) Overrides scope passed to constructor
12784 * @param {Array} newArgs (optional) Overrides args passed to constructor
12786 this.delay = function(delay, newFn, newScope, newArgs){
12787 if(id && delay != d){
12791 t = new Date().getTime();
12793 scope = newScope || scope;
12794 args = newArgs || args;
12796 id = setInterval(call, d);
12801 * Cancel the last queued timeout
12803 this.cancel = function(){
12811 * Ext JS Library 1.1.1
12812 * Copyright(c) 2006-2007, Ext JS, LLC.
12814 * Originally Released Under LGPL - original licence link has changed is not relivant.
12817 * <script type="text/javascript">
12821 Roo.util.TaskRunner = function(interval){
12822 interval = interval || 10;
12823 var tasks = [], removeQueue = [];
12825 var running = false;
12827 var stopThread = function(){
12833 var startThread = function(){
12836 id = setInterval(runTasks, interval);
12840 var removeTask = function(task){
12841 removeQueue.push(task);
12847 var runTasks = function(){
12848 if(removeQueue.length > 0){
12849 for(var i = 0, len = removeQueue.length; i < len; i++){
12850 tasks.remove(removeQueue[i]);
12853 if(tasks.length < 1){
12858 var now = new Date().getTime();
12859 for(var i = 0, len = tasks.length; i < len; ++i){
12861 var itime = now - t.taskRunTime;
12862 if(t.interval <= itime){
12863 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12864 t.taskRunTime = now;
12865 if(rt === false || t.taskRunCount === t.repeat){
12870 if(t.duration && t.duration <= (now - t.taskStartTime)){
12877 * Queues a new task.
12878 * @param {Object} task
12880 this.start = function(task){
12882 task.taskStartTime = new Date().getTime();
12883 task.taskRunTime = 0;
12884 task.taskRunCount = 0;
12889 this.stop = function(task){
12894 this.stopAll = function(){
12896 for(var i = 0, len = tasks.length; i < len; i++){
12897 if(tasks[i].onStop){
12906 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12908 * Ext JS Library 1.1.1
12909 * Copyright(c) 2006-2007, Ext JS, LLC.
12911 * Originally Released Under LGPL - original licence link has changed is not relivant.
12914 * <script type="text/javascript">
12919 * @class Roo.util.MixedCollection
12920 * @extends Roo.util.Observable
12921 * A Collection class that maintains both numeric indexes and keys and exposes events.
12923 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12924 * collection (defaults to false)
12925 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12926 * and return the key value for that item. This is used when available to look up the key on items that
12927 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12928 * equivalent to providing an implementation for the {@link #getKey} method.
12930 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12938 * Fires when the collection is cleared.
12943 * Fires when an item is added to the collection.
12944 * @param {Number} index The index at which the item was added.
12945 * @param {Object} o The item added.
12946 * @param {String} key The key associated with the added item.
12951 * Fires when an item is replaced in the collection.
12952 * @param {String} key he key associated with the new added.
12953 * @param {Object} old The item being replaced.
12954 * @param {Object} new The new item.
12959 * Fires when an item is removed from the collection.
12960 * @param {Object} o The item being removed.
12961 * @param {String} key (optional) The key associated with the removed item.
12966 this.allowFunctions = allowFunctions === true;
12968 this.getKey = keyFn;
12970 Roo.util.MixedCollection.superclass.constructor.call(this);
12973 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12974 allowFunctions : false,
12977 * Adds an item to the collection.
12978 * @param {String} key The key to associate with the item
12979 * @param {Object} o The item to add.
12980 * @return {Object} The item added.
12982 add : function(key, o){
12983 if(arguments.length == 1){
12985 key = this.getKey(o);
12987 if(typeof key == "undefined" || key === null){
12989 this.items.push(o);
12990 this.keys.push(null);
12992 var old = this.map[key];
12994 return this.replace(key, o);
12997 this.items.push(o);
12999 this.keys.push(key);
13001 this.fireEvent("add", this.length-1, o, key);
13006 * MixedCollection has a generic way to fetch keys if you implement getKey.
13009 var mc = new Roo.util.MixedCollection();
13010 mc.add(someEl.dom.id, someEl);
13011 mc.add(otherEl.dom.id, otherEl);
13015 var mc = new Roo.util.MixedCollection();
13016 mc.getKey = function(el){
13022 // or via the constructor
13023 var mc = new Roo.util.MixedCollection(false, function(el){
13029 * @param o {Object} The item for which to find the key.
13030 * @return {Object} The key for the passed item.
13032 getKey : function(o){
13037 * Replaces an item in the collection.
13038 * @param {String} key The key associated with the item to replace, or the item to replace.
13039 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
13040 * @return {Object} The new item.
13042 replace : function(key, o){
13043 if(arguments.length == 1){
13045 key = this.getKey(o);
13047 var old = this.item(key);
13048 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
13049 return this.add(key, o);
13051 var index = this.indexOfKey(key);
13052 this.items[index] = o;
13054 this.fireEvent("replace", key, old, o);
13059 * Adds all elements of an Array or an Object to the collection.
13060 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
13061 * an Array of values, each of which are added to the collection.
13063 addAll : function(objs){
13064 if(arguments.length > 1 || objs instanceof Array){
13065 var args = arguments.length > 1 ? arguments : objs;
13066 for(var i = 0, len = args.length; i < len; i++){
13070 for(var key in objs){
13071 if(this.allowFunctions || typeof objs[key] != "function"){
13072 this.add(key, objs[key]);
13079 * Executes the specified function once for every item in the collection, passing each
13080 * item as the first and only parameter. returning false from the function will stop the iteration.
13081 * @param {Function} fn The function to execute for each item.
13082 * @param {Object} scope (optional) The scope in which to execute the function.
13084 each : function(fn, scope){
13085 var items = [].concat(this.items); // each safe for removal
13086 for(var i = 0, len = items.length; i < len; i++){
13087 if(fn.call(scope || items[i], items[i], i, len) === false){
13094 * Executes the specified function once for every key in the collection, passing each
13095 * key, and its associated item as the first two parameters.
13096 * @param {Function} fn The function to execute for each item.
13097 * @param {Object} scope (optional) The scope in which to execute the function.
13099 eachKey : function(fn, scope){
13100 for(var i = 0, len = this.keys.length; i < len; i++){
13101 fn.call(scope || window, this.keys[i], this.items[i], i, len);
13106 * Returns the first item in the collection which elicits a true return value from the
13107 * passed selection function.
13108 * @param {Function} fn The selection function to execute for each item.
13109 * @param {Object} scope (optional) The scope in which to execute the function.
13110 * @return {Object} The first item in the collection which returned true from the selection function.
13112 find : function(fn, scope){
13113 for(var i = 0, len = this.items.length; i < len; i++){
13114 if(fn.call(scope || window, this.items[i], this.keys[i])){
13115 return this.items[i];
13122 * Inserts an item at the specified index in the collection.
13123 * @param {Number} index The index to insert the item at.
13124 * @param {String} key The key to associate with the new item, or the item itself.
13125 * @param {Object} o (optional) If the second parameter was a key, the new item.
13126 * @return {Object} The item inserted.
13128 insert : function(index, key, o){
13129 if(arguments.length == 2){
13131 key = this.getKey(o);
13133 if(index >= this.length){
13134 return this.add(key, o);
13137 this.items.splice(index, 0, o);
13138 if(typeof key != "undefined" && key != null){
13141 this.keys.splice(index, 0, key);
13142 this.fireEvent("add", index, o, key);
13147 * Removed an item from the collection.
13148 * @param {Object} o The item to remove.
13149 * @return {Object} The item removed.
13151 remove : function(o){
13152 return this.removeAt(this.indexOf(o));
13156 * Remove an item from a specified index in the collection.
13157 * @param {Number} index The index within the collection of the item to remove.
13159 removeAt : function(index){
13160 if(index < this.length && index >= 0){
13162 var o = this.items[index];
13163 this.items.splice(index, 1);
13164 var key = this.keys[index];
13165 if(typeof key != "undefined"){
13166 delete this.map[key];
13168 this.keys.splice(index, 1);
13169 this.fireEvent("remove", o, key);
13174 * Removed an item associated with the passed key fom the collection.
13175 * @param {String} key The key of the item to remove.
13177 removeKey : function(key){
13178 return this.removeAt(this.indexOfKey(key));
13182 * Returns the number of items in the collection.
13183 * @return {Number} the number of items in the collection.
13185 getCount : function(){
13186 return this.length;
13190 * Returns index within the collection of the passed Object.
13191 * @param {Object} o The item to find the index of.
13192 * @return {Number} index of the item.
13194 indexOf : function(o){
13195 if(!this.items.indexOf){
13196 for(var i = 0, len = this.items.length; i < len; i++){
13197 if(this.items[i] == o) {
13203 return this.items.indexOf(o);
13208 * Returns index within the collection of the passed key.
13209 * @param {String} key The key to find the index of.
13210 * @return {Number} index of the key.
13212 indexOfKey : function(key){
13213 if(!this.keys.indexOf){
13214 for(var i = 0, len = this.keys.length; i < len; i++){
13215 if(this.keys[i] == key) {
13221 return this.keys.indexOf(key);
13226 * Returns the item associated with the passed key OR index. Key has priority over index.
13227 * @param {String/Number} key The key or index of the item.
13228 * @return {Object} The item associated with the passed key.
13230 item : function(key){
13231 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13232 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13236 * Returns the item at the specified index.
13237 * @param {Number} index The index of the item.
13240 itemAt : function(index){
13241 return this.items[index];
13245 * Returns the item associated with the passed key.
13246 * @param {String/Number} key The key of the item.
13247 * @return {Object} The item associated with the passed key.
13249 key : function(key){
13250 return this.map[key];
13254 * Returns true if the collection contains the passed Object as an item.
13255 * @param {Object} o The Object to look for in the collection.
13256 * @return {Boolean} True if the collection contains the Object as an item.
13258 contains : function(o){
13259 return this.indexOf(o) != -1;
13263 * Returns true if the collection contains the passed Object as a key.
13264 * @param {String} key The key to look for in the collection.
13265 * @return {Boolean} True if the collection contains the Object as a key.
13267 containsKey : function(key){
13268 return typeof this.map[key] != "undefined";
13272 * Removes all items from the collection.
13274 clear : function(){
13279 this.fireEvent("clear");
13283 * Returns the first item in the collection.
13284 * @return {Object} the first item in the collection..
13286 first : function(){
13287 return this.items[0];
13291 * Returns the last item in the collection.
13292 * @return {Object} the last item in the collection..
13295 return this.items[this.length-1];
13298 _sort : function(property, dir, fn){
13299 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13300 fn = fn || function(a, b){
13303 var c = [], k = this.keys, items = this.items;
13304 for(var i = 0, len = items.length; i < len; i++){
13305 c[c.length] = {key: k[i], value: items[i], index: i};
13307 c.sort(function(a, b){
13308 var v = fn(a[property], b[property]) * dsc;
13310 v = (a.index < b.index ? -1 : 1);
13314 for(var i = 0, len = c.length; i < len; i++){
13315 items[i] = c[i].value;
13318 this.fireEvent("sort", this);
13322 * Sorts this collection with the passed comparison function
13323 * @param {String} direction (optional) "ASC" or "DESC"
13324 * @param {Function} fn (optional) comparison function
13326 sort : function(dir, fn){
13327 this._sort("value", dir, fn);
13331 * Sorts this collection by keys
13332 * @param {String} direction (optional) "ASC" or "DESC"
13333 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13335 keySort : function(dir, fn){
13336 this._sort("key", dir, fn || function(a, b){
13337 return String(a).toUpperCase()-String(b).toUpperCase();
13342 * Returns a range of items in this collection
13343 * @param {Number} startIndex (optional) defaults to 0
13344 * @param {Number} endIndex (optional) default to the last item
13345 * @return {Array} An array of items
13347 getRange : function(start, end){
13348 var items = this.items;
13349 if(items.length < 1){
13352 start = start || 0;
13353 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13356 for(var i = start; i <= end; i++) {
13357 r[r.length] = items[i];
13360 for(var i = start; i >= end; i--) {
13361 r[r.length] = items[i];
13368 * Filter the <i>objects</i> in this collection by a specific property.
13369 * Returns a new collection that has been filtered.
13370 * @param {String} property A property on your objects
13371 * @param {String/RegExp} value Either string that the property values
13372 * should start with or a RegExp to test against the property
13373 * @return {MixedCollection} The new filtered collection
13375 filter : function(property, value){
13376 if(!value.exec){ // not a regex
13377 value = String(value);
13378 if(value.length == 0){
13379 return this.clone();
13381 value = new RegExp("^" + Roo.escapeRe(value), "i");
13383 return this.filterBy(function(o){
13384 return o && value.test(o[property]);
13389 * Filter by a function. * Returns a new collection that has been filtered.
13390 * The passed function will be called with each
13391 * object in the collection. If the function returns true, the value is included
13392 * otherwise it is filtered.
13393 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13394 * @param {Object} scope (optional) The scope of the function (defaults to this)
13395 * @return {MixedCollection} The new filtered collection
13397 filterBy : function(fn, scope){
13398 var r = new Roo.util.MixedCollection();
13399 r.getKey = this.getKey;
13400 var k = this.keys, it = this.items;
13401 for(var i = 0, len = it.length; i < len; i++){
13402 if(fn.call(scope||this, it[i], k[i])){
13403 r.add(k[i], it[i]);
13410 * Creates a duplicate of this collection
13411 * @return {MixedCollection}
13413 clone : function(){
13414 var r = new Roo.util.MixedCollection();
13415 var k = this.keys, it = this.items;
13416 for(var i = 0, len = it.length; i < len; i++){
13417 r.add(k[i], it[i]);
13419 r.getKey = this.getKey;
13424 * Returns the item associated with the passed key or index.
13426 * @param {String/Number} key The key or index of the item.
13427 * @return {Object} The item associated with the passed key.
13429 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13431 * Ext JS Library 1.1.1
13432 * Copyright(c) 2006-2007, Ext JS, LLC.
13434 * Originally Released Under LGPL - original licence link has changed is not relivant.
13437 * <script type="text/javascript">
13440 * @class Roo.util.JSON
13441 * Modified version of Douglas Crockford"s json.js that doesn"t
13442 * mess with the Object prototype
13443 * http://www.json.org/js.html
13446 Roo.util.JSON = new (function(){
13447 var useHasOwn = {}.hasOwnProperty ? true : false;
13449 // crashes Safari in some instances
13450 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13452 var pad = function(n) {
13453 return n < 10 ? "0" + n : n;
13466 var encodeString = function(s){
13467 if (/["\\\x00-\x1f]/.test(s)) {
13468 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13473 c = b.charCodeAt();
13475 Math.floor(c / 16).toString(16) +
13476 (c % 16).toString(16);
13479 return '"' + s + '"';
13482 var encodeArray = function(o){
13483 var a = ["["], b, i, l = o.length, v;
13484 for (i = 0; i < l; i += 1) {
13486 switch (typeof v) {
13495 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13503 var encodeDate = function(o){
13504 return '"' + o.getFullYear() + "-" +
13505 pad(o.getMonth() + 1) + "-" +
13506 pad(o.getDate()) + "T" +
13507 pad(o.getHours()) + ":" +
13508 pad(o.getMinutes()) + ":" +
13509 pad(o.getSeconds()) + '"';
13513 * Encodes an Object, Array or other value
13514 * @param {Mixed} o The variable to encode
13515 * @return {String} The JSON string
13517 this.encode = function(o)
13519 // should this be extended to fully wrap stringify..
13521 if(typeof o == "undefined" || o === null){
13523 }else if(o instanceof Array){
13524 return encodeArray(o);
13525 }else if(o instanceof Date){
13526 return encodeDate(o);
13527 }else if(typeof o == "string"){
13528 return encodeString(o);
13529 }else if(typeof o == "number"){
13530 return isFinite(o) ? String(o) : "null";
13531 }else if(typeof o == "boolean"){
13534 var a = ["{"], b, i, v;
13536 if(!useHasOwn || o.hasOwnProperty(i)) {
13538 switch (typeof v) {
13547 a.push(this.encode(i), ":",
13548 v === null ? "null" : this.encode(v));
13559 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13560 * @param {String} json The JSON string
13561 * @return {Object} The resulting object
13563 this.decode = function(json){
13565 return /** eval:var:json */ eval("(" + json + ')');
13569 * Shorthand for {@link Roo.util.JSON#encode}
13570 * @member Roo encode
13572 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13574 * Shorthand for {@link Roo.util.JSON#decode}
13575 * @member Roo decode
13577 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13580 * Ext JS Library 1.1.1
13581 * Copyright(c) 2006-2007, Ext JS, LLC.
13583 * Originally Released Under LGPL - original licence link has changed is not relivant.
13586 * <script type="text/javascript">
13590 * @class Roo.util.Format
13591 * Reusable data formatting functions
13594 Roo.util.Format = function(){
13595 var trimRe = /^\s+|\s+$/g;
13598 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13599 * @param {String} value The string to truncate
13600 * @param {Number} length The maximum length to allow before truncating
13601 * @return {String} The converted text
13603 ellipsis : function(value, len){
13604 if(value && value.length > len){
13605 return value.substr(0, len-3)+"...";
13611 * Checks a reference and converts it to empty string if it is undefined
13612 * @param {Mixed} value Reference to check
13613 * @return {Mixed} Empty string if converted, otherwise the original value
13615 undef : function(value){
13616 return typeof value != "undefined" ? value : "";
13620 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13621 * @param {String} value The string to encode
13622 * @return {String} The encoded text
13624 htmlEncode : function(value){
13625 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13629 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13630 * @param {String} value The string to decode
13631 * @return {String} The decoded text
13633 htmlDecode : function(value){
13634 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13638 * Trims any whitespace from either side of a string
13639 * @param {String} value The text to trim
13640 * @return {String} The trimmed text
13642 trim : function(value){
13643 return String(value).replace(trimRe, "");
13647 * Returns a substring from within an original string
13648 * @param {String} value The original text
13649 * @param {Number} start The start index of the substring
13650 * @param {Number} length The length of the substring
13651 * @return {String} The substring
13653 substr : function(value, start, length){
13654 return String(value).substr(start, length);
13658 * Converts a string to all lower case letters
13659 * @param {String} value The text to convert
13660 * @return {String} The converted text
13662 lowercase : function(value){
13663 return String(value).toLowerCase();
13667 * Converts a string to all upper case letters
13668 * @param {String} value The text to convert
13669 * @return {String} The converted text
13671 uppercase : function(value){
13672 return String(value).toUpperCase();
13676 * Converts the first character only of a string to upper case
13677 * @param {String} value The text to convert
13678 * @return {String} The converted text
13680 capitalize : function(value){
13681 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13685 call : function(value, fn){
13686 if(arguments.length > 2){
13687 var args = Array.prototype.slice.call(arguments, 2);
13688 args.unshift(value);
13690 return /** eval:var:value */ eval(fn).apply(window, args);
13692 /** eval:var:value */
13693 return /** eval:var:value */ eval(fn).call(window, value);
13699 * safer version of Math.toFixed..??/
13700 * @param {Number/String} value The numeric value to format
13701 * @param {Number/String} value Decimal places
13702 * @return {String} The formatted currency string
13704 toFixed : function(v, n)
13706 // why not use to fixed - precision is buggered???
13708 return Math.round(v-0);
13710 var fact = Math.pow(10,n+1);
13711 v = (Math.round((v-0)*fact))/fact;
13712 var z = (''+fact).substring(2);
13713 if (v == Math.floor(v)) {
13714 return Math.floor(v) + '.' + z;
13717 // now just padd decimals..
13718 var ps = String(v).split('.');
13719 var fd = (ps[1] + z);
13720 var r = fd.substring(0,n);
13721 var rm = fd.substring(n);
13723 return ps[0] + '.' + r;
13725 r*=1; // turn it into a number;
13727 if (String(r).length != n) {
13730 r = String(r).substring(1); // chop the end off.
13733 return ps[0] + '.' + r;
13738 * Format a number as US currency
13739 * @param {Number/String} value The numeric value to format
13740 * @return {String} The formatted currency string
13742 usMoney : function(v){
13743 return '$' + Roo.util.Format.number(v);
13748 * eventually this should probably emulate php's number_format
13749 * @param {Number/String} value The numeric value to format
13750 * @param {Number} decimals number of decimal places
13751 * @return {String} The formatted currency string
13753 number : function(v,decimals)
13755 // multiply and round.
13756 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13757 var mul = Math.pow(10, decimals);
13758 var zero = String(mul).substring(1);
13759 v = (Math.round((v-0)*mul))/mul;
13761 // if it's '0' number.. then
13763 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13765 var ps = v.split('.');
13769 var r = /(\d+)(\d{3})/;
13771 while (r.test(whole)) {
13772 whole = whole.replace(r, '$1' + ',' + '$2');
13778 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13779 // does not have decimals
13780 (decimals ? ('.' + zero) : '');
13783 return whole + sub ;
13787 * Parse a value into a formatted date using the specified format pattern.
13788 * @param {Mixed} value The value to format
13789 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13790 * @return {String} The formatted date string
13792 date : function(v, format){
13796 if(!(v instanceof Date)){
13797 v = new Date(Date.parse(v));
13799 return v.dateFormat(format || Roo.util.Format.defaults.date);
13803 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13804 * @param {String} format Any valid date format string
13805 * @return {Function} The date formatting function
13807 dateRenderer : function(format){
13808 return function(v){
13809 return Roo.util.Format.date(v, format);
13814 stripTagsRE : /<\/?[^>]+>/gi,
13817 * Strips all HTML tags
13818 * @param {Mixed} value The text from which to strip tags
13819 * @return {String} The stripped text
13821 stripTags : function(v){
13822 return !v ? v : String(v).replace(this.stripTagsRE, "");
13826 Roo.util.Format.defaults = {
13830 * Ext JS Library 1.1.1
13831 * Copyright(c) 2006-2007, Ext JS, LLC.
13833 * Originally Released Under LGPL - original licence link has changed is not relivant.
13836 * <script type="text/javascript">
13843 * @class Roo.MasterTemplate
13844 * @extends Roo.Template
13845 * Provides a template that can have child templates. The syntax is:
13847 var t = new Roo.MasterTemplate(
13848 '<select name="{name}">',
13849 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13852 t.add('options', {value: 'foo', text: 'bar'});
13853 // or you can add multiple child elements in one shot
13854 t.addAll('options', [
13855 {value: 'foo', text: 'bar'},
13856 {value: 'foo2', text: 'bar2'},
13857 {value: 'foo3', text: 'bar3'}
13859 // then append, applying the master template values
13860 t.append('my-form', {name: 'my-select'});
13862 * A name attribute for the child template is not required if you have only one child
13863 * template or you want to refer to them by index.
13865 Roo.MasterTemplate = function(){
13866 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13867 this.originalHtml = this.html;
13869 var m, re = this.subTemplateRe;
13872 while(m = re.exec(this.html)){
13873 var name = m[1], content = m[2];
13878 tpl : new Roo.Template(content)
13881 st[name] = st[subIndex];
13883 st[subIndex].tpl.compile();
13884 st[subIndex].tpl.call = this.call.createDelegate(this);
13887 this.subCount = subIndex;
13890 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13892 * The regular expression used to match sub templates
13896 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13899 * Applies the passed values to a child template.
13900 * @param {String/Number} name (optional) The name or index of the child template
13901 * @param {Array/Object} values The values to be applied to the template
13902 * @return {MasterTemplate} this
13904 add : function(name, values){
13905 if(arguments.length == 1){
13906 values = arguments[0];
13909 var s = this.subs[name];
13910 s.buffer[s.buffer.length] = s.tpl.apply(values);
13915 * Applies all the passed values to a child template.
13916 * @param {String/Number} name (optional) The name or index of the child template
13917 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13918 * @param {Boolean} reset (optional) True to reset the template first
13919 * @return {MasterTemplate} this
13921 fill : function(name, values, reset){
13923 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13931 for(var i = 0, len = values.length; i < len; i++){
13932 this.add(name, values[i]);
13938 * Resets the template for reuse
13939 * @return {MasterTemplate} this
13941 reset : function(){
13943 for(var i = 0; i < this.subCount; i++){
13949 applyTemplate : function(values){
13951 var replaceIndex = -1;
13952 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13953 return s[++replaceIndex].buffer.join("");
13955 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13958 apply : function(){
13959 return this.applyTemplate.apply(this, arguments);
13962 compile : function(){return this;}
13966 * Alias for fill().
13969 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13971 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13972 * var tpl = Roo.MasterTemplate.from('element-id');
13973 * @param {String/HTMLElement} el
13974 * @param {Object} config
13977 Roo.MasterTemplate.from = function(el, config){
13978 el = Roo.getDom(el);
13979 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13982 * Ext JS Library 1.1.1
13983 * Copyright(c) 2006-2007, Ext JS, LLC.
13985 * Originally Released Under LGPL - original licence link has changed is not relivant.
13988 * <script type="text/javascript">
13993 * @class Roo.util.CSS
13994 * Utility class for manipulating CSS rules
13997 Roo.util.CSS = function(){
13999 var doc = document;
14001 var camelRe = /(-[a-z])/gi;
14002 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
14006 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
14007 * tag and appended to the HEAD of the document.
14008 * @param {String|Object} cssText The text containing the css rules
14009 * @param {String} id An id to add to the stylesheet for later removal
14010 * @return {StyleSheet}
14012 createStyleSheet : function(cssText, id){
14014 var head = doc.getElementsByTagName("head")[0];
14015 var nrules = doc.createElement("style");
14016 nrules.setAttribute("type", "text/css");
14018 nrules.setAttribute("id", id);
14020 if (typeof(cssText) != 'string') {
14021 // support object maps..
14022 // not sure if this a good idea..
14023 // perhaps it should be merged with the general css handling
14024 // and handle js style props.
14025 var cssTextNew = [];
14026 for(var n in cssText) {
14028 for(var k in cssText[n]) {
14029 citems.push( k + ' : ' +cssText[n][k] + ';' );
14031 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
14034 cssText = cssTextNew.join("\n");
14040 head.appendChild(nrules);
14041 ss = nrules.styleSheet;
14042 ss.cssText = cssText;
14045 nrules.appendChild(doc.createTextNode(cssText));
14047 nrules.cssText = cssText;
14049 head.appendChild(nrules);
14050 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
14052 this.cacheStyleSheet(ss);
14057 * Removes a style or link tag by id
14058 * @param {String} id The id of the tag
14060 removeStyleSheet : function(id){
14061 var existing = doc.getElementById(id);
14063 existing.parentNode.removeChild(existing);
14068 * Dynamically swaps an existing stylesheet reference for a new one
14069 * @param {String} id The id of an existing link tag to remove
14070 * @param {String} url The href of the new stylesheet to include
14072 swapStyleSheet : function(id, url){
14073 this.removeStyleSheet(id);
14074 var ss = doc.createElement("link");
14075 ss.setAttribute("rel", "stylesheet");
14076 ss.setAttribute("type", "text/css");
14077 ss.setAttribute("id", id);
14078 ss.setAttribute("href", url);
14079 doc.getElementsByTagName("head")[0].appendChild(ss);
14083 * Refresh the rule cache if you have dynamically added stylesheets
14084 * @return {Object} An object (hash) of rules indexed by selector
14086 refreshCache : function(){
14087 return this.getRules(true);
14091 cacheStyleSheet : function(stylesheet){
14095 try{// try catch for cross domain access issue
14096 var ssRules = stylesheet.cssRules || stylesheet.rules;
14097 for(var j = ssRules.length-1; j >= 0; --j){
14098 rules[ssRules[j].selectorText] = ssRules[j];
14104 * Gets all css rules for the document
14105 * @param {Boolean} refreshCache true to refresh the internal cache
14106 * @return {Object} An object (hash) of rules indexed by selector
14108 getRules : function(refreshCache){
14109 if(rules == null || refreshCache){
14111 var ds = doc.styleSheets;
14112 for(var i =0, len = ds.length; i < len; i++){
14114 this.cacheStyleSheet(ds[i]);
14122 * Gets an an individual CSS rule by selector(s)
14123 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
14124 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
14125 * @return {CSSRule} The CSS rule or null if one is not found
14127 getRule : function(selector, refreshCache){
14128 var rs = this.getRules(refreshCache);
14129 if(!(selector instanceof Array)){
14130 return rs[selector];
14132 for(var i = 0; i < selector.length; i++){
14133 if(rs[selector[i]]){
14134 return rs[selector[i]];
14142 * Updates a rule property
14143 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14144 * @param {String} property The css property
14145 * @param {String} value The new value for the property
14146 * @return {Boolean} true If a rule was found and updated
14148 updateRule : function(selector, property, value){
14149 if(!(selector instanceof Array)){
14150 var rule = this.getRule(selector);
14152 rule.style[property.replace(camelRe, camelFn)] = value;
14156 for(var i = 0; i < selector.length; i++){
14157 if(this.updateRule(selector[i], property, value)){
14167 * Ext JS Library 1.1.1
14168 * Copyright(c) 2006-2007, Ext JS, LLC.
14170 * Originally Released Under LGPL - original licence link has changed is not relivant.
14173 * <script type="text/javascript">
14179 * @class Roo.util.ClickRepeater
14180 * @extends Roo.util.Observable
14182 * A wrapper class which can be applied to any element. Fires a "click" event while the
14183 * mouse is pressed. The interval between firings may be specified in the config but
14184 * defaults to 10 milliseconds.
14186 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14188 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14189 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14190 * Similar to an autorepeat key delay.
14191 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14192 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14193 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14194 * "interval" and "delay" are ignored. "immediate" is honored.
14195 * @cfg {Boolean} preventDefault True to prevent the default click event
14196 * @cfg {Boolean} stopDefault True to stop the default click event
14199 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14200 * 2007-02-02 jvs Renamed to ClickRepeater
14201 * 2007-02-03 jvs Modifications for FF Mac and Safari
14204 * @param {String/HTMLElement/Element} el The element to listen on
14205 * @param {Object} config
14207 Roo.util.ClickRepeater = function(el, config)
14209 this.el = Roo.get(el);
14210 this.el.unselectable();
14212 Roo.apply(this, config);
14217 * Fires when the mouse button is depressed.
14218 * @param {Roo.util.ClickRepeater} this
14220 "mousedown" : true,
14223 * Fires on a specified interval during the time the element is pressed.
14224 * @param {Roo.util.ClickRepeater} this
14229 * Fires when the mouse key is released.
14230 * @param {Roo.util.ClickRepeater} this
14235 this.el.on("mousedown", this.handleMouseDown, this);
14236 if(this.preventDefault || this.stopDefault){
14237 this.el.on("click", function(e){
14238 if(this.preventDefault){
14239 e.preventDefault();
14241 if(this.stopDefault){
14247 // allow inline handler
14249 this.on("click", this.handler, this.scope || this);
14252 Roo.util.ClickRepeater.superclass.constructor.call(this);
14255 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14258 preventDefault : true,
14259 stopDefault : false,
14263 handleMouseDown : function(){
14264 clearTimeout(this.timer);
14266 if(this.pressClass){
14267 this.el.addClass(this.pressClass);
14269 this.mousedownTime = new Date();
14271 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14272 this.el.on("mouseout", this.handleMouseOut, this);
14274 this.fireEvent("mousedown", this);
14275 this.fireEvent("click", this);
14277 this.timer = this.click.defer(this.delay || this.interval, this);
14281 click : function(){
14282 this.fireEvent("click", this);
14283 this.timer = this.click.defer(this.getInterval(), this);
14287 getInterval: function(){
14288 if(!this.accelerate){
14289 return this.interval;
14291 var pressTime = this.mousedownTime.getElapsed();
14292 if(pressTime < 500){
14294 }else if(pressTime < 1700){
14296 }else if(pressTime < 2600){
14298 }else if(pressTime < 3500){
14300 }else if(pressTime < 4400){
14302 }else if(pressTime < 5300){
14304 }else if(pressTime < 6200){
14312 handleMouseOut : function(){
14313 clearTimeout(this.timer);
14314 if(this.pressClass){
14315 this.el.removeClass(this.pressClass);
14317 this.el.on("mouseover", this.handleMouseReturn, this);
14321 handleMouseReturn : function(){
14322 this.el.un("mouseover", this.handleMouseReturn);
14323 if(this.pressClass){
14324 this.el.addClass(this.pressClass);
14330 handleMouseUp : function(){
14331 clearTimeout(this.timer);
14332 this.el.un("mouseover", this.handleMouseReturn);
14333 this.el.un("mouseout", this.handleMouseOut);
14334 Roo.get(document).un("mouseup", this.handleMouseUp);
14335 this.el.removeClass(this.pressClass);
14336 this.fireEvent("mouseup", this);
14340 * Ext JS Library 1.1.1
14341 * Copyright(c) 2006-2007, Ext JS, LLC.
14343 * Originally Released Under LGPL - original licence link has changed is not relivant.
14346 * <script type="text/javascript">
14351 * @class Roo.KeyNav
14352 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14353 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14354 * way to implement custom navigation schemes for any UI component.</p>
14355 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14356 * pageUp, pageDown, del, home, end. Usage:</p>
14358 var nav = new Roo.KeyNav("my-element", {
14359 "left" : function(e){
14360 this.moveLeft(e.ctrlKey);
14362 "right" : function(e){
14363 this.moveRight(e.ctrlKey);
14365 "enter" : function(e){
14372 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14373 * @param {Object} config The config
14375 Roo.KeyNav = function(el, config){
14376 this.el = Roo.get(el);
14377 Roo.apply(this, config);
14378 if(!this.disabled){
14379 this.disabled = true;
14384 Roo.KeyNav.prototype = {
14386 * @cfg {Boolean} disabled
14387 * True to disable this KeyNav instance (defaults to false)
14391 * @cfg {String} defaultEventAction
14392 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14393 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14394 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14396 defaultEventAction: "stopEvent",
14398 * @cfg {Boolean} forceKeyDown
14399 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14400 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14401 * handle keydown instead of keypress.
14403 forceKeyDown : false,
14406 prepareEvent : function(e){
14407 var k = e.getKey();
14408 var h = this.keyToHandler[k];
14409 //if(h && this[h]){
14410 // e.stopPropagation();
14412 if(Roo.isSafari && h && k >= 37 && k <= 40){
14418 relay : function(e){
14419 var k = e.getKey();
14420 var h = this.keyToHandler[k];
14422 if(this.doRelay(e, this[h], h) !== true){
14423 e[this.defaultEventAction]();
14429 doRelay : function(e, h, hname){
14430 return h.call(this.scope || this, e);
14433 // possible handlers
14447 // quick lookup hash
14464 * Enable this KeyNav
14466 enable: function(){
14468 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14469 // the EventObject will normalize Safari automatically
14470 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14471 this.el.on("keydown", this.relay, this);
14473 this.el.on("keydown", this.prepareEvent, this);
14474 this.el.on("keypress", this.relay, this);
14476 this.disabled = false;
14481 * Disable this KeyNav
14483 disable: function(){
14484 if(!this.disabled){
14485 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14486 this.el.un("keydown", this.relay);
14488 this.el.un("keydown", this.prepareEvent);
14489 this.el.un("keypress", this.relay);
14491 this.disabled = true;
14496 * Ext JS Library 1.1.1
14497 * Copyright(c) 2006-2007, Ext JS, LLC.
14499 * Originally Released Under LGPL - original licence link has changed is not relivant.
14502 * <script type="text/javascript">
14507 * @class Roo.KeyMap
14508 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14509 * The constructor accepts the same config object as defined by {@link #addBinding}.
14510 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14511 * combination it will call the function with this signature (if the match is a multi-key
14512 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14513 * A KeyMap can also handle a string representation of keys.<br />
14516 // map one key by key code
14517 var map = new Roo.KeyMap("my-element", {
14518 key: 13, // or Roo.EventObject.ENTER
14523 // map multiple keys to one action by string
14524 var map = new Roo.KeyMap("my-element", {
14530 // map multiple keys to multiple actions by strings and array of codes
14531 var map = new Roo.KeyMap("my-element", [
14534 fn: function(){ alert("Return was pressed"); }
14537 fn: function(){ alert('a, b or c was pressed'); }
14542 fn: function(){ alert('Control + shift + tab was pressed.'); }
14546 * <b>Note: A KeyMap starts enabled</b>
14548 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14549 * @param {Object} config The config (see {@link #addBinding})
14550 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14552 Roo.KeyMap = function(el, config, eventName){
14553 this.el = Roo.get(el);
14554 this.eventName = eventName || "keydown";
14555 this.bindings = [];
14557 this.addBinding(config);
14562 Roo.KeyMap.prototype = {
14564 * True to stop the event from bubbling and prevent the default browser action if the
14565 * key was handled by the KeyMap (defaults to false)
14571 * Add a new binding to this KeyMap. The following config object properties are supported:
14573 Property Type Description
14574 ---------- --------------- ----------------------------------------------------------------------
14575 key String/Array A single keycode or an array of keycodes to handle
14576 shift Boolean True to handle key only when shift is pressed (defaults to false)
14577 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14578 alt Boolean True to handle key only when alt is pressed (defaults to false)
14579 fn Function The function to call when KeyMap finds the expected key combination
14580 scope Object The scope of the callback function
14586 var map = new Roo.KeyMap(document, {
14587 key: Roo.EventObject.ENTER,
14592 //Add a new binding to the existing KeyMap later
14600 * @param {Object/Array} config A single KeyMap config or an array of configs
14602 addBinding : function(config){
14603 if(config instanceof Array){
14604 for(var i = 0, len = config.length; i < len; i++){
14605 this.addBinding(config[i]);
14609 var keyCode = config.key,
14610 shift = config.shift,
14611 ctrl = config.ctrl,
14614 scope = config.scope;
14615 if(typeof keyCode == "string"){
14617 var keyString = keyCode.toUpperCase();
14618 for(var j = 0, len = keyString.length; j < len; j++){
14619 ks.push(keyString.charCodeAt(j));
14623 var keyArray = keyCode instanceof Array;
14624 var handler = function(e){
14625 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14626 var k = e.getKey();
14628 for(var i = 0, len = keyCode.length; i < len; i++){
14629 if(keyCode[i] == k){
14630 if(this.stopEvent){
14633 fn.call(scope || window, k, e);
14639 if(this.stopEvent){
14642 fn.call(scope || window, k, e);
14647 this.bindings.push(handler);
14651 * Shorthand for adding a single key listener
14652 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14653 * following options:
14654 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14655 * @param {Function} fn The function to call
14656 * @param {Object} scope (optional) The scope of the function
14658 on : function(key, fn, scope){
14659 var keyCode, shift, ctrl, alt;
14660 if(typeof key == "object" && !(key instanceof Array)){
14679 handleKeyDown : function(e){
14680 if(this.enabled){ //just in case
14681 var b = this.bindings;
14682 for(var i = 0, len = b.length; i < len; i++){
14683 b[i].call(this, e);
14689 * Returns true if this KeyMap is enabled
14690 * @return {Boolean}
14692 isEnabled : function(){
14693 return this.enabled;
14697 * Enables this KeyMap
14699 enable: function(){
14701 this.el.on(this.eventName, this.handleKeyDown, this);
14702 this.enabled = true;
14707 * Disable this KeyMap
14709 disable: function(){
14711 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14712 this.enabled = false;
14717 * Ext JS Library 1.1.1
14718 * Copyright(c) 2006-2007, Ext JS, LLC.
14720 * Originally Released Under LGPL - original licence link has changed is not relivant.
14723 * <script type="text/javascript">
14728 * @class Roo.util.TextMetrics
14729 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14730 * wide, in pixels, a given block of text will be.
14733 Roo.util.TextMetrics = function(){
14737 * Measures the size of the specified text
14738 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14739 * that can affect the size of the rendered text
14740 * @param {String} text The text to measure
14741 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14742 * in order to accurately measure the text height
14743 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14745 measure : function(el, text, fixedWidth){
14747 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14750 shared.setFixedWidth(fixedWidth || 'auto');
14751 return shared.getSize(text);
14755 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14756 * the overhead of multiple calls to initialize the style properties on each measurement.
14757 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14758 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14759 * in order to accurately measure the text height
14760 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14762 createInstance : function(el, fixedWidth){
14763 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14770 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14771 var ml = new Roo.Element(document.createElement('div'));
14772 document.body.appendChild(ml.dom);
14773 ml.position('absolute');
14774 ml.setLeftTop(-1000, -1000);
14778 ml.setWidth(fixedWidth);
14783 * Returns the size of the specified text based on the internal element's style and width properties
14784 * @memberOf Roo.util.TextMetrics.Instance#
14785 * @param {String} text The text to measure
14786 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14788 getSize : function(text){
14790 var s = ml.getSize();
14796 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14797 * that can affect the size of the rendered text
14798 * @memberOf Roo.util.TextMetrics.Instance#
14799 * @param {String/HTMLElement} el The element, dom node or id
14801 bind : function(el){
14803 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14808 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14809 * to set a fixed width in order to accurately measure the text height.
14810 * @memberOf Roo.util.TextMetrics.Instance#
14811 * @param {Number} width The width to set on the element
14813 setFixedWidth : function(width){
14814 ml.setWidth(width);
14818 * Returns the measured width of the specified text
14819 * @memberOf Roo.util.TextMetrics.Instance#
14820 * @param {String} text The text to measure
14821 * @return {Number} width The width in pixels
14823 getWidth : function(text){
14824 ml.dom.style.width = 'auto';
14825 return this.getSize(text).width;
14829 * Returns the measured height of the specified text. For multiline text, be sure to call
14830 * {@link #setFixedWidth} if necessary.
14831 * @memberOf Roo.util.TextMetrics.Instance#
14832 * @param {String} text The text to measure
14833 * @return {Number} height The height in pixels
14835 getHeight : function(text){
14836 return this.getSize(text).height;
14840 instance.bind(bindTo);
14845 // backwards compat
14846 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14848 * Ext JS Library 1.1.1
14849 * Copyright(c) 2006-2007, Ext JS, LLC.
14851 * Originally Released Under LGPL - original licence link has changed is not relivant.
14854 * <script type="text/javascript">
14858 * @class Roo.state.Provider
14859 * Abstract base class for state provider implementations. This class provides methods
14860 * for encoding and decoding <b>typed</b> variables including dates and defines the
14861 * Provider interface.
14863 Roo.state.Provider = function(){
14865 * @event statechange
14866 * Fires when a state change occurs.
14867 * @param {Provider} this This state provider
14868 * @param {String} key The state key which was changed
14869 * @param {String} value The encoded value for the state
14872 "statechange": true
14875 Roo.state.Provider.superclass.constructor.call(this);
14877 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14879 * Returns the current value for a key
14880 * @param {String} name The key name
14881 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14882 * @return {Mixed} The state data
14884 get : function(name, defaultValue){
14885 return typeof this.state[name] == "undefined" ?
14886 defaultValue : this.state[name];
14890 * Clears a value from the state
14891 * @param {String} name The key name
14893 clear : function(name){
14894 delete this.state[name];
14895 this.fireEvent("statechange", this, name, null);
14899 * Sets the value for a key
14900 * @param {String} name The key name
14901 * @param {Mixed} value The value to set
14903 set : function(name, value){
14904 this.state[name] = value;
14905 this.fireEvent("statechange", this, name, value);
14909 * Decodes a string previously encoded with {@link #encodeValue}.
14910 * @param {String} value The value to decode
14911 * @return {Mixed} The decoded value
14913 decodeValue : function(cookie){
14914 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14915 var matches = re.exec(unescape(cookie));
14916 if(!matches || !matches[1]) {
14917 return; // non state cookie
14919 var type = matches[1];
14920 var v = matches[2];
14923 return parseFloat(v);
14925 return new Date(Date.parse(v));
14930 var values = v.split("^");
14931 for(var i = 0, len = values.length; i < len; i++){
14932 all.push(this.decodeValue(values[i]));
14937 var values = v.split("^");
14938 for(var i = 0, len = values.length; i < len; i++){
14939 var kv = values[i].split("=");
14940 all[kv[0]] = this.decodeValue(kv[1]);
14949 * Encodes a value including type information. Decode with {@link #decodeValue}.
14950 * @param {Mixed} value The value to encode
14951 * @return {String} The encoded value
14953 encodeValue : function(v){
14955 if(typeof v == "number"){
14957 }else if(typeof v == "boolean"){
14958 enc = "b:" + (v ? "1" : "0");
14959 }else if(v instanceof Date){
14960 enc = "d:" + v.toGMTString();
14961 }else if(v instanceof Array){
14963 for(var i = 0, len = v.length; i < len; i++){
14964 flat += this.encodeValue(v[i]);
14970 }else if(typeof v == "object"){
14973 if(typeof v[key] != "function"){
14974 flat += key + "=" + this.encodeValue(v[key]) + "^";
14977 enc = "o:" + flat.substring(0, flat.length-1);
14981 return escape(enc);
14987 * Ext JS Library 1.1.1
14988 * Copyright(c) 2006-2007, Ext JS, LLC.
14990 * Originally Released Under LGPL - original licence link has changed is not relivant.
14993 * <script type="text/javascript">
14996 * @class Roo.state.Manager
14997 * This is the global state manager. By default all components that are "state aware" check this class
14998 * for state information if you don't pass them a custom state provider. In order for this class
14999 * to be useful, it must be initialized with a provider when your application initializes.
15001 // in your initialization function
15003 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
15005 // supposed you have a {@link Roo.BorderLayout}
15006 var layout = new Roo.BorderLayout(...);
15007 layout.restoreState();
15008 // or a {Roo.BasicDialog}
15009 var dialog = new Roo.BasicDialog(...);
15010 dialog.restoreState();
15014 Roo.state.Manager = function(){
15015 var provider = new Roo.state.Provider();
15019 * Configures the default state provider for your application
15020 * @param {Provider} stateProvider The state provider to set
15022 setProvider : function(stateProvider){
15023 provider = stateProvider;
15027 * Returns the current value for a key
15028 * @param {String} name The key name
15029 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
15030 * @return {Mixed} The state data
15032 get : function(key, defaultValue){
15033 return provider.get(key, defaultValue);
15037 * Sets the value for a key
15038 * @param {String} name The key name
15039 * @param {Mixed} value The state data
15041 set : function(key, value){
15042 provider.set(key, value);
15046 * Clears a value from the state
15047 * @param {String} name The key name
15049 clear : function(key){
15050 provider.clear(key);
15054 * Gets the currently configured state provider
15055 * @return {Provider} The state provider
15057 getProvider : function(){
15064 * Ext JS Library 1.1.1
15065 * Copyright(c) 2006-2007, Ext JS, LLC.
15067 * Originally Released Under LGPL - original licence link has changed is not relivant.
15070 * <script type="text/javascript">
15073 * @class Roo.state.CookieProvider
15074 * @extends Roo.state.Provider
15075 * The default Provider implementation which saves state via cookies.
15078 var cp = new Roo.state.CookieProvider({
15080 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
15081 domain: "roojs.com"
15083 Roo.state.Manager.setProvider(cp);
15085 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
15086 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
15087 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
15088 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
15089 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
15090 * domain the page is running on including the 'www' like 'www.roojs.com')
15091 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
15093 * Create a new CookieProvider
15094 * @param {Object} config The configuration object
15096 Roo.state.CookieProvider = function(config){
15097 Roo.state.CookieProvider.superclass.constructor.call(this);
15099 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
15100 this.domain = null;
15101 this.secure = false;
15102 Roo.apply(this, config);
15103 this.state = this.readCookies();
15106 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
15108 set : function(name, value){
15109 if(typeof value == "undefined" || value === null){
15113 this.setCookie(name, value);
15114 Roo.state.CookieProvider.superclass.set.call(this, name, value);
15118 clear : function(name){
15119 this.clearCookie(name);
15120 Roo.state.CookieProvider.superclass.clear.call(this, name);
15124 readCookies : function(){
15126 var c = document.cookie + ";";
15127 var re = /\s?(.*?)=(.*?);/g;
15129 while((matches = re.exec(c)) != null){
15130 var name = matches[1];
15131 var value = matches[2];
15132 if(name && name.substring(0,3) == "ys-"){
15133 cookies[name.substr(3)] = this.decodeValue(value);
15140 setCookie : function(name, value){
15141 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15142 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15143 ((this.path == null) ? "" : ("; path=" + this.path)) +
15144 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15145 ((this.secure == true) ? "; secure" : "");
15149 clearCookie : function(name){
15150 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15151 ((this.path == null) ? "" : ("; path=" + this.path)) +
15152 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15153 ((this.secure == true) ? "; secure" : "");
15157 * Ext JS Library 1.1.1
15158 * Copyright(c) 2006-2007, Ext JS, LLC.
15160 * Originally Released Under LGPL - original licence link has changed is not relivant.
15163 * <script type="text/javascript">
15168 * @class Roo.ComponentMgr
15169 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15172 Roo.ComponentMgr = function(){
15173 var all = new Roo.util.MixedCollection();
15177 * Registers a component.
15178 * @param {Roo.Component} c The component
15180 register : function(c){
15185 * Unregisters a component.
15186 * @param {Roo.Component} c The component
15188 unregister : function(c){
15193 * Returns a component by id
15194 * @param {String} id The component id
15196 get : function(id){
15197 return all.get(id);
15201 * Registers a function that will be called when a specified component is added to ComponentMgr
15202 * @param {String} id The component id
15203 * @param {Funtction} fn The callback function
15204 * @param {Object} scope The scope of the callback
15206 onAvailable : function(id, fn, scope){
15207 all.on("add", function(index, o){
15209 fn.call(scope || o, o);
15210 all.un("add", fn, scope);
15217 * Ext JS Library 1.1.1
15218 * Copyright(c) 2006-2007, Ext JS, LLC.
15220 * Originally Released Under LGPL - original licence link has changed is not relivant.
15223 * <script type="text/javascript">
15227 * @class Roo.Component
15228 * @extends Roo.util.Observable
15229 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15230 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15231 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15232 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15233 * All visual components (widgets) that require rendering into a layout should subclass Component.
15235 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15236 * 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
15237 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15239 Roo.Component = function(config){
15240 config = config || {};
15241 if(config.tagName || config.dom || typeof config == "string"){ // element object
15242 config = {el: config, id: config.id || config};
15244 this.initialConfig = config;
15246 Roo.apply(this, config);
15250 * Fires after the component is disabled.
15251 * @param {Roo.Component} this
15256 * Fires after the component is enabled.
15257 * @param {Roo.Component} this
15261 * @event beforeshow
15262 * Fires before the component is shown. Return false to stop the show.
15263 * @param {Roo.Component} this
15268 * Fires after the component is shown.
15269 * @param {Roo.Component} this
15273 * @event beforehide
15274 * Fires before the component is hidden. Return false to stop the hide.
15275 * @param {Roo.Component} this
15280 * Fires after the component is hidden.
15281 * @param {Roo.Component} this
15285 * @event beforerender
15286 * Fires before the component is rendered. Return false to stop the render.
15287 * @param {Roo.Component} this
15289 beforerender : true,
15292 * Fires after the component is rendered.
15293 * @param {Roo.Component} this
15297 * @event beforedestroy
15298 * Fires before the component is destroyed. Return false to stop the destroy.
15299 * @param {Roo.Component} this
15301 beforedestroy : true,
15304 * Fires after the component is destroyed.
15305 * @param {Roo.Component} this
15310 this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
15312 Roo.ComponentMgr.register(this);
15313 Roo.Component.superclass.constructor.call(this);
15314 this.initComponent();
15315 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15316 this.render(this.renderTo);
15317 delete this.renderTo;
15322 Roo.Component.AUTO_ID = 1000;
15324 Roo.extend(Roo.Component, Roo.util.Observable, {
15326 * @scope Roo.Component.prototype
15328 * true if this component is hidden. Read-only.
15333 * true if this component is disabled. Read-only.
15338 * true if this component has been rendered. Read-only.
15342 /** @cfg {String} disableClass
15343 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15345 disabledClass : "x-item-disabled",
15346 /** @cfg {Boolean} allowDomMove
15347 * Whether the component can move the Dom node when rendering (defaults to true).
15349 allowDomMove : true,
15350 /** @cfg {String} hideMode (display|visibility)
15351 * How this component should hidden. Supported values are
15352 * "visibility" (css visibility), "offsets" (negative offset position) and
15353 * "display" (css display) - defaults to "display".
15355 hideMode: 'display',
15358 ctype : "Roo.Component",
15361 * @cfg {String} actionMode
15362 * which property holds the element that used for hide() / show() / disable() / enable()
15368 getActionEl : function(){
15369 return this[this.actionMode];
15372 initComponent : Roo.emptyFn,
15374 * If this is a lazy rendering component, render it to its container element.
15375 * @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.
15377 render : function(container, position){
15378 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15379 if(!container && this.el){
15380 this.el = Roo.get(this.el);
15381 container = this.el.dom.parentNode;
15382 this.allowDomMove = false;
15384 this.container = Roo.get(container);
15385 this.rendered = true;
15386 if(position !== undefined){
15387 if(typeof position == 'number'){
15388 position = this.container.dom.childNodes[position];
15390 position = Roo.getDom(position);
15393 this.onRender(this.container, position || null);
15395 this.el.addClass(this.cls);
15399 this.el.applyStyles(this.style);
15402 this.fireEvent("render", this);
15403 this.afterRender(this.container);
15415 // default function is not really useful
15416 onRender : function(ct, position){
15418 this.el = Roo.get(this.el);
15419 if(this.allowDomMove !== false){
15420 ct.dom.insertBefore(this.el.dom, position);
15426 getAutoCreate : function(){
15427 var cfg = typeof this.autoCreate == "object" ?
15428 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15429 if(this.id && !cfg.id){
15436 afterRender : Roo.emptyFn,
15439 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15440 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15442 destroy : function(){
15443 if(this.fireEvent("beforedestroy", this) !== false){
15444 this.purgeListeners();
15445 this.beforeDestroy();
15447 this.el.removeAllListeners();
15449 if(this.actionMode == "container"){
15450 this.container.remove();
15454 Roo.ComponentMgr.unregister(this);
15455 this.fireEvent("destroy", this);
15460 beforeDestroy : function(){
15465 onDestroy : function(){
15470 * Returns the underlying {@link Roo.Element}.
15471 * @return {Roo.Element} The element
15473 getEl : function(){
15478 * Returns the id of this component.
15481 getId : function(){
15486 * Try to focus this component.
15487 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15488 * @return {Roo.Component} this
15490 focus : function(selectText){
15493 if(selectText === true){
15494 this.el.dom.select();
15509 * Disable this component.
15510 * @return {Roo.Component} this
15512 disable : function(){
15516 this.disabled = true;
15517 this.fireEvent("disable", this);
15522 onDisable : function(){
15523 this.getActionEl().addClass(this.disabledClass);
15524 this.el.dom.disabled = true;
15528 * Enable this component.
15529 * @return {Roo.Component} this
15531 enable : function(){
15535 this.disabled = false;
15536 this.fireEvent("enable", this);
15541 onEnable : function(){
15542 this.getActionEl().removeClass(this.disabledClass);
15543 this.el.dom.disabled = false;
15547 * Convenience function for setting disabled/enabled by boolean.
15548 * @param {Boolean} disabled
15550 setDisabled : function(disabled){
15551 this[disabled ? "disable" : "enable"]();
15555 * Show this component.
15556 * @return {Roo.Component} this
15559 if(this.fireEvent("beforeshow", this) !== false){
15560 this.hidden = false;
15564 this.fireEvent("show", this);
15570 onShow : function(){
15571 var ae = this.getActionEl();
15572 if(this.hideMode == 'visibility'){
15573 ae.dom.style.visibility = "visible";
15574 }else if(this.hideMode == 'offsets'){
15575 ae.removeClass('x-hidden');
15577 ae.dom.style.display = "";
15582 * Hide this component.
15583 * @return {Roo.Component} this
15586 if(this.fireEvent("beforehide", this) !== false){
15587 this.hidden = true;
15591 this.fireEvent("hide", this);
15597 onHide : function(){
15598 var ae = this.getActionEl();
15599 if(this.hideMode == 'visibility'){
15600 ae.dom.style.visibility = "hidden";
15601 }else if(this.hideMode == 'offsets'){
15602 ae.addClass('x-hidden');
15604 ae.dom.style.display = "none";
15609 * Convenience function to hide or show this component by boolean.
15610 * @param {Boolean} visible True to show, false to hide
15611 * @return {Roo.Component} this
15613 setVisible: function(visible){
15623 * Returns true if this component is visible.
15625 isVisible : function(){
15626 return this.getActionEl().isVisible();
15629 cloneConfig : function(overrides){
15630 overrides = overrides || {};
15631 var id = overrides.id || Roo.id();
15632 var cfg = Roo.applyIf(overrides, this.initialConfig);
15633 cfg.id = id; // prevent dup id
15634 return new this.constructor(cfg);
15638 * Ext JS Library 1.1.1
15639 * Copyright(c) 2006-2007, Ext JS, LLC.
15641 * Originally Released Under LGPL - original licence link has changed is not relivant.
15644 * <script type="text/javascript">
15648 * @class Roo.BoxComponent
15649 * @extends Roo.Component
15650 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15651 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15652 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15653 * layout containers.
15655 * @param {Roo.Element/String/Object} config The configuration options.
15657 Roo.BoxComponent = function(config){
15658 Roo.Component.call(this, config);
15662 * Fires after the component is resized.
15663 * @param {Roo.Component} this
15664 * @param {Number} adjWidth The box-adjusted width that was set
15665 * @param {Number} adjHeight The box-adjusted height that was set
15666 * @param {Number} rawWidth The width that was originally specified
15667 * @param {Number} rawHeight The height that was originally specified
15672 * Fires after the component is moved.
15673 * @param {Roo.Component} this
15674 * @param {Number} x The new x position
15675 * @param {Number} y The new y position
15681 Roo.extend(Roo.BoxComponent, Roo.Component, {
15682 // private, set in afterRender to signify that the component has been rendered
15684 // private, used to defer height settings to subclasses
15685 deferHeight: false,
15686 /** @cfg {Number} width
15687 * width (optional) size of component
15689 /** @cfg {Number} height
15690 * height (optional) size of component
15694 * Sets the width and height of the component. This method fires the resize event. This method can accept
15695 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15696 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15697 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15698 * @return {Roo.BoxComponent} this
15700 setSize : function(w, h){
15701 // support for standard size objects
15702 if(typeof w == 'object'){
15707 if(!this.boxReady){
15713 // prevent recalcs when not needed
15714 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15717 this.lastSize = {width: w, height: h};
15719 var adj = this.adjustSize(w, h);
15720 var aw = adj.width, ah = adj.height;
15721 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15722 var rz = this.getResizeEl();
15723 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15724 rz.setSize(aw, ah);
15725 }else if(!this.deferHeight && ah !== undefined){
15727 }else if(aw !== undefined){
15730 this.onResize(aw, ah, w, h);
15731 this.fireEvent('resize', this, aw, ah, w, h);
15737 * Gets the current size of the component's underlying element.
15738 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15740 getSize : function(){
15741 return this.el.getSize();
15745 * Gets the current XY position of the component's underlying element.
15746 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15747 * @return {Array} The XY position of the element (e.g., [100, 200])
15749 getPosition : function(local){
15750 if(local === true){
15751 return [this.el.getLeft(true), this.el.getTop(true)];
15753 return this.xy || this.el.getXY();
15757 * Gets the current box measurements of the component's underlying element.
15758 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15759 * @returns {Object} box An object in the format {x, y, width, height}
15761 getBox : function(local){
15762 var s = this.el.getSize();
15764 s.x = this.el.getLeft(true);
15765 s.y = this.el.getTop(true);
15767 var xy = this.xy || this.el.getXY();
15775 * Sets the current box measurements of the component's underlying element.
15776 * @param {Object} box An object in the format {x, y, width, height}
15777 * @returns {Roo.BoxComponent} this
15779 updateBox : function(box){
15780 this.setSize(box.width, box.height);
15781 this.setPagePosition(box.x, box.y);
15786 getResizeEl : function(){
15787 return this.resizeEl || this.el;
15791 getPositionEl : function(){
15792 return this.positionEl || this.el;
15796 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15797 * This method fires the move event.
15798 * @param {Number} left The new left
15799 * @param {Number} top The new top
15800 * @returns {Roo.BoxComponent} this
15802 setPosition : function(x, y){
15805 if(!this.boxReady){
15808 var adj = this.adjustPosition(x, y);
15809 var ax = adj.x, ay = adj.y;
15811 var el = this.getPositionEl();
15812 if(ax !== undefined || ay !== undefined){
15813 if(ax !== undefined && ay !== undefined){
15814 el.setLeftTop(ax, ay);
15815 }else if(ax !== undefined){
15817 }else if(ay !== undefined){
15820 this.onPosition(ax, ay);
15821 this.fireEvent('move', this, ax, ay);
15827 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15828 * This method fires the move event.
15829 * @param {Number} x The new x position
15830 * @param {Number} y The new y position
15831 * @returns {Roo.BoxComponent} this
15833 setPagePosition : function(x, y){
15836 if(!this.boxReady){
15839 if(x === undefined || y === undefined){ // cannot translate undefined points
15842 var p = this.el.translatePoints(x, y);
15843 this.setPosition(p.left, p.top);
15848 onRender : function(ct, position){
15849 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15851 this.resizeEl = Roo.get(this.resizeEl);
15853 if(this.positionEl){
15854 this.positionEl = Roo.get(this.positionEl);
15859 afterRender : function(){
15860 Roo.BoxComponent.superclass.afterRender.call(this);
15861 this.boxReady = true;
15862 this.setSize(this.width, this.height);
15863 if(this.x || this.y){
15864 this.setPosition(this.x, this.y);
15866 if(this.pageX || this.pageY){
15867 this.setPagePosition(this.pageX, this.pageY);
15872 * Force the component's size to recalculate based on the underlying element's current height and width.
15873 * @returns {Roo.BoxComponent} this
15875 syncSize : function(){
15876 delete this.lastSize;
15877 this.setSize(this.el.getWidth(), this.el.getHeight());
15882 * Called after the component is resized, this method is empty by default but can be implemented by any
15883 * subclass that needs to perform custom logic after a resize occurs.
15884 * @param {Number} adjWidth The box-adjusted width that was set
15885 * @param {Number} adjHeight The box-adjusted height that was set
15886 * @param {Number} rawWidth The width that was originally specified
15887 * @param {Number} rawHeight The height that was originally specified
15889 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15894 * Called after the component is moved, this method is empty by default but can be implemented by any
15895 * subclass that needs to perform custom logic after a move occurs.
15896 * @param {Number} x The new x position
15897 * @param {Number} y The new y position
15899 onPosition : function(x, y){
15904 adjustSize : function(w, h){
15905 if(this.autoWidth){
15908 if(this.autoHeight){
15911 return {width : w, height: h};
15915 adjustPosition : function(x, y){
15916 return {x : x, y: y};
15919 * Original code for Roojs - LGPL
15920 * <script type="text/javascript">
15924 * @class Roo.XComponent
15925 * A delayed Element creator...
15926 * Or a way to group chunks of interface together.
15927 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15928 * used in conjunction with XComponent.build() it will create an instance of each element,
15929 * then call addxtype() to build the User interface.
15931 * Mypart.xyx = new Roo.XComponent({
15933 parent : 'Mypart.xyz', // empty == document.element.!!
15937 disabled : function() {}
15939 tree : function() { // return an tree of xtype declared components
15943 xtype : 'NestedLayoutPanel',
15950 * It can be used to build a big heiracy, with parent etc.
15951 * or you can just use this to render a single compoent to a dom element
15952 * MYPART.render(Roo.Element | String(id) | dom_element )
15959 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15960 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15962 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15964 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15965 * - if mulitple topModules exist, the last one is defined as the top module.
15969 * When the top level or multiple modules are to embedded into a existing HTML page,
15970 * the parent element can container '#id' of the element where the module will be drawn.
15974 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15975 * it relies more on a include mechanism, where sub modules are included into an outer page.
15976 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15978 * Bootstrap Roo Included elements
15980 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15981 * hence confusing the component builder as it thinks there are multiple top level elements.
15985 * @extends Roo.util.Observable
15987 * @param cfg {Object} configuration of component
15990 Roo.XComponent = function(cfg) {
15991 Roo.apply(this, cfg);
15995 * Fires when this the componnt is built
15996 * @param {Roo.XComponent} c the component
16001 this.region = this.region || 'center'; // default..
16002 Roo.XComponent.register(this);
16003 this.modules = false;
16004 this.el = false; // where the layout goes..
16008 Roo.extend(Roo.XComponent, Roo.util.Observable, {
16011 * The created element (with Roo.factory())
16012 * @type {Roo.Layout}
16018 * for BC - use el in new code
16019 * @type {Roo.Layout}
16025 * for BC - use el in new code
16026 * @type {Roo.Layout}
16031 * @cfg {Function|boolean} disabled
16032 * If this module is disabled by some rule, return true from the funtion
16037 * @cfg {String} parent
16038 * Name of parent element which it get xtype added to..
16043 * @cfg {String} order
16044 * Used to set the order in which elements are created (usefull for multiple tabs)
16049 * @cfg {String} name
16050 * String to display while loading.
16054 * @cfg {String} region
16055 * Region to render component to (defaults to center)
16060 * @cfg {Array} items
16061 * A single item array - the first element is the root of the tree..
16062 * It's done this way to stay compatible with the Xtype system...
16068 * The method that retuns the tree of parts that make up this compoennt
16075 * render element to dom or tree
16076 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
16079 render : function(el)
16083 var hp = this.parent ? 1 : 0;
16084 Roo.debug && Roo.log(this);
16086 var tree = this._tree ? this._tree() : this.tree();
16089 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
16090 // if parent is a '#.....' string, then let's use that..
16091 var ename = this.parent.substr(1);
16092 this.parent = false;
16093 Roo.debug && Roo.log(ename);
16095 case 'bootstrap-body':
16096 if (typeof(tree.el) != 'undefined' && tree.el == document.body) {
16097 // this is the BorderLayout standard?
16098 this.parent = { el : true };
16101 if (["Nest", "Content", "Grid", "Tree"].indexOf(tree.xtype) > -1) {
16102 // need to insert stuff...
16104 el : new Roo.bootstrap.layout.Border({
16105 el : document.body,
16111 tabPosition: 'top',
16112 //resizeTabs: true,
16113 alwaysShowTabs: true,
16123 if (typeof(Roo.bootstrap.Body) != 'undefined' ) {
16124 this.parent = { el : new Roo.bootstrap.Body() };
16125 Roo.debug && Roo.log("setting el to doc body");
16128 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
16132 this.parent = { el : true};
16135 el = Roo.get(ename);
16136 if (typeof(Roo.bootstrap) != 'undefined' && tree['|xns'] == 'Roo.bootstrap') {
16137 this.parent = { el : true};
16144 if (!el && !this.parent) {
16145 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
16150 Roo.debug && Roo.log("EL:");
16151 Roo.debug && Roo.log(el);
16152 Roo.debug && Roo.log("this.parent.el:");
16153 Roo.debug && Roo.log(this.parent.el);
16156 // altertive root elements ??? - we need a better way to indicate these.
16157 var is_alt = Roo.XComponent.is_alt ||
16158 (typeof(tree.el) != 'undefined' && tree.el == document.body) ||
16159 (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
16160 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
16164 if (!this.parent && is_alt) {
16165 //el = Roo.get(document.body);
16166 this.parent = { el : true };
16171 if (!this.parent) {
16173 Roo.debug && Roo.log("no parent - creating one");
16175 el = el ? Roo.get(el) : false;
16177 if (typeof(Roo.BorderLayout) == 'undefined' ) {
16180 el : new Roo.bootstrap.layout.Border({
16181 el: el || document.body,
16187 tabPosition: 'top',
16188 //resizeTabs: true,
16189 alwaysShowTabs: false,
16192 overflow: 'visible'
16198 // it's a top level one..
16200 el : new Roo.BorderLayout(el || document.body, {
16205 tabPosition: 'top',
16206 //resizeTabs: true,
16207 alwaysShowTabs: el && hp? false : true,
16208 hideTabs: el || !hp ? true : false,
16216 if (!this.parent.el) {
16217 // probably an old style ctor, which has been disabled.
16221 // The 'tree' method is '_tree now'
16223 tree.region = tree.region || this.region;
16224 var is_body = false;
16225 if (this.parent.el === true) {
16226 // bootstrap... - body..
16230 this.parent.el = Roo.factory(tree);
16234 this.el = this.parent.el.addxtype(tree, undefined, is_body);
16235 this.fireEvent('built', this);
16237 this.panel = this.el;
16238 this.layout = this.panel.layout;
16239 this.parentLayout = this.parent.layout || false;
16245 Roo.apply(Roo.XComponent, {
16247 * @property hideProgress
16248 * true to disable the building progress bar.. usefull on single page renders.
16251 hideProgress : false,
16253 * @property buildCompleted
16254 * True when the builder has completed building the interface.
16257 buildCompleted : false,
16260 * @property topModule
16261 * the upper most module - uses document.element as it's constructor.
16268 * @property modules
16269 * array of modules to be created by registration system.
16270 * @type {Array} of Roo.XComponent
16275 * @property elmodules
16276 * array of modules to be created by which use #ID
16277 * @type {Array} of Roo.XComponent
16284 * Is an alternative Root - normally used by bootstrap or other systems,
16285 * where the top element in the tree can wrap 'body'
16286 * @type {boolean} (default false)
16291 * @property build_from_html
16292 * Build elements from html - used by bootstrap HTML stuff
16293 * - this is cleared after build is completed
16294 * @type {boolean} (default false)
16297 build_from_html : false,
16299 * Register components to be built later.
16301 * This solves the following issues
16302 * - Building is not done on page load, but after an authentication process has occured.
16303 * - Interface elements are registered on page load
16304 * - Parent Interface elements may not be loaded before child, so this handles that..
16311 module : 'Pman.Tab.projectMgr',
16313 parent : 'Pman.layout',
16314 disabled : false, // or use a function..
16317 * * @param {Object} details about module
16319 register : function(obj) {
16321 Roo.XComponent.event.fireEvent('register', obj);
16322 switch(typeof(obj.disabled) ) {
16328 if ( obj.disabled() ) {
16334 if (obj.disabled) {
16340 this.modules.push(obj);
16344 * convert a string to an object..
16345 * eg. 'AAA.BBB' -> finds AAA.BBB
16349 toObject : function(str)
16351 if (!str || typeof(str) == 'object') {
16354 if (str.substring(0,1) == '#') {
16358 var ar = str.split('.');
16363 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16365 throw "Module not found : " + str;
16369 throw "Module not found : " + str;
16371 Roo.each(ar, function(e) {
16372 if (typeof(o[e]) == 'undefined') {
16373 throw "Module not found : " + str;
16384 * move modules into their correct place in the tree..
16387 preBuild : function ()
16390 Roo.each(this.modules , function (obj)
16392 Roo.XComponent.event.fireEvent('beforebuild', obj);
16394 var opar = obj.parent;
16396 obj.parent = this.toObject(opar);
16398 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16403 Roo.debug && Roo.log("GOT top level module");
16404 Roo.debug && Roo.log(obj);
16405 obj.modules = new Roo.util.MixedCollection(false,
16406 function(o) { return o.order + '' }
16408 this.topModule = obj;
16411 // parent is a string (usually a dom element name..)
16412 if (typeof(obj.parent) == 'string') {
16413 this.elmodules.push(obj);
16416 if (obj.parent.constructor != Roo.XComponent) {
16417 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16419 if (!obj.parent.modules) {
16420 obj.parent.modules = new Roo.util.MixedCollection(false,
16421 function(o) { return o.order + '' }
16424 if (obj.parent.disabled) {
16425 obj.disabled = true;
16427 obj.parent.modules.add(obj);
16432 * make a list of modules to build.
16433 * @return {Array} list of modules.
16436 buildOrder : function()
16439 var cmp = function(a,b) {
16440 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16442 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16443 throw "No top level modules to build";
16446 // make a flat list in order of modules to build.
16447 var mods = this.topModule ? [ this.topModule ] : [];
16450 // elmodules (is a list of DOM based modules )
16451 Roo.each(this.elmodules, function(e) {
16453 if (!this.topModule &&
16454 typeof(e.parent) == 'string' &&
16455 e.parent.substring(0,1) == '#' &&
16456 Roo.get(e.parent.substr(1))
16459 _this.topModule = e;
16465 // add modules to their parents..
16466 var addMod = function(m) {
16467 Roo.debug && Roo.log("build Order: add: " + m.name);
16470 if (m.modules && !m.disabled) {
16471 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16472 m.modules.keySort('ASC', cmp );
16473 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16475 m.modules.each(addMod);
16477 Roo.debug && Roo.log("build Order: no child modules");
16479 // not sure if this is used any more..
16481 m.finalize.name = m.name + " (clean up) ";
16482 mods.push(m.finalize);
16486 if (this.topModule && this.topModule.modules) {
16487 this.topModule.modules.keySort('ASC', cmp );
16488 this.topModule.modules.each(addMod);
16494 * Build the registered modules.
16495 * @param {Object} parent element.
16496 * @param {Function} optional method to call after module has been added.
16500 build : function(opts)
16503 if (typeof(opts) != 'undefined') {
16504 Roo.apply(this,opts);
16508 var mods = this.buildOrder();
16510 //this.allmods = mods;
16511 //Roo.debug && Roo.log(mods);
16513 if (!mods.length) { // should not happen
16514 throw "NO modules!!!";
16518 var msg = "Building Interface...";
16519 // flash it up as modal - so we store the mask!?
16520 if (!this.hideProgress && Roo.MessageBox) {
16521 Roo.MessageBox.show({ title: 'loading' });
16522 Roo.MessageBox.show({
16523 title: "Please wait...",
16532 var total = mods.length;
16535 var progressRun = function() {
16536 if (!mods.length) {
16537 Roo.debug && Roo.log('hide?');
16538 if (!this.hideProgress && Roo.MessageBox) {
16539 Roo.MessageBox.hide();
16541 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16543 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16549 var m = mods.shift();
16552 Roo.debug && Roo.log(m);
16553 // not sure if this is supported any more.. - modules that are are just function
16554 if (typeof(m) == 'function') {
16556 return progressRun.defer(10, _this);
16560 msg = "Building Interface " + (total - mods.length) +
16562 (m.name ? (' - ' + m.name) : '');
16563 Roo.debug && Roo.log(msg);
16564 if (!_this.hideProgress && Roo.MessageBox) {
16565 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16569 // is the module disabled?
16570 var disabled = (typeof(m.disabled) == 'function') ?
16571 m.disabled.call(m.module.disabled) : m.disabled;
16575 return progressRun(); // we do not update the display!
16583 // it's 10 on top level, and 1 on others??? why...
16584 return progressRun.defer(10, _this);
16587 progressRun.defer(1, _this);
16601 * wrapper for event.on - aliased later..
16602 * Typically use to register a event handler for register:
16604 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16613 Roo.XComponent.event = new Roo.util.Observable({
16617 * Fires when an Component is registered,
16618 * set the disable property on the Component to stop registration.
16619 * @param {Roo.XComponent} c the component being registerd.
16624 * @event beforebuild
16625 * Fires before each Component is built
16626 * can be used to apply permissions.
16627 * @param {Roo.XComponent} c the component being registerd.
16630 'beforebuild' : true,
16632 * @event buildcomplete
16633 * Fires on the top level element when all elements have been built
16634 * @param {Roo.XComponent} the top level component.
16636 'buildcomplete' : true
16641 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);
16644 * marked - a markdown parser
16645 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
16646 * https://github.com/chjj/marked
16652 * Roo.Markdown - is a very crude wrapper around marked..
16656 * alert( Roo.Markdown.toHtml("Markdown *rocks*.") );
16658 * Note: move the sample code to the bottom of this
16659 * file before uncommenting it.
16664 Roo.Markdown.toHtml = function(text) {
16666 var c = new Roo.Markdown.marked.setOptions({
16667 renderer: new Roo.Markdown.marked.Renderer(),
16678 text = text.replace(/\\\n/g,' ');
16679 return Roo.Markdown.marked(text);
16684 // Wraps all "globals" so that the only thing
16685 // exposed is makeHtml().
16690 * Block-Level Grammar
16695 code: /^( {4}[^\n]+\n*)+/,
16697 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
16698 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
16700 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
16701 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
16702 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
16703 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
16704 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
16706 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
16710 block.bullet = /(?:[*+-]|\d+\.)/;
16711 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
16712 block.item = replace(block.item, 'gm')
16713 (/bull/g, block.bullet)
16716 block.list = replace(block.list)
16717 (/bull/g, block.bullet)
16718 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
16719 ('def', '\\n+(?=' + block.def.source + ')')
16722 block.blockquote = replace(block.blockquote)
16726 block._tag = '(?!(?:'
16727 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
16728 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
16729 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
16731 block.html = replace(block.html)
16732 ('comment', /<!--[\s\S]*?-->/)
16733 ('closed', /<(tag)[\s\S]+?<\/\1>/)
16734 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
16735 (/tag/g, block._tag)
16738 block.paragraph = replace(block.paragraph)
16740 ('heading', block.heading)
16741 ('lheading', block.lheading)
16742 ('blockquote', block.blockquote)
16743 ('tag', '<' + block._tag)
16748 * Normal Block Grammar
16751 block.normal = merge({}, block);
16754 * GFM Block Grammar
16757 block.gfm = merge({}, block.normal, {
16758 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
16760 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
16763 block.gfm.paragraph = replace(block.paragraph)
16765 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
16766 + block.list.source.replace('\\1', '\\3') + '|')
16770 * GFM + Tables Block Grammar
16773 block.tables = merge({}, block.gfm, {
16774 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
16775 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
16782 function Lexer(options) {
16784 this.tokens.links = {};
16785 this.options = options || marked.defaults;
16786 this.rules = block.normal;
16788 if (this.options.gfm) {
16789 if (this.options.tables) {
16790 this.rules = block.tables;
16792 this.rules = block.gfm;
16798 * Expose Block Rules
16801 Lexer.rules = block;
16804 * Static Lex Method
16807 Lexer.lex = function(src, options) {
16808 var lexer = new Lexer(options);
16809 return lexer.lex(src);
16816 Lexer.prototype.lex = function(src) {
16818 .replace(/\r\n|\r/g, '\n')
16819 .replace(/\t/g, ' ')
16820 .replace(/\u00a0/g, ' ')
16821 .replace(/\u2424/g, '\n');
16823 return this.token(src, true);
16830 Lexer.prototype.token = function(src, top, bq) {
16831 var src = src.replace(/^ +$/gm, '')
16844 if (cap = this.rules.newline.exec(src)) {
16845 src = src.substring(cap[0].length);
16846 if (cap[0].length > 1) {
16854 if (cap = this.rules.code.exec(src)) {
16855 src = src.substring(cap[0].length);
16856 cap = cap[0].replace(/^ {4}/gm, '');
16859 text: !this.options.pedantic
16860 ? cap.replace(/\n+$/, '')
16867 if (cap = this.rules.fences.exec(src)) {
16868 src = src.substring(cap[0].length);
16878 if (cap = this.rules.heading.exec(src)) {
16879 src = src.substring(cap[0].length);
16882 depth: cap[1].length,
16888 // table no leading pipe (gfm)
16889 if (top && (cap = this.rules.nptable.exec(src))) {
16890 src = src.substring(cap[0].length);
16894 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
16895 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
16896 cells: cap[3].replace(/\n$/, '').split('\n')
16899 for (i = 0; i < item.align.length; i++) {
16900 if (/^ *-+: *$/.test(item.align[i])) {
16901 item.align[i] = 'right';
16902 } else if (/^ *:-+: *$/.test(item.align[i])) {
16903 item.align[i] = 'center';
16904 } else if (/^ *:-+ *$/.test(item.align[i])) {
16905 item.align[i] = 'left';
16907 item.align[i] = null;
16911 for (i = 0; i < item.cells.length; i++) {
16912 item.cells[i] = item.cells[i].split(/ *\| */);
16915 this.tokens.push(item);
16921 if (cap = this.rules.lheading.exec(src)) {
16922 src = src.substring(cap[0].length);
16925 depth: cap[2] === '=' ? 1 : 2,
16932 if (cap = this.rules.hr.exec(src)) {
16933 src = src.substring(cap[0].length);
16941 if (cap = this.rules.blockquote.exec(src)) {
16942 src = src.substring(cap[0].length);
16945 type: 'blockquote_start'
16948 cap = cap[0].replace(/^ *> ?/gm, '');
16950 // Pass `top` to keep the current
16951 // "toplevel" state. This is exactly
16952 // how markdown.pl works.
16953 this.token(cap, top, true);
16956 type: 'blockquote_end'
16963 if (cap = this.rules.list.exec(src)) {
16964 src = src.substring(cap[0].length);
16968 type: 'list_start',
16969 ordered: bull.length > 1
16972 // Get each top-level item.
16973 cap = cap[0].match(this.rules.item);
16979 for (; i < l; i++) {
16982 // Remove the list item's bullet
16983 // so it is seen as the next token.
16984 space = item.length;
16985 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
16987 // Outdent whatever the
16988 // list item contains. Hacky.
16989 if (~item.indexOf('\n ')) {
16990 space -= item.length;
16991 item = !this.options.pedantic
16992 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
16993 : item.replace(/^ {1,4}/gm, '');
16996 // Determine whether the next list item belongs here.
16997 // Backpedal if it does not belong in this list.
16998 if (this.options.smartLists && i !== l - 1) {
16999 b = block.bullet.exec(cap[i + 1])[0];
17000 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
17001 src = cap.slice(i + 1).join('\n') + src;
17006 // Determine whether item is loose or not.
17007 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
17008 // for discount behavior.
17009 loose = next || /\n\n(?!\s*$)/.test(item);
17011 next = item.charAt(item.length - 1) === '\n';
17012 if (!loose) { loose = next; }
17017 ? 'loose_item_start'
17018 : 'list_item_start'
17022 this.token(item, false, bq);
17025 type: 'list_item_end'
17037 if (cap = this.rules.html.exec(src)) {
17038 src = src.substring(cap[0].length);
17040 type: this.options.sanitize
17043 pre: !this.options.sanitizer
17044 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
17051 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
17052 src = src.substring(cap[0].length);
17053 this.tokens.links[cap[1].toLowerCase()] = {
17061 if (top && (cap = this.rules.table.exec(src))) {
17062 src = src.substring(cap[0].length);
17066 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
17067 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
17068 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
17071 for (i = 0; i < item.align.length; i++) {
17072 if (/^ *-+: *$/.test(item.align[i])) {
17073 item.align[i] = 'right';
17074 } else if (/^ *:-+: *$/.test(item.align[i])) {
17075 item.align[i] = 'center';
17076 } else if (/^ *:-+ *$/.test(item.align[i])) {
17077 item.align[i] = 'left';
17079 item.align[i] = null;
17083 for (i = 0; i < item.cells.length; i++) {
17084 item.cells[i] = item.cells[i]
17085 .replace(/^ *\| *| *\| *$/g, '')
17089 this.tokens.push(item);
17094 // top-level paragraph
17095 if (top && (cap = this.rules.paragraph.exec(src))) {
17096 src = src.substring(cap[0].length);
17099 text: cap[1].charAt(cap[1].length - 1) === '\n'
17100 ? cap[1].slice(0, -1)
17107 if (cap = this.rules.text.exec(src)) {
17108 // Top-level should never reach here.
17109 src = src.substring(cap[0].length);
17119 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17123 return this.tokens;
17127 * Inline-Level Grammar
17131 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
17132 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
17134 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
17135 link: /^!?\[(inside)\]\(href\)/,
17136 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
17137 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
17138 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
17139 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
17140 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
17141 br: /^ {2,}\n(?!\s*$)/,
17143 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
17146 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
17147 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
17149 inline.link = replace(inline.link)
17150 ('inside', inline._inside)
17151 ('href', inline._href)
17154 inline.reflink = replace(inline.reflink)
17155 ('inside', inline._inside)
17159 * Normal Inline Grammar
17162 inline.normal = merge({}, inline);
17165 * Pedantic Inline Grammar
17168 inline.pedantic = merge({}, inline.normal, {
17169 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
17170 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
17174 * GFM Inline Grammar
17177 inline.gfm = merge({}, inline.normal, {
17178 escape: replace(inline.escape)('])', '~|])')(),
17179 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
17180 del: /^~~(?=\S)([\s\S]*?\S)~~/,
17181 text: replace(inline.text)
17183 ('|', '|https?://|')
17188 * GFM + Line Breaks Inline Grammar
17191 inline.breaks = merge({}, inline.gfm, {
17192 br: replace(inline.br)('{2,}', '*')(),
17193 text: replace(inline.gfm.text)('{2,}', '*')()
17197 * Inline Lexer & Compiler
17200 function InlineLexer(links, options) {
17201 this.options = options || marked.defaults;
17202 this.links = links;
17203 this.rules = inline.normal;
17204 this.renderer = this.options.renderer || new Renderer;
17205 this.renderer.options = this.options;
17209 Error('Tokens array requires a `links` property.');
17212 if (this.options.gfm) {
17213 if (this.options.breaks) {
17214 this.rules = inline.breaks;
17216 this.rules = inline.gfm;
17218 } else if (this.options.pedantic) {
17219 this.rules = inline.pedantic;
17224 * Expose Inline Rules
17227 InlineLexer.rules = inline;
17230 * Static Lexing/Compiling Method
17233 InlineLexer.output = function(src, links, options) {
17234 var inline = new InlineLexer(links, options);
17235 return inline.output(src);
17242 InlineLexer.prototype.output = function(src) {
17251 if (cap = this.rules.escape.exec(src)) {
17252 src = src.substring(cap[0].length);
17258 if (cap = this.rules.autolink.exec(src)) {
17259 src = src.substring(cap[0].length);
17260 if (cap[2] === '@') {
17261 text = cap[1].charAt(6) === ':'
17262 ? this.mangle(cap[1].substring(7))
17263 : this.mangle(cap[1]);
17264 href = this.mangle('mailto:') + text;
17266 text = escape(cap[1]);
17269 out += this.renderer.link(href, null, text);
17274 if (!this.inLink && (cap = this.rules.url.exec(src))) {
17275 src = src.substring(cap[0].length);
17276 text = escape(cap[1]);
17278 out += this.renderer.link(href, null, text);
17283 if (cap = this.rules.tag.exec(src)) {
17284 if (!this.inLink && /^<a /i.test(cap[0])) {
17285 this.inLink = true;
17286 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
17287 this.inLink = false;
17289 src = src.substring(cap[0].length);
17290 out += this.options.sanitize
17291 ? this.options.sanitizer
17292 ? this.options.sanitizer(cap[0])
17299 if (cap = this.rules.link.exec(src)) {
17300 src = src.substring(cap[0].length);
17301 this.inLink = true;
17302 out += this.outputLink(cap, {
17306 this.inLink = false;
17311 if ((cap = this.rules.reflink.exec(src))
17312 || (cap = this.rules.nolink.exec(src))) {
17313 src = src.substring(cap[0].length);
17314 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
17315 link = this.links[link.toLowerCase()];
17316 if (!link || !link.href) {
17317 out += cap[0].charAt(0);
17318 src = cap[0].substring(1) + src;
17321 this.inLink = true;
17322 out += this.outputLink(cap, link);
17323 this.inLink = false;
17328 if (cap = this.rules.strong.exec(src)) {
17329 src = src.substring(cap[0].length);
17330 out += this.renderer.strong(this.output(cap[2] || cap[1]));
17335 if (cap = this.rules.em.exec(src)) {
17336 src = src.substring(cap[0].length);
17337 out += this.renderer.em(this.output(cap[2] || cap[1]));
17342 if (cap = this.rules.code.exec(src)) {
17343 src = src.substring(cap[0].length);
17344 out += this.renderer.codespan(escape(cap[2], true));
17349 if (cap = this.rules.br.exec(src)) {
17350 src = src.substring(cap[0].length);
17351 out += this.renderer.br();
17356 if (cap = this.rules.del.exec(src)) {
17357 src = src.substring(cap[0].length);
17358 out += this.renderer.del(this.output(cap[1]));
17363 if (cap = this.rules.text.exec(src)) {
17364 src = src.substring(cap[0].length);
17365 out += this.renderer.text(escape(this.smartypants(cap[0])));
17371 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17382 InlineLexer.prototype.outputLink = function(cap, link) {
17383 var href = escape(link.href)
17384 , title = link.title ? escape(link.title) : null;
17386 return cap[0].charAt(0) !== '!'
17387 ? this.renderer.link(href, title, this.output(cap[1]))
17388 : this.renderer.image(href, title, escape(cap[1]));
17392 * Smartypants Transformations
17395 InlineLexer.prototype.smartypants = function(text) {
17396 if (!this.options.smartypants) { return text; }
17399 .replace(/---/g, '\u2014')
17401 .replace(/--/g, '\u2013')
17403 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
17404 // closing singles & apostrophes
17405 .replace(/'/g, '\u2019')
17407 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
17409 .replace(/"/g, '\u201d')
17411 .replace(/\.{3}/g, '\u2026');
17418 InlineLexer.prototype.mangle = function(text) {
17419 if (!this.options.mangle) { return text; }
17425 for (; i < l; i++) {
17426 ch = text.charCodeAt(i);
17427 if (Math.random() > 0.5) {
17428 ch = 'x' + ch.toString(16);
17430 out += '&#' + ch + ';';
17440 function Renderer(options) {
17441 this.options = options || {};
17444 Renderer.prototype.code = function(code, lang, escaped) {
17445 if (this.options.highlight) {
17446 var out = this.options.highlight(code, lang);
17447 if (out != null && out !== code) {
17452 // hack!!! - it's already escapeD?
17457 return '<pre><code>'
17458 + (escaped ? code : escape(code, true))
17459 + '\n</code></pre>';
17462 return '<pre><code class="'
17463 + this.options.langPrefix
17464 + escape(lang, true)
17466 + (escaped ? code : escape(code, true))
17467 + '\n</code></pre>\n';
17470 Renderer.prototype.blockquote = function(quote) {
17471 return '<blockquote>\n' + quote + '</blockquote>\n';
17474 Renderer.prototype.html = function(html) {
17478 Renderer.prototype.heading = function(text, level, raw) {
17482 + this.options.headerPrefix
17483 + raw.toLowerCase().replace(/[^\w]+/g, '-')
17491 Renderer.prototype.hr = function() {
17492 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
17495 Renderer.prototype.list = function(body, ordered) {
17496 var type = ordered ? 'ol' : 'ul';
17497 return '<' + type + '>\n' + body + '</' + type + '>\n';
17500 Renderer.prototype.listitem = function(text) {
17501 return '<li>' + text + '</li>\n';
17504 Renderer.prototype.paragraph = function(text) {
17505 return '<p>' + text + '</p>\n';
17508 Renderer.prototype.table = function(header, body) {
17509 return '<table class="table table-striped">\n'
17519 Renderer.prototype.tablerow = function(content) {
17520 return '<tr>\n' + content + '</tr>\n';
17523 Renderer.prototype.tablecell = function(content, flags) {
17524 var type = flags.header ? 'th' : 'td';
17525 var tag = flags.align
17526 ? '<' + type + ' style="text-align:' + flags.align + '">'
17527 : '<' + type + '>';
17528 return tag + content + '</' + type + '>\n';
17531 // span level renderer
17532 Renderer.prototype.strong = function(text) {
17533 return '<strong>' + text + '</strong>';
17536 Renderer.prototype.em = function(text) {
17537 return '<em>' + text + '</em>';
17540 Renderer.prototype.codespan = function(text) {
17541 return '<code>' + text + '</code>';
17544 Renderer.prototype.br = function() {
17545 return this.options.xhtml ? '<br/>' : '<br>';
17548 Renderer.prototype.del = function(text) {
17549 return '<del>' + text + '</del>';
17552 Renderer.prototype.link = function(href, title, text) {
17553 if (this.options.sanitize) {
17555 var prot = decodeURIComponent(unescape(href))
17556 .replace(/[^\w:]/g, '')
17561 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
17565 var out = '<a href="' + href + '"';
17567 out += ' title="' + title + '"';
17569 out += '>' + text + '</a>';
17573 Renderer.prototype.image = function(href, title, text) {
17574 var out = '<img src="' + href + '" alt="' + text + '"';
17576 out += ' title="' + title + '"';
17578 out += this.options.xhtml ? '/>' : '>';
17582 Renderer.prototype.text = function(text) {
17587 * Parsing & Compiling
17590 function Parser(options) {
17593 this.options = options || marked.defaults;
17594 this.options.renderer = this.options.renderer || new Renderer;
17595 this.renderer = this.options.renderer;
17596 this.renderer.options = this.options;
17600 * Static Parse Method
17603 Parser.parse = function(src, options, renderer) {
17604 var parser = new Parser(options, renderer);
17605 return parser.parse(src);
17612 Parser.prototype.parse = function(src) {
17613 this.inline = new InlineLexer(src.links, this.options, this.renderer);
17614 this.tokens = src.reverse();
17617 while (this.next()) {
17628 Parser.prototype.next = function() {
17629 return this.token = this.tokens.pop();
17633 * Preview Next Token
17636 Parser.prototype.peek = function() {
17637 return this.tokens[this.tokens.length - 1] || 0;
17641 * Parse Text Tokens
17644 Parser.prototype.parseText = function() {
17645 var body = this.token.text;
17647 while (this.peek().type === 'text') {
17648 body += '\n' + this.next().text;
17651 return this.inline.output(body);
17655 * Parse Current Token
17658 Parser.prototype.tok = function() {
17659 switch (this.token.type) {
17664 return this.renderer.hr();
17667 return this.renderer.heading(
17668 this.inline.output(this.token.text),
17673 return this.renderer.code(this.token.text,
17675 this.token.escaped);
17688 for (i = 0; i < this.token.header.length; i++) {
17689 flags = { header: true, align: this.token.align[i] };
17690 cell += this.renderer.tablecell(
17691 this.inline.output(this.token.header[i]),
17692 { header: true, align: this.token.align[i] }
17695 header += this.renderer.tablerow(cell);
17697 for (i = 0; i < this.token.cells.length; i++) {
17698 row = this.token.cells[i];
17701 for (j = 0; j < row.length; j++) {
17702 cell += this.renderer.tablecell(
17703 this.inline.output(row[j]),
17704 { header: false, align: this.token.align[j] }
17708 body += this.renderer.tablerow(cell);
17710 return this.renderer.table(header, body);
17712 case 'blockquote_start': {
17715 while (this.next().type !== 'blockquote_end') {
17716 body += this.tok();
17719 return this.renderer.blockquote(body);
17721 case 'list_start': {
17723 , ordered = this.token.ordered;
17725 while (this.next().type !== 'list_end') {
17726 body += this.tok();
17729 return this.renderer.list(body, ordered);
17731 case 'list_item_start': {
17734 while (this.next().type !== 'list_item_end') {
17735 body += this.token.type === 'text'
17740 return this.renderer.listitem(body);
17742 case 'loose_item_start': {
17745 while (this.next().type !== 'list_item_end') {
17746 body += this.tok();
17749 return this.renderer.listitem(body);
17752 var html = !this.token.pre && !this.options.pedantic
17753 ? this.inline.output(this.token.text)
17755 return this.renderer.html(html);
17757 case 'paragraph': {
17758 return this.renderer.paragraph(this.inline.output(this.token.text));
17761 return this.renderer.paragraph(this.parseText());
17770 function escape(html, encode) {
17772 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
17773 .replace(/</g, '<')
17774 .replace(/>/g, '>')
17775 .replace(/"/g, '"')
17776 .replace(/'/g, ''');
17779 function unescape(html) {
17780 // explicitly match decimal, hex, and named HTML entities
17781 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
17782 n = n.toLowerCase();
17783 if (n === 'colon') { return ':'; }
17784 if (n.charAt(0) === '#') {
17785 return n.charAt(1) === 'x'
17786 ? String.fromCharCode(parseInt(n.substring(2), 16))
17787 : String.fromCharCode(+n.substring(1));
17793 function replace(regex, opt) {
17794 regex = regex.source;
17796 return function self(name, val) {
17797 if (!name) { return new RegExp(regex, opt); }
17798 val = val.source || val;
17799 val = val.replace(/(^|[^\[])\^/g, '$1');
17800 regex = regex.replace(name, val);
17808 function merge(obj) {
17813 for (; i < arguments.length; i++) {
17814 target = arguments[i];
17815 for (key in target) {
17816 if (Object.prototype.hasOwnProperty.call(target, key)) {
17817 obj[key] = target[key];
17830 function marked(src, opt, callback) {
17831 if (callback || typeof opt === 'function') {
17837 opt = merge({}, marked.defaults, opt || {});
17839 var highlight = opt.highlight
17845 tokens = Lexer.lex(src, opt)
17847 return callback(e);
17850 pending = tokens.length;
17852 var done = function(err) {
17854 opt.highlight = highlight;
17855 return callback(err);
17861 out = Parser.parse(tokens, opt);
17866 opt.highlight = highlight;
17870 : callback(null, out);
17873 if (!highlight || highlight.length < 3) {
17877 delete opt.highlight;
17879 if (!pending) { return done(); }
17881 for (; i < tokens.length; i++) {
17883 if (token.type !== 'code') {
17884 return --pending || done();
17886 return highlight(token.text, token.lang, function(err, code) {
17887 if (err) { return done(err); }
17888 if (code == null || code === token.text) {
17889 return --pending || done();
17892 token.escaped = true;
17893 --pending || done();
17901 if (opt) { opt = merge({}, marked.defaults, opt); }
17902 return Parser.parse(Lexer.lex(src, opt), opt);
17904 e.message += '\nPlease report this to https://github.com/chjj/marked.';
17905 if ((opt || marked.defaults).silent) {
17906 return '<p>An error occured:</p><pre>'
17907 + escape(e.message + '', true)
17919 marked.setOptions = function(opt) {
17920 merge(marked.defaults, opt);
17924 marked.defaults = {
17935 langPrefix: 'lang-',
17936 smartypants: false,
17938 renderer: new Renderer,
17946 marked.Parser = Parser;
17947 marked.parser = Parser.parse;
17949 marked.Renderer = Renderer;
17951 marked.Lexer = Lexer;
17952 marked.lexer = Lexer.lex;
17954 marked.InlineLexer = InlineLexer;
17955 marked.inlineLexer = InlineLexer.output;
17957 marked.parse = marked;
17959 Roo.Markdown.marked = marked;
17963 * Ext JS Library 1.1.1
17964 * Copyright(c) 2006-2007, Ext JS, LLC.
17966 * Originally Released Under LGPL - original licence link has changed is not relivant.
17969 * <script type="text/javascript">
17975 * These classes are derivatives of the similarly named classes in the YUI Library.
17976 * The original license:
17977 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
17978 * Code licensed under the BSD License:
17979 * http://developer.yahoo.net/yui/license.txt
17984 var Event=Roo.EventManager;
17985 var Dom=Roo.lib.Dom;
17988 * @class Roo.dd.DragDrop
17989 * @extends Roo.util.Observable
17990 * Defines the interface and base operation of items that that can be
17991 * dragged or can be drop targets. It was designed to be extended, overriding
17992 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
17993 * Up to three html elements can be associated with a DragDrop instance:
17995 * <li>linked element: the element that is passed into the constructor.
17996 * This is the element which defines the boundaries for interaction with
17997 * other DragDrop objects.</li>
17998 * <li>handle element(s): The drag operation only occurs if the element that
17999 * was clicked matches a handle element. By default this is the linked
18000 * element, but there are times that you will want only a portion of the
18001 * linked element to initiate the drag operation, and the setHandleElId()
18002 * method provides a way to define this.</li>
18003 * <li>drag element: this represents the element that would be moved along
18004 * with the cursor during a drag operation. By default, this is the linked
18005 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
18006 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
18009 * This class should not be instantiated until the onload event to ensure that
18010 * the associated elements are available.
18011 * The following would define a DragDrop obj that would interact with any
18012 * other DragDrop obj in the "group1" group:
18014 * dd = new Roo.dd.DragDrop("div1", "group1");
18016 * Since none of the event handlers have been implemented, nothing would
18017 * actually happen if you were to run the code above. Normally you would
18018 * override this class or one of the default implementations, but you can
18019 * also override the methods you want on an instance of the class...
18021 * dd.onDragDrop = function(e, id) {
18022 * alert("dd was dropped on " + id);
18026 * @param {String} id of the element that is linked to this instance
18027 * @param {String} sGroup the group of related DragDrop objects
18028 * @param {object} config an object containing configurable attributes
18029 * Valid properties for DragDrop:
18030 * padding, isTarget, maintainOffset, primaryButtonOnly
18032 Roo.dd.DragDrop = function(id, sGroup, config) {
18034 this.init(id, sGroup, config);
18039 Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
18042 * The id of the element associated with this object. This is what we
18043 * refer to as the "linked element" because the size and position of
18044 * this element is used to determine when the drag and drop objects have
18052 * Configuration attributes passed into the constructor
18059 * The id of the element that will be dragged. By default this is same
18060 * as the linked element , but could be changed to another element. Ex:
18062 * @property dragElId
18069 * the id of the element that initiates the drag operation. By default
18070 * this is the linked element, but could be changed to be a child of this
18071 * element. This lets us do things like only starting the drag when the
18072 * header element within the linked html element is clicked.
18073 * @property handleElId
18080 * An associative array of HTML tags that will be ignored if clicked.
18081 * @property invalidHandleTypes
18082 * @type {string: string}
18084 invalidHandleTypes: null,
18087 * An associative array of ids for elements that will be ignored if clicked
18088 * @property invalidHandleIds
18089 * @type {string: string}
18091 invalidHandleIds: null,
18094 * An indexted array of css class names for elements that will be ignored
18096 * @property invalidHandleClasses
18099 invalidHandleClasses: null,
18102 * The linked element's absolute X position at the time the drag was
18104 * @property startPageX
18111 * The linked element's absolute X position at the time the drag was
18113 * @property startPageY
18120 * The group defines a logical collection of DragDrop objects that are
18121 * related. Instances only get events when interacting with other
18122 * DragDrop object in the same group. This lets us define multiple
18123 * groups using a single DragDrop subclass if we want.
18125 * @type {string: string}
18130 * Individual drag/drop instances can be locked. This will prevent
18131 * onmousedown start drag.
18139 * Lock this instance
18142 lock: function() { this.locked = true; },
18145 * Unlock this instace
18148 unlock: function() { this.locked = false; },
18151 * By default, all insances can be a drop target. This can be disabled by
18152 * setting isTarget to false.
18159 * The padding configured for this drag and drop object for calculating
18160 * the drop zone intersection with this object.
18167 * Cached reference to the linked element
18168 * @property _domRef
18174 * Internal typeof flag
18175 * @property __ygDragDrop
18178 __ygDragDrop: true,
18181 * Set to true when horizontal contraints are applied
18182 * @property constrainX
18189 * Set to true when vertical contraints are applied
18190 * @property constrainY
18197 * The left constraint
18205 * The right constraint
18213 * The up constraint
18222 * The down constraint
18230 * Maintain offsets when we resetconstraints. Set to true when you want
18231 * the position of the element relative to its parent to stay the same
18232 * when the page changes
18234 * @property maintainOffset
18237 maintainOffset: false,
18240 * Array of pixel locations the element will snap to if we specified a
18241 * horizontal graduation/interval. This array is generated automatically
18242 * when you define a tick interval.
18249 * Array of pixel locations the element will snap to if we specified a
18250 * vertical graduation/interval. This array is generated automatically
18251 * when you define a tick interval.
18258 * By default the drag and drop instance will only respond to the primary
18259 * button click (left button for a right-handed mouse). Set to true to
18260 * allow drag and drop to start with any mouse click that is propogated
18262 * @property primaryButtonOnly
18265 primaryButtonOnly: true,
18268 * The availabe property is false until the linked dom element is accessible.
18269 * @property available
18275 * By default, drags can only be initiated if the mousedown occurs in the
18276 * region the linked element is. This is done in part to work around a
18277 * bug in some browsers that mis-report the mousedown if the previous
18278 * mouseup happened outside of the window. This property is set to true
18279 * if outer handles are defined.
18281 * @property hasOuterHandles
18285 hasOuterHandles: false,
18288 * Code that executes immediately before the startDrag event
18289 * @method b4StartDrag
18292 b4StartDrag: function(x, y) { },
18295 * Abstract method called after a drag/drop object is clicked
18296 * and the drag or mousedown time thresholds have beeen met.
18297 * @method startDrag
18298 * @param {int} X click location
18299 * @param {int} Y click location
18301 startDrag: function(x, y) { /* override this */ },
18304 * Code that executes immediately before the onDrag event
18308 b4Drag: function(e) { },
18311 * Abstract method called during the onMouseMove event while dragging an
18314 * @param {Event} e the mousemove event
18316 onDrag: function(e) { /* override this */ },
18319 * Abstract method called when this element fist begins hovering over
18320 * another DragDrop obj
18321 * @method onDragEnter
18322 * @param {Event} e the mousemove event
18323 * @param {String|DragDrop[]} id In POINT mode, the element
18324 * id this is hovering over. In INTERSECT mode, an array of one or more
18325 * dragdrop items being hovered over.
18327 onDragEnter: function(e, id) { /* override this */ },
18330 * Code that executes immediately before the onDragOver event
18331 * @method b4DragOver
18334 b4DragOver: function(e) { },
18337 * Abstract method called when this element is hovering over another
18339 * @method onDragOver
18340 * @param {Event} e the mousemove event
18341 * @param {String|DragDrop[]} id In POINT mode, the element
18342 * id this is hovering over. In INTERSECT mode, an array of dd items
18343 * being hovered over.
18345 onDragOver: function(e, id) { /* override this */ },
18348 * Code that executes immediately before the onDragOut event
18349 * @method b4DragOut
18352 b4DragOut: function(e) { },
18355 * Abstract method called when we are no longer hovering over an element
18356 * @method onDragOut
18357 * @param {Event} e the mousemove event
18358 * @param {String|DragDrop[]} id In POINT mode, the element
18359 * id this was hovering over. In INTERSECT mode, an array of dd items
18360 * that the mouse is no longer over.
18362 onDragOut: function(e, id) { /* override this */ },
18365 * Code that executes immediately before the onDragDrop event
18366 * @method b4DragDrop
18369 b4DragDrop: function(e) { },
18372 * Abstract method called when this item is dropped on another DragDrop
18374 * @method onDragDrop
18375 * @param {Event} e the mouseup event
18376 * @param {String|DragDrop[]} id In POINT mode, the element
18377 * id this was dropped on. In INTERSECT mode, an array of dd items this
18380 onDragDrop: function(e, id) { /* override this */ },
18383 * Abstract method called when this item is dropped on an area with no
18385 * @method onInvalidDrop
18386 * @param {Event} e the mouseup event
18388 onInvalidDrop: function(e) { /* override this */ },
18391 * Code that executes immediately before the endDrag event
18392 * @method b4EndDrag
18395 b4EndDrag: function(e) { },
18398 * Fired when we are done dragging the object
18400 * @param {Event} e the mouseup event
18402 endDrag: function(e) { /* override this */ },
18405 * Code executed immediately before the onMouseDown event
18406 * @method b4MouseDown
18407 * @param {Event} e the mousedown event
18410 b4MouseDown: function(e) { },
18413 * Event handler that fires when a drag/drop obj gets a mousedown
18414 * @method onMouseDown
18415 * @param {Event} e the mousedown event
18417 onMouseDown: function(e) { /* override this */ },
18420 * Event handler that fires when a drag/drop obj gets a mouseup
18421 * @method onMouseUp
18422 * @param {Event} e the mouseup event
18424 onMouseUp: function(e) { /* override this */ },
18427 * Override the onAvailable method to do what is needed after the initial
18428 * position was determined.
18429 * @method onAvailable
18431 onAvailable: function () {
18435 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
18438 defaultPadding : {left:0, right:0, top:0, bottom:0},
18441 * Initializes the drag drop object's constraints to restrict movement to a certain element.
18445 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
18446 { dragElId: "existingProxyDiv" });
18447 dd.startDrag = function(){
18448 this.constrainTo("parent-id");
18451 * Or you can initalize it using the {@link Roo.Element} object:
18453 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
18454 startDrag : function(){
18455 this.constrainTo("parent-id");
18459 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
18460 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
18461 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
18462 * an object containing the sides to pad. For example: {right:10, bottom:10}
18463 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
18465 constrainTo : function(constrainTo, pad, inContent){
18466 if(typeof pad == "number"){
18467 pad = {left: pad, right:pad, top:pad, bottom:pad};
18469 pad = pad || this.defaultPadding;
18470 var b = Roo.get(this.getEl()).getBox();
18471 var ce = Roo.get(constrainTo);
18472 var s = ce.getScroll();
18473 var c, cd = ce.dom;
18474 if(cd == document.body){
18475 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
18478 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
18482 var topSpace = b.y - c.y;
18483 var leftSpace = b.x - c.x;
18485 this.resetConstraints();
18486 this.setXConstraint(leftSpace - (pad.left||0), // left
18487 c.width - leftSpace - b.width - (pad.right||0) //right
18489 this.setYConstraint(topSpace - (pad.top||0), //top
18490 c.height - topSpace - b.height - (pad.bottom||0) //bottom
18495 * Returns a reference to the linked element
18497 * @return {HTMLElement} the html element
18499 getEl: function() {
18500 if (!this._domRef) {
18501 this._domRef = Roo.getDom(this.id);
18504 return this._domRef;
18508 * Returns a reference to the actual element to drag. By default this is
18509 * the same as the html element, but it can be assigned to another
18510 * element. An example of this can be found in Roo.dd.DDProxy
18511 * @method getDragEl
18512 * @return {HTMLElement} the html element
18514 getDragEl: function() {
18515 return Roo.getDom(this.dragElId);
18519 * Sets up the DragDrop object. Must be called in the constructor of any
18520 * Roo.dd.DragDrop subclass
18522 * @param id the id of the linked element
18523 * @param {String} sGroup the group of related items
18524 * @param {object} config configuration attributes
18526 init: function(id, sGroup, config) {
18527 this.initTarget(id, sGroup, config);
18528 if (!Roo.isTouch) {
18529 Event.on(this.id, "mousedown", this.handleMouseDown, this);
18531 Event.on(this.id, "touchstart", this.handleMouseDown, this);
18532 // Event.on(this.id, "selectstart", Event.preventDefault);
18536 * Initializes Targeting functionality only... the object does not
18537 * get a mousedown handler.
18538 * @method initTarget
18539 * @param id the id of the linked element
18540 * @param {String} sGroup the group of related items
18541 * @param {object} config configuration attributes
18543 initTarget: function(id, sGroup, config) {
18545 // configuration attributes
18546 this.config = config || {};
18548 // create a local reference to the drag and drop manager
18549 this.DDM = Roo.dd.DDM;
18550 // initialize the groups array
18553 // assume that we have an element reference instead of an id if the
18554 // parameter is not a string
18555 if (typeof id !== "string") {
18562 // add to an interaction group
18563 this.addToGroup((sGroup) ? sGroup : "default");
18565 // We don't want to register this as the handle with the manager
18566 // so we just set the id rather than calling the setter.
18567 this.handleElId = id;
18569 // the linked element is the element that gets dragged by default
18570 this.setDragElId(id);
18572 // by default, clicked anchors will not start drag operations.
18573 this.invalidHandleTypes = { A: "A" };
18574 this.invalidHandleIds = {};
18575 this.invalidHandleClasses = [];
18577 this.applyConfig();
18579 this.handleOnAvailable();
18583 * Applies the configuration parameters that were passed into the constructor.
18584 * This is supposed to happen at each level through the inheritance chain. So
18585 * a DDProxy implentation will execute apply config on DDProxy, DD, and
18586 * DragDrop in order to get all of the parameters that are available in
18588 * @method applyConfig
18590 applyConfig: function() {
18592 // configurable properties:
18593 // padding, isTarget, maintainOffset, primaryButtonOnly
18594 this.padding = this.config.padding || [0, 0, 0, 0];
18595 this.isTarget = (this.config.isTarget !== false);
18596 this.maintainOffset = (this.config.maintainOffset);
18597 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
18602 * Executed when the linked element is available
18603 * @method handleOnAvailable
18606 handleOnAvailable: function() {
18607 this.available = true;
18608 this.resetConstraints();
18609 this.onAvailable();
18613 * Configures the padding for the target zone in px. Effectively expands
18614 * (or reduces) the virtual object size for targeting calculations.
18615 * Supports css-style shorthand; if only one parameter is passed, all sides
18616 * will have that padding, and if only two are passed, the top and bottom
18617 * will have the first param, the left and right the second.
18618 * @method setPadding
18619 * @param {int} iTop Top pad
18620 * @param {int} iRight Right pad
18621 * @param {int} iBot Bot pad
18622 * @param {int} iLeft Left pad
18624 setPadding: function(iTop, iRight, iBot, iLeft) {
18625 // this.padding = [iLeft, iRight, iTop, iBot];
18626 if (!iRight && 0 !== iRight) {
18627 this.padding = [iTop, iTop, iTop, iTop];
18628 } else if (!iBot && 0 !== iBot) {
18629 this.padding = [iTop, iRight, iTop, iRight];
18631 this.padding = [iTop, iRight, iBot, iLeft];
18636 * Stores the initial placement of the linked element.
18637 * @method setInitialPosition
18638 * @param {int} diffX the X offset, default 0
18639 * @param {int} diffY the Y offset, default 0
18641 setInitPosition: function(diffX, diffY) {
18642 var el = this.getEl();
18644 if (!this.DDM.verifyEl(el)) {
18648 var dx = diffX || 0;
18649 var dy = diffY || 0;
18651 var p = Dom.getXY( el );
18653 this.initPageX = p[0] - dx;
18654 this.initPageY = p[1] - dy;
18656 this.lastPageX = p[0];
18657 this.lastPageY = p[1];
18660 this.setStartPosition(p);
18664 * Sets the start position of the element. This is set when the obj
18665 * is initialized, the reset when a drag is started.
18666 * @method setStartPosition
18667 * @param pos current position (from previous lookup)
18670 setStartPosition: function(pos) {
18671 var p = pos || Dom.getXY( this.getEl() );
18672 this.deltaSetXY = null;
18674 this.startPageX = p[0];
18675 this.startPageY = p[1];
18679 * Add this instance to a group of related drag/drop objects. All
18680 * instances belong to at least one group, and can belong to as many
18681 * groups as needed.
18682 * @method addToGroup
18683 * @param sGroup {string} the name of the group
18685 addToGroup: function(sGroup) {
18686 this.groups[sGroup] = true;
18687 this.DDM.regDragDrop(this, sGroup);
18691 * Remove's this instance from the supplied interaction group
18692 * @method removeFromGroup
18693 * @param {string} sGroup The group to drop
18695 removeFromGroup: function(sGroup) {
18696 if (this.groups[sGroup]) {
18697 delete this.groups[sGroup];
18700 this.DDM.removeDDFromGroup(this, sGroup);
18704 * Allows you to specify that an element other than the linked element
18705 * will be moved with the cursor during a drag
18706 * @method setDragElId
18707 * @param id {string} the id of the element that will be used to initiate the drag
18709 setDragElId: function(id) {
18710 this.dragElId = id;
18714 * Allows you to specify a child of the linked element that should be
18715 * used to initiate the drag operation. An example of this would be if
18716 * you have a content div with text and links. Clicking anywhere in the
18717 * content area would normally start the drag operation. Use this method
18718 * to specify that an element inside of the content div is the element
18719 * that starts the drag operation.
18720 * @method setHandleElId
18721 * @param id {string} the id of the element that will be used to
18722 * initiate the drag.
18724 setHandleElId: function(id) {
18725 if (typeof id !== "string") {
18728 this.handleElId = id;
18729 this.DDM.regHandle(this.id, id);
18733 * Allows you to set an element outside of the linked element as a drag
18735 * @method setOuterHandleElId
18736 * @param id the id of the element that will be used to initiate the drag
18738 setOuterHandleElId: function(id) {
18739 if (typeof id !== "string") {
18742 Event.on(id, "mousedown",
18743 this.handleMouseDown, this);
18744 this.setHandleElId(id);
18746 this.hasOuterHandles = true;
18750 * Remove all drag and drop hooks for this element
18753 unreg: function() {
18754 Event.un(this.id, "mousedown",
18755 this.handleMouseDown);
18756 Event.un(this.id, "touchstart",
18757 this.handleMouseDown);
18758 this._domRef = null;
18759 this.DDM._remove(this);
18762 destroy : function(){
18767 * Returns true if this instance is locked, or the drag drop mgr is locked
18768 * (meaning that all drag/drop is disabled on the page.)
18770 * @return {boolean} true if this obj or all drag/drop is locked, else
18773 isLocked: function() {
18774 return (this.DDM.isLocked() || this.locked);
18778 * Fired when this object is clicked
18779 * @method handleMouseDown
18781 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
18784 handleMouseDown: function(e, oDD){
18786 if (!Roo.isTouch && this.primaryButtonOnly && e.button != 0) {
18787 //Roo.log('not touch/ button !=0');
18790 if (e.browserEvent.touches && e.browserEvent.touches.length != 1) {
18791 return; // double touch..
18795 if (this.isLocked()) {
18796 //Roo.log('locked');
18800 this.DDM.refreshCache(this.groups);
18801 // Roo.log([Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e)]);
18802 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
18803 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
18804 //Roo.log('no outer handes or not over target');
18807 // Roo.log('check validator');
18808 if (this.clickValidator(e)) {
18809 // Roo.log('validate success');
18810 // set the initial element position
18811 this.setStartPosition();
18814 this.b4MouseDown(e);
18815 this.onMouseDown(e);
18817 this.DDM.handleMouseDown(e, this);
18819 this.DDM.stopEvent(e);
18827 clickValidator: function(e) {
18828 var target = e.getTarget();
18829 return ( this.isValidHandleChild(target) &&
18830 (this.id == this.handleElId ||
18831 this.DDM.handleWasClicked(target, this.id)) );
18835 * Allows you to specify a tag name that should not start a drag operation
18836 * when clicked. This is designed to facilitate embedding links within a
18837 * drag handle that do something other than start the drag.
18838 * @method addInvalidHandleType
18839 * @param {string} tagName the type of element to exclude
18841 addInvalidHandleType: function(tagName) {
18842 var type = tagName.toUpperCase();
18843 this.invalidHandleTypes[type] = type;
18847 * Lets you to specify an element id for a child of a drag handle
18848 * that should not initiate a drag
18849 * @method addInvalidHandleId
18850 * @param {string} id the element id of the element you wish to ignore
18852 addInvalidHandleId: function(id) {
18853 if (typeof id !== "string") {
18856 this.invalidHandleIds[id] = id;
18860 * Lets you specify a css class of elements that will not initiate a drag
18861 * @method addInvalidHandleClass
18862 * @param {string} cssClass the class of the elements you wish to ignore
18864 addInvalidHandleClass: function(cssClass) {
18865 this.invalidHandleClasses.push(cssClass);
18869 * Unsets an excluded tag name set by addInvalidHandleType
18870 * @method removeInvalidHandleType
18871 * @param {string} tagName the type of element to unexclude
18873 removeInvalidHandleType: function(tagName) {
18874 var type = tagName.toUpperCase();
18875 // this.invalidHandleTypes[type] = null;
18876 delete this.invalidHandleTypes[type];
18880 * Unsets an invalid handle id
18881 * @method removeInvalidHandleId
18882 * @param {string} id the id of the element to re-enable
18884 removeInvalidHandleId: function(id) {
18885 if (typeof id !== "string") {
18888 delete this.invalidHandleIds[id];
18892 * Unsets an invalid css class
18893 * @method removeInvalidHandleClass
18894 * @param {string} cssClass the class of the element(s) you wish to
18897 removeInvalidHandleClass: function(cssClass) {
18898 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
18899 if (this.invalidHandleClasses[i] == cssClass) {
18900 delete this.invalidHandleClasses[i];
18906 * Checks the tag exclusion list to see if this click should be ignored
18907 * @method isValidHandleChild
18908 * @param {HTMLElement} node the HTMLElement to evaluate
18909 * @return {boolean} true if this is a valid tag type, false if not
18911 isValidHandleChild: function(node) {
18914 // var n = (node.nodeName == "#text") ? node.parentNode : node;
18917 nodeName = node.nodeName.toUpperCase();
18919 nodeName = node.nodeName;
18921 valid = valid && !this.invalidHandleTypes[nodeName];
18922 valid = valid && !this.invalidHandleIds[node.id];
18924 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
18925 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
18934 * Create the array of horizontal tick marks if an interval was specified
18935 * in setXConstraint().
18936 * @method setXTicks
18939 setXTicks: function(iStartX, iTickSize) {
18941 this.xTickSize = iTickSize;
18945 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
18947 this.xTicks[this.xTicks.length] = i;
18952 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
18954 this.xTicks[this.xTicks.length] = i;
18959 this.xTicks.sort(this.DDM.numericSort) ;
18963 * Create the array of vertical tick marks if an interval was specified in
18964 * setYConstraint().
18965 * @method setYTicks
18968 setYTicks: function(iStartY, iTickSize) {
18970 this.yTickSize = iTickSize;
18974 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
18976 this.yTicks[this.yTicks.length] = i;
18981 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
18983 this.yTicks[this.yTicks.length] = i;
18988 this.yTicks.sort(this.DDM.numericSort) ;
18992 * By default, the element can be dragged any place on the screen. Use
18993 * this method to limit the horizontal travel of the element. Pass in
18994 * 0,0 for the parameters if you want to lock the drag to the y axis.
18995 * @method setXConstraint
18996 * @param {int} iLeft the number of pixels the element can move to the left
18997 * @param {int} iRight the number of pixels the element can move to the
18999 * @param {int} iTickSize optional parameter for specifying that the
19001 * should move iTickSize pixels at a time.
19003 setXConstraint: function(iLeft, iRight, iTickSize) {
19004 this.leftConstraint = iLeft;
19005 this.rightConstraint = iRight;
19007 this.minX = this.initPageX - iLeft;
19008 this.maxX = this.initPageX + iRight;
19009 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
19011 this.constrainX = true;
19015 * Clears any constraints applied to this instance. Also clears ticks
19016 * since they can't exist independent of a constraint at this time.
19017 * @method clearConstraints
19019 clearConstraints: function() {
19020 this.constrainX = false;
19021 this.constrainY = false;
19026 * Clears any tick interval defined for this instance
19027 * @method clearTicks
19029 clearTicks: function() {
19030 this.xTicks = null;
19031 this.yTicks = null;
19032 this.xTickSize = 0;
19033 this.yTickSize = 0;
19037 * By default, the element can be dragged any place on the screen. Set
19038 * this to limit the vertical travel of the element. Pass in 0,0 for the
19039 * parameters if you want to lock the drag to the x axis.
19040 * @method setYConstraint
19041 * @param {int} iUp the number of pixels the element can move up
19042 * @param {int} iDown the number of pixels the element can move down
19043 * @param {int} iTickSize optional parameter for specifying that the
19044 * element should move iTickSize pixels at a time.
19046 setYConstraint: function(iUp, iDown, iTickSize) {
19047 this.topConstraint = iUp;
19048 this.bottomConstraint = iDown;
19050 this.minY = this.initPageY - iUp;
19051 this.maxY = this.initPageY + iDown;
19052 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
19054 this.constrainY = true;
19059 * resetConstraints must be called if you manually reposition a dd element.
19060 * @method resetConstraints
19061 * @param {boolean} maintainOffset
19063 resetConstraints: function() {
19066 // Maintain offsets if necessary
19067 if (this.initPageX || this.initPageX === 0) {
19068 // figure out how much this thing has moved
19069 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
19070 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
19072 this.setInitPosition(dx, dy);
19074 // This is the first time we have detected the element's position
19076 this.setInitPosition();
19079 if (this.constrainX) {
19080 this.setXConstraint( this.leftConstraint,
19081 this.rightConstraint,
19085 if (this.constrainY) {
19086 this.setYConstraint( this.topConstraint,
19087 this.bottomConstraint,
19093 * Normally the drag element is moved pixel by pixel, but we can specify
19094 * that it move a number of pixels at a time. This method resolves the
19095 * location when we have it set up like this.
19097 * @param {int} val where we want to place the object
19098 * @param {int[]} tickArray sorted array of valid points
19099 * @return {int} the closest tick
19102 getTick: function(val, tickArray) {
19105 // If tick interval is not defined, it is effectively 1 pixel,
19106 // so we return the value passed to us.
19108 } else if (tickArray[0] >= val) {
19109 // The value is lower than the first tick, so we return the first
19111 return tickArray[0];
19113 for (var i=0, len=tickArray.length; i<len; ++i) {
19115 if (tickArray[next] && tickArray[next] >= val) {
19116 var diff1 = val - tickArray[i];
19117 var diff2 = tickArray[next] - val;
19118 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
19122 // The value is larger than the last tick, so we return the last
19124 return tickArray[tickArray.length - 1];
19131 * @return {string} string representation of the dd obj
19133 toString: function() {
19134 return ("DragDrop " + this.id);
19142 * Ext JS Library 1.1.1
19143 * Copyright(c) 2006-2007, Ext JS, LLC.
19145 * Originally Released Under LGPL - original licence link has changed is not relivant.
19148 * <script type="text/javascript">
19153 * The drag and drop utility provides a framework for building drag and drop
19154 * applications. In addition to enabling drag and drop for specific elements,
19155 * the drag and drop elements are tracked by the manager class, and the
19156 * interactions between the various elements are tracked during the drag and
19157 * the implementing code is notified about these important moments.
19160 // Only load the library once. Rewriting the manager class would orphan
19161 // existing drag and drop instances.
19162 if (!Roo.dd.DragDropMgr) {
19165 * @class Roo.dd.DragDropMgr
19166 * DragDropMgr is a singleton that tracks the element interaction for
19167 * all DragDrop items in the window. Generally, you will not call
19168 * this class directly, but it does have helper methods that could
19169 * be useful in your DragDrop implementations.
19172 Roo.dd.DragDropMgr = function() {
19174 var Event = Roo.EventManager;
19179 * Two dimensional Array of registered DragDrop objects. The first
19180 * dimension is the DragDrop item group, the second the DragDrop
19183 * @type {string: string}
19190 * Array of element ids defined as drag handles. Used to determine
19191 * if the element that generated the mousedown event is actually the
19192 * handle and not the html element itself.
19193 * @property handleIds
19194 * @type {string: string}
19201 * the DragDrop object that is currently being dragged
19202 * @property dragCurrent
19210 * the DragDrop object(s) that are being hovered over
19211 * @property dragOvers
19219 * the X distance between the cursor and the object being dragged
19228 * the Y distance between the cursor and the object being dragged
19237 * Flag to determine if we should prevent the default behavior of the
19238 * events we define. By default this is true, but this can be set to
19239 * false if you need the default behavior (not recommended)
19240 * @property preventDefault
19244 preventDefault: true,
19247 * Flag to determine if we should stop the propagation of the events
19248 * we generate. This is true by default but you may want to set it to
19249 * false if the html element contains other features that require the
19251 * @property stopPropagation
19255 stopPropagation: true,
19258 * Internal flag that is set to true when drag and drop has been
19260 * @property initialized
19267 * All drag and drop can be disabled.
19275 * Called the first time an element is registered.
19281 this.initialized = true;
19285 * In point mode, drag and drop interaction is defined by the
19286 * location of the cursor during the drag/drop
19294 * In intersect mode, drag and drop interactio nis defined by the
19295 * overlap of two or more drag and drop objects.
19296 * @property INTERSECT
19303 * The current drag and drop mode. Default: POINT
19311 * Runs method on all drag and drop objects
19312 * @method _execOnAll
19316 _execOnAll: function(sMethod, args) {
19317 for (var i in this.ids) {
19318 for (var j in this.ids[i]) {
19319 var oDD = this.ids[i][j];
19320 if (! this.isTypeOfDD(oDD)) {
19323 oDD[sMethod].apply(oDD, args);
19329 * Drag and drop initialization. Sets up the global event handlers
19334 _onLoad: function() {
19338 if (!Roo.isTouch) {
19339 Event.on(document, "mouseup", this.handleMouseUp, this, true);
19340 Event.on(document, "mousemove", this.handleMouseMove, this, true);
19342 Event.on(document, "touchend", this.handleMouseUp, this, true);
19343 Event.on(document, "touchmove", this.handleMouseMove, this, true);
19345 Event.on(window, "unload", this._onUnload, this, true);
19346 Event.on(window, "resize", this._onResize, this, true);
19347 // Event.on(window, "mouseout", this._test);
19352 * Reset constraints on all drag and drop objs
19353 * @method _onResize
19357 _onResize: function(e) {
19358 this._execOnAll("resetConstraints", []);
19362 * Lock all drag and drop functionality
19366 lock: function() { this.locked = true; },
19369 * Unlock all drag and drop functionality
19373 unlock: function() { this.locked = false; },
19376 * Is drag and drop locked?
19378 * @return {boolean} True if drag and drop is locked, false otherwise.
19381 isLocked: function() { return this.locked; },
19384 * Location cache that is set for all drag drop objects when a drag is
19385 * initiated, cleared when the drag is finished.
19386 * @property locationCache
19393 * Set useCache to false if you want to force object the lookup of each
19394 * drag and drop linked element constantly during a drag.
19395 * @property useCache
19402 * The number of pixels that the mouse needs to move after the
19403 * mousedown before the drag is initiated. Default=3;
19404 * @property clickPixelThresh
19408 clickPixelThresh: 3,
19411 * The number of milliseconds after the mousedown event to initiate the
19412 * drag if we don't get a mouseup event. Default=1000
19413 * @property clickTimeThresh
19417 clickTimeThresh: 350,
19420 * Flag that indicates that either the drag pixel threshold or the
19421 * mousdown time threshold has been met
19422 * @property dragThreshMet
19427 dragThreshMet: false,
19430 * Timeout used for the click time threshold
19431 * @property clickTimeout
19436 clickTimeout: null,
19439 * The X position of the mousedown event stored for later use when a
19440 * drag threshold is met.
19449 * The Y position of the mousedown event stored for later use when a
19450 * drag threshold is met.
19459 * Each DragDrop instance must be registered with the DragDropMgr.
19460 * This is executed in DragDrop.init()
19461 * @method regDragDrop
19462 * @param {DragDrop} oDD the DragDrop object to register
19463 * @param {String} sGroup the name of the group this element belongs to
19466 regDragDrop: function(oDD, sGroup) {
19467 if (!this.initialized) { this.init(); }
19469 if (!this.ids[sGroup]) {
19470 this.ids[sGroup] = {};
19472 this.ids[sGroup][oDD.id] = oDD;
19476 * Removes the supplied dd instance from the supplied group. Executed
19477 * by DragDrop.removeFromGroup, so don't call this function directly.
19478 * @method removeDDFromGroup
19482 removeDDFromGroup: function(oDD, sGroup) {
19483 if (!this.ids[sGroup]) {
19484 this.ids[sGroup] = {};
19487 var obj = this.ids[sGroup];
19488 if (obj && obj[oDD.id]) {
19489 delete obj[oDD.id];
19494 * Unregisters a drag and drop item. This is executed in
19495 * DragDrop.unreg, use that method instead of calling this directly.
19500 _remove: function(oDD) {
19501 for (var g in oDD.groups) {
19502 if (g && this.ids[g][oDD.id]) {
19503 delete this.ids[g][oDD.id];
19506 delete this.handleIds[oDD.id];
19510 * Each DragDrop handle element must be registered. This is done
19511 * automatically when executing DragDrop.setHandleElId()
19512 * @method regHandle
19513 * @param {String} sDDId the DragDrop id this element is a handle for
19514 * @param {String} sHandleId the id of the element that is the drag
19518 regHandle: function(sDDId, sHandleId) {
19519 if (!this.handleIds[sDDId]) {
19520 this.handleIds[sDDId] = {};
19522 this.handleIds[sDDId][sHandleId] = sHandleId;
19526 * Utility function to determine if a given element has been
19527 * registered as a drag drop item.
19528 * @method isDragDrop
19529 * @param {String} id the element id to check
19530 * @return {boolean} true if this element is a DragDrop item,
19534 isDragDrop: function(id) {
19535 return ( this.getDDById(id) ) ? true : false;
19539 * Returns the drag and drop instances that are in all groups the
19540 * passed in instance belongs to.
19541 * @method getRelated
19542 * @param {DragDrop} p_oDD the obj to get related data for
19543 * @param {boolean} bTargetsOnly if true, only return targetable objs
19544 * @return {DragDrop[]} the related instances
19547 getRelated: function(p_oDD, bTargetsOnly) {
19549 for (var i in p_oDD.groups) {
19550 for (j in this.ids[i]) {
19551 var dd = this.ids[i][j];
19552 if (! this.isTypeOfDD(dd)) {
19555 if (!bTargetsOnly || dd.isTarget) {
19556 oDDs[oDDs.length] = dd;
19565 * Returns true if the specified dd target is a legal target for
19566 * the specifice drag obj
19567 * @method isLegalTarget
19568 * @param {DragDrop} the drag obj
19569 * @param {DragDrop} the target
19570 * @return {boolean} true if the target is a legal target for the
19574 isLegalTarget: function (oDD, oTargetDD) {
19575 var targets = this.getRelated(oDD, true);
19576 for (var i=0, len=targets.length;i<len;++i) {
19577 if (targets[i].id == oTargetDD.id) {
19586 * My goal is to be able to transparently determine if an object is
19587 * typeof DragDrop, and the exact subclass of DragDrop. typeof
19588 * returns "object", oDD.constructor.toString() always returns
19589 * "DragDrop" and not the name of the subclass. So for now it just
19590 * evaluates a well-known variable in DragDrop.
19591 * @method isTypeOfDD
19592 * @param {Object} the object to evaluate
19593 * @return {boolean} true if typeof oDD = DragDrop
19596 isTypeOfDD: function (oDD) {
19597 return (oDD && oDD.__ygDragDrop);
19601 * Utility function to determine if a given element has been
19602 * registered as a drag drop handle for the given Drag Drop object.
19604 * @param {String} id the element id to check
19605 * @return {boolean} true if this element is a DragDrop handle, false
19609 isHandle: function(sDDId, sHandleId) {
19610 return ( this.handleIds[sDDId] &&
19611 this.handleIds[sDDId][sHandleId] );
19615 * Returns the DragDrop instance for a given id
19616 * @method getDDById
19617 * @param {String} id the id of the DragDrop object
19618 * @return {DragDrop} the drag drop object, null if it is not found
19621 getDDById: function(id) {
19622 for (var i in this.ids) {
19623 if (this.ids[i][id]) {
19624 return this.ids[i][id];
19631 * Fired after a registered DragDrop object gets the mousedown event.
19632 * Sets up the events required to track the object being dragged
19633 * @method handleMouseDown
19634 * @param {Event} e the event
19635 * @param oDD the DragDrop object being dragged
19639 handleMouseDown: function(e, oDD) {
19641 Roo.QuickTips.disable();
19643 this.currentTarget = e.getTarget();
19645 this.dragCurrent = oDD;
19647 var el = oDD.getEl();
19649 // track start position
19650 this.startX = e.getPageX();
19651 this.startY = e.getPageY();
19653 this.deltaX = this.startX - el.offsetLeft;
19654 this.deltaY = this.startY - el.offsetTop;
19656 this.dragThreshMet = false;
19658 this.clickTimeout = setTimeout(
19660 var DDM = Roo.dd.DDM;
19661 DDM.startDrag(DDM.startX, DDM.startY);
19663 this.clickTimeThresh );
19667 * Fired when either the drag pixel threshol or the mousedown hold
19668 * time threshold has been met.
19669 * @method startDrag
19670 * @param x {int} the X position of the original mousedown
19671 * @param y {int} the Y position of the original mousedown
19674 startDrag: function(x, y) {
19675 clearTimeout(this.clickTimeout);
19676 if (this.dragCurrent) {
19677 this.dragCurrent.b4StartDrag(x, y);
19678 this.dragCurrent.startDrag(x, y);
19680 this.dragThreshMet = true;
19684 * Internal function to handle the mouseup event. Will be invoked
19685 * from the context of the document.
19686 * @method handleMouseUp
19687 * @param {Event} e the event
19691 handleMouseUp: function(e) {
19694 Roo.QuickTips.enable();
19696 if (! this.dragCurrent) {
19700 clearTimeout(this.clickTimeout);
19702 if (this.dragThreshMet) {
19703 this.fireEvents(e, true);
19713 * Utility to stop event propagation and event default, if these
19714 * features are turned on.
19715 * @method stopEvent
19716 * @param {Event} e the event as returned by this.getEvent()
19719 stopEvent: function(e){
19720 if(this.stopPropagation) {
19721 e.stopPropagation();
19724 if (this.preventDefault) {
19725 e.preventDefault();
19730 * Internal function to clean up event handlers after the drag
19731 * operation is complete
19733 * @param {Event} e the event
19737 stopDrag: function(e) {
19738 // Fire the drag end event for the item that was dragged
19739 if (this.dragCurrent) {
19740 if (this.dragThreshMet) {
19741 this.dragCurrent.b4EndDrag(e);
19742 this.dragCurrent.endDrag(e);
19745 this.dragCurrent.onMouseUp(e);
19748 this.dragCurrent = null;
19749 this.dragOvers = {};
19753 * Internal function to handle the mousemove event. Will be invoked
19754 * from the context of the html element.
19756 * @TODO figure out what we can do about mouse events lost when the
19757 * user drags objects beyond the window boundary. Currently we can
19758 * detect this in internet explorer by verifying that the mouse is
19759 * down during the mousemove event. Firefox doesn't give us the
19760 * button state on the mousemove event.
19761 * @method handleMouseMove
19762 * @param {Event} e the event
19766 handleMouseMove: function(e) {
19767 if (! this.dragCurrent) {
19771 // var button = e.which || e.button;
19773 // check for IE mouseup outside of page boundary
19774 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
19776 return this.handleMouseUp(e);
19779 if (!this.dragThreshMet) {
19780 var diffX = Math.abs(this.startX - e.getPageX());
19781 var diffY = Math.abs(this.startY - e.getPageY());
19782 if (diffX > this.clickPixelThresh ||
19783 diffY > this.clickPixelThresh) {
19784 this.startDrag(this.startX, this.startY);
19788 if (this.dragThreshMet) {
19789 this.dragCurrent.b4Drag(e);
19790 this.dragCurrent.onDrag(e);
19791 if(!this.dragCurrent.moveOnly){
19792 this.fireEvents(e, false);
19802 * Iterates over all of the DragDrop elements to find ones we are
19803 * hovering over or dropping on
19804 * @method fireEvents
19805 * @param {Event} e the event
19806 * @param {boolean} isDrop is this a drop op or a mouseover op?
19810 fireEvents: function(e, isDrop) {
19811 var dc = this.dragCurrent;
19813 // If the user did the mouse up outside of the window, we could
19814 // get here even though we have ended the drag.
19815 if (!dc || dc.isLocked()) {
19819 var pt = e.getPoint();
19821 // cache the previous dragOver array
19827 var enterEvts = [];
19829 // Check to see if the object(s) we were hovering over is no longer
19830 // being hovered over so we can fire the onDragOut event
19831 for (var i in this.dragOvers) {
19833 var ddo = this.dragOvers[i];
19835 if (! this.isTypeOfDD(ddo)) {
19839 if (! this.isOverTarget(pt, ddo, this.mode)) {
19840 outEvts.push( ddo );
19843 oldOvers[i] = true;
19844 delete this.dragOvers[i];
19847 for (var sGroup in dc.groups) {
19849 if ("string" != typeof sGroup) {
19853 for (i in this.ids[sGroup]) {
19854 var oDD = this.ids[sGroup][i];
19855 if (! this.isTypeOfDD(oDD)) {
19859 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
19860 if (this.isOverTarget(pt, oDD, this.mode)) {
19861 // look for drop interactions
19863 dropEvts.push( oDD );
19864 // look for drag enter and drag over interactions
19867 // initial drag over: dragEnter fires
19868 if (!oldOvers[oDD.id]) {
19869 enterEvts.push( oDD );
19870 // subsequent drag overs: dragOver fires
19872 overEvts.push( oDD );
19875 this.dragOvers[oDD.id] = oDD;
19883 if (outEvts.length) {
19884 dc.b4DragOut(e, outEvts);
19885 dc.onDragOut(e, outEvts);
19888 if (enterEvts.length) {
19889 dc.onDragEnter(e, enterEvts);
19892 if (overEvts.length) {
19893 dc.b4DragOver(e, overEvts);
19894 dc.onDragOver(e, overEvts);
19897 if (dropEvts.length) {
19898 dc.b4DragDrop(e, dropEvts);
19899 dc.onDragDrop(e, dropEvts);
19903 // fire dragout events
19905 for (i=0, len=outEvts.length; i<len; ++i) {
19906 dc.b4DragOut(e, outEvts[i].id);
19907 dc.onDragOut(e, outEvts[i].id);
19910 // fire enter events
19911 for (i=0,len=enterEvts.length; i<len; ++i) {
19912 // dc.b4DragEnter(e, oDD.id);
19913 dc.onDragEnter(e, enterEvts[i].id);
19916 // fire over events
19917 for (i=0,len=overEvts.length; i<len; ++i) {
19918 dc.b4DragOver(e, overEvts[i].id);
19919 dc.onDragOver(e, overEvts[i].id);
19922 // fire drop events
19923 for (i=0, len=dropEvts.length; i<len; ++i) {
19924 dc.b4DragDrop(e, dropEvts[i].id);
19925 dc.onDragDrop(e, dropEvts[i].id);
19930 // notify about a drop that did not find a target
19931 if (isDrop && !dropEvts.length) {
19932 dc.onInvalidDrop(e);
19938 * Helper function for getting the best match from the list of drag
19939 * and drop objects returned by the drag and drop events when we are
19940 * in INTERSECT mode. It returns either the first object that the
19941 * cursor is over, or the object that has the greatest overlap with
19942 * the dragged element.
19943 * @method getBestMatch
19944 * @param {DragDrop[]} dds The array of drag and drop objects
19946 * @return {DragDrop} The best single match
19949 getBestMatch: function(dds) {
19951 // Return null if the input is not what we expect
19952 //if (!dds || !dds.length || dds.length == 0) {
19954 // If there is only one item, it wins
19955 //} else if (dds.length == 1) {
19957 var len = dds.length;
19962 // Loop through the targeted items
19963 for (var i=0; i<len; ++i) {
19965 // If the cursor is over the object, it wins. If the
19966 // cursor is over multiple matches, the first one we come
19968 if (dd.cursorIsOver) {
19971 // Otherwise the object with the most overlap wins
19974 winner.overlap.getArea() < dd.overlap.getArea()) {
19985 * Refreshes the cache of the top-left and bottom-right points of the
19986 * drag and drop objects in the specified group(s). This is in the
19987 * format that is stored in the drag and drop instance, so typical
19990 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
19994 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
19996 * @TODO this really should be an indexed array. Alternatively this
19997 * method could accept both.
19998 * @method refreshCache
19999 * @param {Object} groups an associative array of groups to refresh
20002 refreshCache: function(groups) {
20003 for (var sGroup in groups) {
20004 if ("string" != typeof sGroup) {
20007 for (var i in this.ids[sGroup]) {
20008 var oDD = this.ids[sGroup][i];
20010 if (this.isTypeOfDD(oDD)) {
20011 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
20012 var loc = this.getLocation(oDD);
20014 this.locationCache[oDD.id] = loc;
20016 delete this.locationCache[oDD.id];
20017 // this will unregister the drag and drop object if
20018 // the element is not in a usable state
20027 * This checks to make sure an element exists and is in the DOM. The
20028 * main purpose is to handle cases where innerHTML is used to remove
20029 * drag and drop objects from the DOM. IE provides an 'unspecified
20030 * error' when trying to access the offsetParent of such an element
20032 * @param {HTMLElement} el the element to check
20033 * @return {boolean} true if the element looks usable
20036 verifyEl: function(el) {
20041 parent = el.offsetParent;
20044 parent = el.offsetParent;
20055 * Returns a Region object containing the drag and drop element's position
20056 * and size, including the padding configured for it
20057 * @method getLocation
20058 * @param {DragDrop} oDD the drag and drop object to get the
20060 * @return {Roo.lib.Region} a Region object representing the total area
20061 * the element occupies, including any padding
20062 * the instance is configured for.
20065 getLocation: function(oDD) {
20066 if (! this.isTypeOfDD(oDD)) {
20070 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
20073 pos= Roo.lib.Dom.getXY(el);
20081 x2 = x1 + el.offsetWidth;
20083 y2 = y1 + el.offsetHeight;
20085 t = y1 - oDD.padding[0];
20086 r = x2 + oDD.padding[1];
20087 b = y2 + oDD.padding[2];
20088 l = x1 - oDD.padding[3];
20090 return new Roo.lib.Region( t, r, b, l );
20094 * Checks the cursor location to see if it over the target
20095 * @method isOverTarget
20096 * @param {Roo.lib.Point} pt The point to evaluate
20097 * @param {DragDrop} oTarget the DragDrop object we are inspecting
20098 * @return {boolean} true if the mouse is over the target
20102 isOverTarget: function(pt, oTarget, intersect) {
20103 // use cache if available
20104 var loc = this.locationCache[oTarget.id];
20105 if (!loc || !this.useCache) {
20106 loc = this.getLocation(oTarget);
20107 this.locationCache[oTarget.id] = loc;
20115 oTarget.cursorIsOver = loc.contains( pt );
20117 // DragDrop is using this as a sanity check for the initial mousedown
20118 // in this case we are done. In POINT mode, if the drag obj has no
20119 // contraints, we are also done. Otherwise we need to evaluate the
20120 // location of the target as related to the actual location of the
20121 // dragged element.
20122 var dc = this.dragCurrent;
20123 if (!dc || !dc.getTargetCoord ||
20124 (!intersect && !dc.constrainX && !dc.constrainY)) {
20125 return oTarget.cursorIsOver;
20128 oTarget.overlap = null;
20130 // Get the current location of the drag element, this is the
20131 // location of the mouse event less the delta that represents
20132 // where the original mousedown happened on the element. We
20133 // need to consider constraints and ticks as well.
20134 var pos = dc.getTargetCoord(pt.x, pt.y);
20136 var el = dc.getDragEl();
20137 var curRegion = new Roo.lib.Region( pos.y,
20138 pos.x + el.offsetWidth,
20139 pos.y + el.offsetHeight,
20142 var overlap = curRegion.intersect(loc);
20145 oTarget.overlap = overlap;
20146 return (intersect) ? true : oTarget.cursorIsOver;
20153 * unload event handler
20154 * @method _onUnload
20158 _onUnload: function(e, me) {
20159 Roo.dd.DragDropMgr.unregAll();
20163 * Cleans up the drag and drop events and objects.
20168 unregAll: function() {
20170 if (this.dragCurrent) {
20172 this.dragCurrent = null;
20175 this._execOnAll("unreg", []);
20177 for (i in this.elementCache) {
20178 delete this.elementCache[i];
20181 this.elementCache = {};
20186 * A cache of DOM elements
20187 * @property elementCache
20194 * Get the wrapper for the DOM element specified
20195 * @method getElWrapper
20196 * @param {String} id the id of the element to get
20197 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
20199 * @deprecated This wrapper isn't that useful
20202 getElWrapper: function(id) {
20203 var oWrapper = this.elementCache[id];
20204 if (!oWrapper || !oWrapper.el) {
20205 oWrapper = this.elementCache[id] =
20206 new this.ElementWrapper(Roo.getDom(id));
20212 * Returns the actual DOM element
20213 * @method getElement
20214 * @param {String} id the id of the elment to get
20215 * @return {Object} The element
20216 * @deprecated use Roo.getDom instead
20219 getElement: function(id) {
20220 return Roo.getDom(id);
20224 * Returns the style property for the DOM element (i.e.,
20225 * document.getElById(id).style)
20227 * @param {String} id the id of the elment to get
20228 * @return {Object} The style property of the element
20229 * @deprecated use Roo.getDom instead
20232 getCss: function(id) {
20233 var el = Roo.getDom(id);
20234 return (el) ? el.style : null;
20238 * Inner class for cached elements
20239 * @class DragDropMgr.ElementWrapper
20244 ElementWrapper: function(el) {
20249 this.el = el || null;
20254 this.id = this.el && el.id;
20256 * A reference to the style property
20259 this.css = this.el && el.style;
20263 * Returns the X position of an html element
20265 * @param el the element for which to get the position
20266 * @return {int} the X coordinate
20268 * @deprecated use Roo.lib.Dom.getX instead
20271 getPosX: function(el) {
20272 return Roo.lib.Dom.getX(el);
20276 * Returns the Y position of an html element
20278 * @param el the element for which to get the position
20279 * @return {int} the Y coordinate
20280 * @deprecated use Roo.lib.Dom.getY instead
20283 getPosY: function(el) {
20284 return Roo.lib.Dom.getY(el);
20288 * Swap two nodes. In IE, we use the native method, for others we
20289 * emulate the IE behavior
20291 * @param n1 the first node to swap
20292 * @param n2 the other node to swap
20295 swapNode: function(n1, n2) {
20299 var p = n2.parentNode;
20300 var s = n2.nextSibling;
20303 p.insertBefore(n1, n2);
20304 } else if (n2 == n1.nextSibling) {
20305 p.insertBefore(n2, n1);
20307 n1.parentNode.replaceChild(n2, n1);
20308 p.insertBefore(n1, s);
20314 * Returns the current scroll position
20315 * @method getScroll
20319 getScroll: function () {
20320 var t, l, dde=document.documentElement, db=document.body;
20321 if (dde && (dde.scrollTop || dde.scrollLeft)) {
20323 l = dde.scrollLeft;
20330 return { top: t, left: l };
20334 * Returns the specified element style property
20336 * @param {HTMLElement} el the element
20337 * @param {string} styleProp the style property
20338 * @return {string} The value of the style property
20339 * @deprecated use Roo.lib.Dom.getStyle
20342 getStyle: function(el, styleProp) {
20343 return Roo.fly(el).getStyle(styleProp);
20347 * Gets the scrollTop
20348 * @method getScrollTop
20349 * @return {int} the document's scrollTop
20352 getScrollTop: function () { return this.getScroll().top; },
20355 * Gets the scrollLeft
20356 * @method getScrollLeft
20357 * @return {int} the document's scrollTop
20360 getScrollLeft: function () { return this.getScroll().left; },
20363 * Sets the x/y position of an element to the location of the
20366 * @param {HTMLElement} moveEl The element to move
20367 * @param {HTMLElement} targetEl The position reference element
20370 moveToEl: function (moveEl, targetEl) {
20371 var aCoord = Roo.lib.Dom.getXY(targetEl);
20372 Roo.lib.Dom.setXY(moveEl, aCoord);
20376 * Numeric array sort function
20377 * @method numericSort
20380 numericSort: function(a, b) { return (a - b); },
20384 * @property _timeoutCount
20391 * Trying to make the load order less important. Without this we get
20392 * an error if this file is loaded before the Event Utility.
20393 * @method _addListeners
20397 _addListeners: function() {
20398 var DDM = Roo.dd.DDM;
20399 if ( Roo.lib.Event && document ) {
20402 if (DDM._timeoutCount > 2000) {
20404 setTimeout(DDM._addListeners, 10);
20405 if (document && document.body) {
20406 DDM._timeoutCount += 1;
20413 * Recursively searches the immediate parent and all child nodes for
20414 * the handle element in order to determine wheter or not it was
20416 * @method handleWasClicked
20417 * @param node the html element to inspect
20420 handleWasClicked: function(node, id) {
20421 if (this.isHandle(id, node.id)) {
20424 // check to see if this is a text node child of the one we want
20425 var p = node.parentNode;
20428 if (this.isHandle(id, p.id)) {
20443 // shorter alias, save a few bytes
20444 Roo.dd.DDM = Roo.dd.DragDropMgr;
20445 Roo.dd.DDM._addListeners();
20449 * Ext JS Library 1.1.1
20450 * Copyright(c) 2006-2007, Ext JS, LLC.
20452 * Originally Released Under LGPL - original licence link has changed is not relivant.
20455 * <script type="text/javascript">
20460 * A DragDrop implementation where the linked element follows the
20461 * mouse cursor during a drag.
20462 * @extends Roo.dd.DragDrop
20464 * @param {String} id the id of the linked element
20465 * @param {String} sGroup the group of related DragDrop items
20466 * @param {object} config an object containing configurable attributes
20467 * Valid properties for DD:
20470 Roo.dd.DD = function(id, sGroup, config) {
20472 this.init(id, sGroup, config);
20476 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
20479 * When set to true, the utility automatically tries to scroll the browser
20480 * window wehn a drag and drop element is dragged near the viewport boundary.
20481 * Defaults to true.
20488 * Sets the pointer offset to the distance between the linked element's top
20489 * left corner and the location the element was clicked
20490 * @method autoOffset
20491 * @param {int} iPageX the X coordinate of the click
20492 * @param {int} iPageY the Y coordinate of the click
20494 autoOffset: function(iPageX, iPageY) {
20495 var x = iPageX - this.startPageX;
20496 var y = iPageY - this.startPageY;
20497 this.setDelta(x, y);
20501 * Sets the pointer offset. You can call this directly to force the
20502 * offset to be in a particular location (e.g., pass in 0,0 to set it
20503 * to the center of the object)
20505 * @param {int} iDeltaX the distance from the left
20506 * @param {int} iDeltaY the distance from the top
20508 setDelta: function(iDeltaX, iDeltaY) {
20509 this.deltaX = iDeltaX;
20510 this.deltaY = iDeltaY;
20514 * Sets the drag element to the location of the mousedown or click event,
20515 * maintaining the cursor location relative to the location on the element
20516 * that was clicked. Override this if you want to place the element in a
20517 * location other than where the cursor is.
20518 * @method setDragElPos
20519 * @param {int} iPageX the X coordinate of the mousedown or drag event
20520 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20522 setDragElPos: function(iPageX, iPageY) {
20523 // the first time we do this, we are going to check to make sure
20524 // the element has css positioning
20526 var el = this.getDragEl();
20527 this.alignElWithMouse(el, iPageX, iPageY);
20531 * Sets the element to the location of the mousedown or click event,
20532 * maintaining the cursor location relative to the location on the element
20533 * that was clicked. Override this if you want to place the element in a
20534 * location other than where the cursor is.
20535 * @method alignElWithMouse
20536 * @param {HTMLElement} el the element to move
20537 * @param {int} iPageX the X coordinate of the mousedown or drag event
20538 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20540 alignElWithMouse: function(el, iPageX, iPageY) {
20541 var oCoord = this.getTargetCoord(iPageX, iPageY);
20542 var fly = el.dom ? el : Roo.fly(el);
20543 if (!this.deltaSetXY) {
20544 var aCoord = [oCoord.x, oCoord.y];
20546 var newLeft = fly.getLeft(true);
20547 var newTop = fly.getTop(true);
20548 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
20550 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
20553 this.cachePosition(oCoord.x, oCoord.y);
20554 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
20559 * Saves the most recent position so that we can reset the constraints and
20560 * tick marks on-demand. We need to know this so that we can calculate the
20561 * number of pixels the element is offset from its original position.
20562 * @method cachePosition
20563 * @param iPageX the current x position (optional, this just makes it so we
20564 * don't have to look it up again)
20565 * @param iPageY the current y position (optional, this just makes it so we
20566 * don't have to look it up again)
20568 cachePosition: function(iPageX, iPageY) {
20570 this.lastPageX = iPageX;
20571 this.lastPageY = iPageY;
20573 var aCoord = Roo.lib.Dom.getXY(this.getEl());
20574 this.lastPageX = aCoord[0];
20575 this.lastPageY = aCoord[1];
20580 * Auto-scroll the window if the dragged object has been moved beyond the
20581 * visible window boundary.
20582 * @method autoScroll
20583 * @param {int} x the drag element's x position
20584 * @param {int} y the drag element's y position
20585 * @param {int} h the height of the drag element
20586 * @param {int} w the width of the drag element
20589 autoScroll: function(x, y, h, w) {
20592 // The client height
20593 var clientH = Roo.lib.Dom.getViewWidth();
20595 // The client width
20596 var clientW = Roo.lib.Dom.getViewHeight();
20598 // The amt scrolled down
20599 var st = this.DDM.getScrollTop();
20601 // The amt scrolled right
20602 var sl = this.DDM.getScrollLeft();
20604 // Location of the bottom of the element
20607 // Location of the right of the element
20610 // The distance from the cursor to the bottom of the visible area,
20611 // adjusted so that we don't scroll if the cursor is beyond the
20612 // element drag constraints
20613 var toBot = (clientH + st - y - this.deltaY);
20615 // The distance from the cursor to the right of the visible area
20616 var toRight = (clientW + sl - x - this.deltaX);
20619 // How close to the edge the cursor must be before we scroll
20620 // var thresh = (document.all) ? 100 : 40;
20623 // How many pixels to scroll per autoscroll op. This helps to reduce
20624 // clunky scrolling. IE is more sensitive about this ... it needs this
20625 // value to be higher.
20626 var scrAmt = (document.all) ? 80 : 30;
20628 // Scroll down if we are near the bottom of the visible page and the
20629 // obj extends below the crease
20630 if ( bot > clientH && toBot < thresh ) {
20631 window.scrollTo(sl, st + scrAmt);
20634 // Scroll up if the window is scrolled down and the top of the object
20635 // goes above the top border
20636 if ( y < st && st > 0 && y - st < thresh ) {
20637 window.scrollTo(sl, st - scrAmt);
20640 // Scroll right if the obj is beyond the right border and the cursor is
20641 // near the border.
20642 if ( right > clientW && toRight < thresh ) {
20643 window.scrollTo(sl + scrAmt, st);
20646 // Scroll left if the window has been scrolled to the right and the obj
20647 // extends past the left border
20648 if ( x < sl && sl > 0 && x - sl < thresh ) {
20649 window.scrollTo(sl - scrAmt, st);
20655 * Finds the location the element should be placed if we want to move
20656 * it to where the mouse location less the click offset would place us.
20657 * @method getTargetCoord
20658 * @param {int} iPageX the X coordinate of the click
20659 * @param {int} iPageY the Y coordinate of the click
20660 * @return an object that contains the coordinates (Object.x and Object.y)
20663 getTargetCoord: function(iPageX, iPageY) {
20666 var x = iPageX - this.deltaX;
20667 var y = iPageY - this.deltaY;
20669 if (this.constrainX) {
20670 if (x < this.minX) { x = this.minX; }
20671 if (x > this.maxX) { x = this.maxX; }
20674 if (this.constrainY) {
20675 if (y < this.minY) { y = this.minY; }
20676 if (y > this.maxY) { y = this.maxY; }
20679 x = this.getTick(x, this.xTicks);
20680 y = this.getTick(y, this.yTicks);
20687 * Sets up config options specific to this class. Overrides
20688 * Roo.dd.DragDrop, but all versions of this method through the
20689 * inheritance chain are called
20691 applyConfig: function() {
20692 Roo.dd.DD.superclass.applyConfig.call(this);
20693 this.scroll = (this.config.scroll !== false);
20697 * Event that fires prior to the onMouseDown event. Overrides
20700 b4MouseDown: function(e) {
20701 // this.resetConstraints();
20702 this.autoOffset(e.getPageX(),
20707 * Event that fires prior to the onDrag event. Overrides
20710 b4Drag: function(e) {
20711 this.setDragElPos(e.getPageX(),
20715 toString: function() {
20716 return ("DD " + this.id);
20719 //////////////////////////////////////////////////////////////////////////
20720 // Debugging ygDragDrop events that can be overridden
20721 //////////////////////////////////////////////////////////////////////////
20723 startDrag: function(x, y) {
20726 onDrag: function(e) {
20729 onDragEnter: function(e, id) {
20732 onDragOver: function(e, id) {
20735 onDragOut: function(e, id) {
20738 onDragDrop: function(e, id) {
20741 endDrag: function(e) {
20748 * Ext JS Library 1.1.1
20749 * Copyright(c) 2006-2007, Ext JS, LLC.
20751 * Originally Released Under LGPL - original licence link has changed is not relivant.
20754 * <script type="text/javascript">
20758 * @class Roo.dd.DDProxy
20759 * A DragDrop implementation that inserts an empty, bordered div into
20760 * the document that follows the cursor during drag operations. At the time of
20761 * the click, the frame div is resized to the dimensions of the linked html
20762 * element, and moved to the exact location of the linked element.
20764 * References to the "frame" element refer to the single proxy element that
20765 * was created to be dragged in place of all DDProxy elements on the
20768 * @extends Roo.dd.DD
20770 * @param {String} id the id of the linked html element
20771 * @param {String} sGroup the group of related DragDrop objects
20772 * @param {object} config an object containing configurable attributes
20773 * Valid properties for DDProxy in addition to those in DragDrop:
20774 * resizeFrame, centerFrame, dragElId
20776 Roo.dd.DDProxy = function(id, sGroup, config) {
20778 this.init(id, sGroup, config);
20784 * The default drag frame div id
20785 * @property Roo.dd.DDProxy.dragElId
20789 Roo.dd.DDProxy.dragElId = "ygddfdiv";
20791 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
20794 * By default we resize the drag frame to be the same size as the element
20795 * we want to drag (this is to get the frame effect). We can turn it off
20796 * if we want a different behavior.
20797 * @property resizeFrame
20803 * By default the frame is positioned exactly where the drag element is, so
20804 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
20805 * you do not have constraints on the obj is to have the drag frame centered
20806 * around the cursor. Set centerFrame to true for this effect.
20807 * @property centerFrame
20810 centerFrame: false,
20813 * Creates the proxy element if it does not yet exist
20814 * @method createFrame
20816 createFrame: function() {
20818 var body = document.body;
20820 if (!body || !body.firstChild) {
20821 setTimeout( function() { self.createFrame(); }, 50 );
20825 var div = this.getDragEl();
20828 div = document.createElement("div");
20829 div.id = this.dragElId;
20832 s.position = "absolute";
20833 s.visibility = "hidden";
20835 s.border = "2px solid #aaa";
20838 // appendChild can blow up IE if invoked prior to the window load event
20839 // while rendering a table. It is possible there are other scenarios
20840 // that would cause this to happen as well.
20841 body.insertBefore(div, body.firstChild);
20846 * Initialization for the drag frame element. Must be called in the
20847 * constructor of all subclasses
20848 * @method initFrame
20850 initFrame: function() {
20851 this.createFrame();
20854 applyConfig: function() {
20855 Roo.dd.DDProxy.superclass.applyConfig.call(this);
20857 this.resizeFrame = (this.config.resizeFrame !== false);
20858 this.centerFrame = (this.config.centerFrame);
20859 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
20863 * Resizes the drag frame to the dimensions of the clicked object, positions
20864 * it over the object, and finally displays it
20865 * @method showFrame
20866 * @param {int} iPageX X click position
20867 * @param {int} iPageY Y click position
20870 showFrame: function(iPageX, iPageY) {
20871 var el = this.getEl();
20872 var dragEl = this.getDragEl();
20873 var s = dragEl.style;
20875 this._resizeProxy();
20877 if (this.centerFrame) {
20878 this.setDelta( Math.round(parseInt(s.width, 10)/2),
20879 Math.round(parseInt(s.height, 10)/2) );
20882 this.setDragElPos(iPageX, iPageY);
20884 Roo.fly(dragEl).show();
20888 * The proxy is automatically resized to the dimensions of the linked
20889 * element when a drag is initiated, unless resizeFrame is set to false
20890 * @method _resizeProxy
20893 _resizeProxy: function() {
20894 if (this.resizeFrame) {
20895 var el = this.getEl();
20896 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
20900 // overrides Roo.dd.DragDrop
20901 b4MouseDown: function(e) {
20902 var x = e.getPageX();
20903 var y = e.getPageY();
20904 this.autoOffset(x, y);
20905 this.setDragElPos(x, y);
20908 // overrides Roo.dd.DragDrop
20909 b4StartDrag: function(x, y) {
20910 // show the drag frame
20911 this.showFrame(x, y);
20914 // overrides Roo.dd.DragDrop
20915 b4EndDrag: function(e) {
20916 Roo.fly(this.getDragEl()).hide();
20919 // overrides Roo.dd.DragDrop
20920 // By default we try to move the element to the last location of the frame.
20921 // This is so that the default behavior mirrors that of Roo.dd.DD.
20922 endDrag: function(e) {
20924 var lel = this.getEl();
20925 var del = this.getDragEl();
20927 // Show the drag frame briefly so we can get its position
20928 del.style.visibility = "";
20931 // Hide the linked element before the move to get around a Safari
20933 lel.style.visibility = "hidden";
20934 Roo.dd.DDM.moveToEl(lel, del);
20935 del.style.visibility = "hidden";
20936 lel.style.visibility = "";
20941 beforeMove : function(){
20945 afterDrag : function(){
20949 toString: function() {
20950 return ("DDProxy " + this.id);
20956 * Ext JS Library 1.1.1
20957 * Copyright(c) 2006-2007, Ext JS, LLC.
20959 * Originally Released Under LGPL - original licence link has changed is not relivant.
20962 * <script type="text/javascript">
20966 * @class Roo.dd.DDTarget
20967 * A DragDrop implementation that does not move, but can be a drop
20968 * target. You would get the same result by simply omitting implementation
20969 * for the event callbacks, but this way we reduce the processing cost of the
20970 * event listener and the callbacks.
20971 * @extends Roo.dd.DragDrop
20973 * @param {String} id the id of the element that is a drop target
20974 * @param {String} sGroup the group of related DragDrop objects
20975 * @param {object} config an object containing configurable attributes
20976 * Valid properties for DDTarget in addition to those in
20980 Roo.dd.DDTarget = function(id, sGroup, config) {
20982 this.initTarget(id, sGroup, config);
20984 if (config.listeners || config.events) {
20985 Roo.dd.DragDrop.superclass.constructor.call(this, {
20986 listeners : config.listeners || {},
20987 events : config.events || {}
20992 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
20993 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
20994 toString: function() {
20995 return ("DDTarget " + this.id);
21000 * Ext JS Library 1.1.1
21001 * Copyright(c) 2006-2007, Ext JS, LLC.
21003 * Originally Released Under LGPL - original licence link has changed is not relivant.
21006 * <script type="text/javascript">
21011 * @class Roo.dd.ScrollManager
21012 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
21013 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
21016 Roo.dd.ScrollManager = function(){
21017 var ddm = Roo.dd.DragDropMgr;
21024 var onStop = function(e){
21029 var triggerRefresh = function(){
21030 if(ddm.dragCurrent){
21031 ddm.refreshCache(ddm.dragCurrent.groups);
21035 var doScroll = function(){
21036 if(ddm.dragCurrent){
21037 var dds = Roo.dd.ScrollManager;
21039 if(proc.el.scroll(proc.dir, dds.increment)){
21043 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
21048 var clearProc = function(){
21050 clearInterval(proc.id);
21057 var startProc = function(el, dir){
21058 Roo.log('scroll startproc');
21062 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
21065 var onFire = function(e, isDrop){
21067 if(isDrop || !ddm.dragCurrent){ return; }
21068 var dds = Roo.dd.ScrollManager;
21069 if(!dragEl || dragEl != ddm.dragCurrent){
21070 dragEl = ddm.dragCurrent;
21071 // refresh regions on drag start
21072 dds.refreshCache();
21075 var xy = Roo.lib.Event.getXY(e);
21076 var pt = new Roo.lib.Point(xy[0], xy[1]);
21077 for(var id in els){
21078 var el = els[id], r = el._region;
21079 if(r && r.contains(pt) && el.isScrollable()){
21080 if(r.bottom - pt.y <= dds.thresh){
21082 startProc(el, "down");
21085 }else if(r.right - pt.x <= dds.thresh){
21087 startProc(el, "left");
21090 }else if(pt.y - r.top <= dds.thresh){
21092 startProc(el, "up");
21095 }else if(pt.x - r.left <= dds.thresh){
21097 startProc(el, "right");
21106 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
21107 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
21111 * Registers new overflow element(s) to auto scroll
21112 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
21114 register : function(el){
21115 if(el instanceof Array){
21116 for(var i = 0, len = el.length; i < len; i++) {
21117 this.register(el[i]);
21123 Roo.dd.ScrollManager.els = els;
21127 * Unregisters overflow element(s) so they are no longer scrolled
21128 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
21130 unregister : function(el){
21131 if(el instanceof Array){
21132 for(var i = 0, len = el.length; i < len; i++) {
21133 this.unregister(el[i]);
21142 * The number of pixels from the edge of a container the pointer needs to be to
21143 * trigger scrolling (defaults to 25)
21149 * The number of pixels to scroll in each scroll increment (defaults to 50)
21155 * The frequency of scrolls in milliseconds (defaults to 500)
21161 * True to animate the scroll (defaults to true)
21167 * The animation duration in seconds -
21168 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
21174 * Manually trigger a cache refresh.
21176 refreshCache : function(){
21177 for(var id in els){
21178 if(typeof els[id] == 'object'){ // for people extending the object prototype
21179 els[id]._region = els[id].getRegion();
21186 * Ext JS Library 1.1.1
21187 * Copyright(c) 2006-2007, Ext JS, LLC.
21189 * Originally Released Under LGPL - original licence link has changed is not relivant.
21192 * <script type="text/javascript">
21197 * @class Roo.dd.Registry
21198 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
21199 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
21202 Roo.dd.Registry = function(){
21205 var autoIdSeed = 0;
21207 var getId = function(el, autogen){
21208 if(typeof el == "string"){
21212 if(!id && autogen !== false){
21213 id = "roodd-" + (++autoIdSeed);
21221 * Register a drag drop element
21222 * @param {String|HTMLElement} element The id or DOM node to register
21223 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
21224 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
21225 * knows how to interpret, plus there are some specific properties known to the Registry that should be
21226 * populated in the data object (if applicable):
21228 Value Description<br />
21229 --------- ------------------------------------------<br />
21230 handles Array of DOM nodes that trigger dragging<br />
21231 for the element being registered<br />
21232 isHandle True if the element passed in triggers<br />
21233 dragging itself, else false
21236 register : function(el, data){
21238 if(typeof el == "string"){
21239 el = document.getElementById(el);
21242 elements[getId(el)] = data;
21243 if(data.isHandle !== false){
21244 handles[data.ddel.id] = data;
21247 var hs = data.handles;
21248 for(var i = 0, len = hs.length; i < len; i++){
21249 handles[getId(hs[i])] = data;
21255 * Unregister a drag drop element
21256 * @param {String|HTMLElement} element The id or DOM node to unregister
21258 unregister : function(el){
21259 var id = getId(el, false);
21260 var data = elements[id];
21262 delete elements[id];
21264 var hs = data.handles;
21265 for(var i = 0, len = hs.length; i < len; i++){
21266 delete handles[getId(hs[i], false)];
21273 * Returns the handle registered for a DOM Node by id
21274 * @param {String|HTMLElement} id The DOM node or id to look up
21275 * @return {Object} handle The custom handle data
21277 getHandle : function(id){
21278 if(typeof id != "string"){ // must be element?
21281 return handles[id];
21285 * Returns the handle that is registered for the DOM node that is the target of the event
21286 * @param {Event} e The event
21287 * @return {Object} handle The custom handle data
21289 getHandleFromEvent : function(e){
21290 var t = Roo.lib.Event.getTarget(e);
21291 return t ? handles[t.id] : null;
21295 * Returns a custom data object that is registered for a DOM node by id
21296 * @param {String|HTMLElement} id The DOM node or id to look up
21297 * @return {Object} data The custom data
21299 getTarget : function(id){
21300 if(typeof id != "string"){ // must be element?
21303 return elements[id];
21307 * Returns a custom data object that is registered for the DOM node that is the target of the event
21308 * @param {Event} e The event
21309 * @return {Object} data The custom data
21311 getTargetFromEvent : function(e){
21312 var t = Roo.lib.Event.getTarget(e);
21313 return t ? elements[t.id] || handles[t.id] : null;
21318 * Ext JS Library 1.1.1
21319 * Copyright(c) 2006-2007, Ext JS, LLC.
21321 * Originally Released Under LGPL - original licence link has changed is not relivant.
21324 * <script type="text/javascript">
21329 * @class Roo.dd.StatusProxy
21330 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
21331 * default drag proxy used by all Roo.dd components.
21333 * @param {Object} config
21335 Roo.dd.StatusProxy = function(config){
21336 Roo.apply(this, config);
21337 this.id = this.id || Roo.id();
21338 this.el = new Roo.Layer({
21340 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
21341 {tag: "div", cls: "x-dd-drop-icon"},
21342 {tag: "div", cls: "x-dd-drag-ghost"}
21345 shadow: !config || config.shadow !== false
21347 this.ghost = Roo.get(this.el.dom.childNodes[1]);
21348 this.dropStatus = this.dropNotAllowed;
21351 Roo.dd.StatusProxy.prototype = {
21353 * @cfg {String} dropAllowed
21354 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
21356 dropAllowed : "x-dd-drop-ok",
21358 * @cfg {String} dropNotAllowed
21359 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
21361 dropNotAllowed : "x-dd-drop-nodrop",
21364 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
21365 * over the current target element.
21366 * @param {String} cssClass The css class for the new drop status indicator image
21368 setStatus : function(cssClass){
21369 cssClass = cssClass || this.dropNotAllowed;
21370 if(this.dropStatus != cssClass){
21371 this.el.replaceClass(this.dropStatus, cssClass);
21372 this.dropStatus = cssClass;
21377 * Resets the status indicator to the default dropNotAllowed value
21378 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
21380 reset : function(clearGhost){
21381 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
21382 this.dropStatus = this.dropNotAllowed;
21384 this.ghost.update("");
21389 * Updates the contents of the ghost element
21390 * @param {String} html The html that will replace the current innerHTML of the ghost element
21392 update : function(html){
21393 if(typeof html == "string"){
21394 this.ghost.update(html);
21396 this.ghost.update("");
21397 html.style.margin = "0";
21398 this.ghost.dom.appendChild(html);
21400 // ensure float = none set?? cant remember why though.
21401 var el = this.ghost.dom.firstChild;
21403 Roo.fly(el).setStyle('float', 'none');
21408 * Returns the underlying proxy {@link Roo.Layer}
21409 * @return {Roo.Layer} el
21411 getEl : function(){
21416 * Returns the ghost element
21417 * @return {Roo.Element} el
21419 getGhost : function(){
21425 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
21427 hide : function(clear){
21435 * Stops the repair animation if it's currently running
21438 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
21444 * Displays this proxy
21451 * Force the Layer to sync its shadow and shim positions to the element
21458 * Causes the proxy to return to its position of origin via an animation. Should be called after an
21459 * invalid drop operation by the item being dragged.
21460 * @param {Array} xy The XY position of the element ([x, y])
21461 * @param {Function} callback The function to call after the repair is complete
21462 * @param {Object} scope The scope in which to execute the callback
21464 repair : function(xy, callback, scope){
21465 this.callback = callback;
21466 this.scope = scope;
21467 if(xy && this.animRepair !== false){
21468 this.el.addClass("x-dd-drag-repair");
21469 this.el.hideUnders(true);
21470 this.anim = this.el.shift({
21471 duration: this.repairDuration || .5,
21475 callback: this.afterRepair,
21479 this.afterRepair();
21484 afterRepair : function(){
21486 if(typeof this.callback == "function"){
21487 this.callback.call(this.scope || this);
21489 this.callback = null;
21494 * Ext JS Library 1.1.1
21495 * Copyright(c) 2006-2007, Ext JS, LLC.
21497 * Originally Released Under LGPL - original licence link has changed is not relivant.
21500 * <script type="text/javascript">
21504 * @class Roo.dd.DragSource
21505 * @extends Roo.dd.DDProxy
21506 * A simple class that provides the basic implementation needed to make any element draggable.
21508 * @param {String/HTMLElement/Element} el The container element
21509 * @param {Object} config
21511 Roo.dd.DragSource = function(el, config){
21512 this.el = Roo.get(el);
21513 this.dragData = {};
21515 Roo.apply(this, config);
21518 this.proxy = new Roo.dd.StatusProxy();
21521 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
21522 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
21524 this.dragging = false;
21527 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
21529 * @cfg {String} dropAllowed
21530 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21532 dropAllowed : "x-dd-drop-ok",
21534 * @cfg {String} dropNotAllowed
21535 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21537 dropNotAllowed : "x-dd-drop-nodrop",
21540 * Returns the data object associated with this drag source
21541 * @return {Object} data An object containing arbitrary data
21543 getDragData : function(e){
21544 return this.dragData;
21548 onDragEnter : function(e, id){
21549 var target = Roo.dd.DragDropMgr.getDDById(id);
21550 this.cachedTarget = target;
21551 if(this.beforeDragEnter(target, e, id) !== false){
21552 if(target.isNotifyTarget){
21553 var status = target.notifyEnter(this, e, this.dragData);
21554 this.proxy.setStatus(status);
21556 this.proxy.setStatus(this.dropAllowed);
21559 if(this.afterDragEnter){
21561 * An empty function by default, but provided so that you can perform a custom action
21562 * when the dragged item enters the drop target by providing an implementation.
21563 * @param {Roo.dd.DragDrop} target The drop target
21564 * @param {Event} e The event object
21565 * @param {String} id The id of the dragged element
21566 * @method afterDragEnter
21568 this.afterDragEnter(target, e, id);
21574 * An empty function by default, but provided so that you can perform a custom action
21575 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
21576 * @param {Roo.dd.DragDrop} target The drop target
21577 * @param {Event} e The event object
21578 * @param {String} id The id of the dragged element
21579 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21581 beforeDragEnter : function(target, e, id){
21586 alignElWithMouse: function() {
21587 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
21592 onDragOver : function(e, id){
21593 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21594 if(this.beforeDragOver(target, e, id) !== false){
21595 if(target.isNotifyTarget){
21596 var status = target.notifyOver(this, e, this.dragData);
21597 this.proxy.setStatus(status);
21600 if(this.afterDragOver){
21602 * An empty function by default, but provided so that you can perform a custom action
21603 * while the dragged item is over the drop target by providing an implementation.
21604 * @param {Roo.dd.DragDrop} target The drop target
21605 * @param {Event} e The event object
21606 * @param {String} id The id of the dragged element
21607 * @method afterDragOver
21609 this.afterDragOver(target, e, id);
21615 * An empty function by default, but provided so that you can perform a custom action
21616 * while the dragged item is over the drop target and optionally cancel the onDragOver.
21617 * @param {Roo.dd.DragDrop} target The drop target
21618 * @param {Event} e The event object
21619 * @param {String} id The id of the dragged element
21620 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21622 beforeDragOver : function(target, e, id){
21627 onDragOut : function(e, id){
21628 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21629 if(this.beforeDragOut(target, e, id) !== false){
21630 if(target.isNotifyTarget){
21631 target.notifyOut(this, e, this.dragData);
21633 this.proxy.reset();
21634 if(this.afterDragOut){
21636 * An empty function by default, but provided so that you can perform a custom action
21637 * after the dragged item is dragged out of the target without dropping.
21638 * @param {Roo.dd.DragDrop} target The drop target
21639 * @param {Event} e The event object
21640 * @param {String} id The id of the dragged element
21641 * @method afterDragOut
21643 this.afterDragOut(target, e, id);
21646 this.cachedTarget = null;
21650 * An empty function by default, but provided so that you can perform a custom action before the dragged
21651 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
21652 * @param {Roo.dd.DragDrop} target The drop target
21653 * @param {Event} e The event object
21654 * @param {String} id The id of the dragged element
21655 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21657 beforeDragOut : function(target, e, id){
21662 onDragDrop : function(e, id){
21663 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21664 if(this.beforeDragDrop(target, e, id) !== false){
21665 if(target.isNotifyTarget){
21666 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
21667 this.onValidDrop(target, e, id);
21669 this.onInvalidDrop(target, e, id);
21672 this.onValidDrop(target, e, id);
21675 if(this.afterDragDrop){
21677 * An empty function by default, but provided so that you can perform a custom action
21678 * after a valid drag drop has occurred by providing an implementation.
21679 * @param {Roo.dd.DragDrop} target The drop target
21680 * @param {Event} e The event object
21681 * @param {String} id The id of the dropped element
21682 * @method afterDragDrop
21684 this.afterDragDrop(target, e, id);
21687 delete this.cachedTarget;
21691 * An empty function by default, but provided so that you can perform a custom action before the dragged
21692 * item is dropped onto the target and optionally cancel the onDragDrop.
21693 * @param {Roo.dd.DragDrop} target The drop target
21694 * @param {Event} e The event object
21695 * @param {String} id The id of the dragged element
21696 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
21698 beforeDragDrop : function(target, e, id){
21703 onValidDrop : function(target, e, id){
21705 if(this.afterValidDrop){
21707 * An empty function by default, but provided so that you can perform a custom action
21708 * after a valid drop has occurred by providing an implementation.
21709 * @param {Object} target The target DD
21710 * @param {Event} e The event object
21711 * @param {String} id The id of the dropped element
21712 * @method afterInvalidDrop
21714 this.afterValidDrop(target, e, id);
21719 getRepairXY : function(e, data){
21720 return this.el.getXY();
21724 onInvalidDrop : function(target, e, id){
21725 this.beforeInvalidDrop(target, e, id);
21726 if(this.cachedTarget){
21727 if(this.cachedTarget.isNotifyTarget){
21728 this.cachedTarget.notifyOut(this, e, this.dragData);
21730 this.cacheTarget = null;
21732 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
21734 if(this.afterInvalidDrop){
21736 * An empty function by default, but provided so that you can perform a custom action
21737 * after an invalid drop has occurred by providing an implementation.
21738 * @param {Event} e The event object
21739 * @param {String} id The id of the dropped element
21740 * @method afterInvalidDrop
21742 this.afterInvalidDrop(e, id);
21747 afterRepair : function(){
21749 this.el.highlight(this.hlColor || "c3daf9");
21751 this.dragging = false;
21755 * An empty function by default, but provided so that you can perform a custom action after an invalid
21756 * drop has occurred.
21757 * @param {Roo.dd.DragDrop} target The drop target
21758 * @param {Event} e The event object
21759 * @param {String} id The id of the dragged element
21760 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
21762 beforeInvalidDrop : function(target, e, id){
21767 handleMouseDown : function(e){
21768 if(this.dragging) {
21771 var data = this.getDragData(e);
21772 if(data && this.onBeforeDrag(data, e) !== false){
21773 this.dragData = data;
21775 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
21780 * An empty function by default, but provided so that you can perform a custom action before the initial
21781 * drag event begins and optionally cancel it.
21782 * @param {Object} data An object containing arbitrary data to be shared with drop targets
21783 * @param {Event} e The event object
21784 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21786 onBeforeDrag : function(data, e){
21791 * An empty function by default, but provided so that you can perform a custom action once the initial
21792 * drag event has begun. The drag cannot be canceled from this function.
21793 * @param {Number} x The x position of the click on the dragged object
21794 * @param {Number} y The y position of the click on the dragged object
21796 onStartDrag : Roo.emptyFn,
21798 // private - YUI override
21799 startDrag : function(x, y){
21800 this.proxy.reset();
21801 this.dragging = true;
21802 this.proxy.update("");
21803 this.onInitDrag(x, y);
21808 onInitDrag : function(x, y){
21809 var clone = this.el.dom.cloneNode(true);
21810 clone.id = Roo.id(); // prevent duplicate ids
21811 this.proxy.update(clone);
21812 this.onStartDrag(x, y);
21817 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
21818 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
21820 getProxy : function(){
21825 * Hides the drag source's {@link Roo.dd.StatusProxy}
21827 hideProxy : function(){
21829 this.proxy.reset(true);
21830 this.dragging = false;
21834 triggerCacheRefresh : function(){
21835 Roo.dd.DDM.refreshCache(this.groups);
21838 // private - override to prevent hiding
21839 b4EndDrag: function(e) {
21842 // private - override to prevent moving
21843 endDrag : function(e){
21844 this.onEndDrag(this.dragData, e);
21848 onEndDrag : function(data, e){
21851 // private - pin to cursor
21852 autoOffset : function(x, y) {
21853 this.setDelta(-12, -20);
21857 * Ext JS Library 1.1.1
21858 * Copyright(c) 2006-2007, Ext JS, LLC.
21860 * Originally Released Under LGPL - original licence link has changed is not relivant.
21863 * <script type="text/javascript">
21868 * @class Roo.dd.DropTarget
21869 * @extends Roo.dd.DDTarget
21870 * A simple class that provides the basic implementation needed to make any element a drop target that can have
21871 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
21873 * @param {String/HTMLElement/Element} el The container element
21874 * @param {Object} config
21876 Roo.dd.DropTarget = function(el, config){
21877 this.el = Roo.get(el);
21879 var listeners = false; ;
21880 if (config && config.listeners) {
21881 listeners= config.listeners;
21882 delete config.listeners;
21884 Roo.apply(this, config);
21886 if(this.containerScroll){
21887 Roo.dd.ScrollManager.register(this.el);
21891 * @scope Roo.dd.DropTarget
21896 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
21897 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
21898 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
21900 * IMPORTANT : it should set this.overClass and this.dropAllowed
21902 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21903 * @param {Event} e The event
21904 * @param {Object} data An object containing arbitrary data supplied by the drag source
21910 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
21911 * This method will be called on every mouse movement while the drag source is over the drop target.
21912 * This default implementation simply returns the dropAllowed config value.
21914 * IMPORTANT : it should set this.dropAllowed
21916 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21917 * @param {Event} e The event
21918 * @param {Object} data An object containing arbitrary data supplied by the drag source
21924 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
21925 * out of the target without dropping. This default implementation simply removes the CSS class specified by
21926 * overClass (if any) from the drop element.
21928 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21929 * @param {Event} e The event
21930 * @param {Object} data An object containing arbitrary data supplied by the drag source
21936 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
21937 * been dropped on it. This method has no default implementation and returns false, so you must provide an
21938 * implementation that does something to process the drop event and returns true so that the drag source's
21939 * repair action does not run.
21941 * IMPORTANT : it should set this.success
21943 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21944 * @param {Event} e The event
21945 * @param {Object} data An object containing arbitrary data supplied by the drag source
21951 Roo.dd.DropTarget.superclass.constructor.call( this,
21953 this.ddGroup || this.group,
21956 listeners : listeners || {}
21964 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
21966 * @cfg {String} overClass
21967 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
21970 * @cfg {String} ddGroup
21971 * The drag drop group to handle drop events for
21975 * @cfg {String} dropAllowed
21976 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21978 dropAllowed : "x-dd-drop-ok",
21980 * @cfg {String} dropNotAllowed
21981 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21983 dropNotAllowed : "x-dd-drop-nodrop",
21985 * @cfg {boolean} success
21986 * set this after drop listener..
21990 * @cfg {boolean|String} valid true/false or string (ok-add/ok-sub/ok/nodrop)
21991 * if the drop point is valid for over/enter..
21998 isNotifyTarget : true,
22003 notifyEnter : function(dd, e, data)
22006 this.fireEvent('enter', dd, e, data);
22007 if(this.overClass){
22008 this.el.addClass(this.overClass);
22010 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
22011 this.valid ? this.dropAllowed : this.dropNotAllowed
22018 notifyOver : function(dd, e, data)
22021 this.fireEvent('over', dd, e, data);
22022 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
22023 this.valid ? this.dropAllowed : this.dropNotAllowed
22030 notifyOut : function(dd, e, data)
22032 this.fireEvent('out', dd, e, data);
22033 if(this.overClass){
22034 this.el.removeClass(this.overClass);
22041 notifyDrop : function(dd, e, data)
22043 this.success = false;
22044 this.fireEvent('drop', dd, e, data);
22045 return this.success;
22049 * Ext JS Library 1.1.1
22050 * Copyright(c) 2006-2007, Ext JS, LLC.
22052 * Originally Released Under LGPL - original licence link has changed is not relivant.
22055 * <script type="text/javascript">
22060 * @class Roo.dd.DragZone
22061 * @extends Roo.dd.DragSource
22062 * This class provides a container DD instance that proxies for multiple child node sources.<br />
22063 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
22065 * @param {String/HTMLElement/Element} el The container element
22066 * @param {Object} config
22068 Roo.dd.DragZone = function(el, config){
22069 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
22070 if(this.containerScroll){
22071 Roo.dd.ScrollManager.register(this.el);
22075 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
22077 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
22078 * for auto scrolling during drag operations.
22081 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
22082 * method after a failed drop (defaults to "c3daf9" - light blue)
22086 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
22087 * for a valid target to drag based on the mouse down. Override this method
22088 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
22089 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
22090 * @param {EventObject} e The mouse down event
22091 * @return {Object} The dragData
22093 getDragData : function(e){
22094 return Roo.dd.Registry.getHandleFromEvent(e);
22098 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
22099 * this.dragData.ddel
22100 * @param {Number} x The x position of the click on the dragged object
22101 * @param {Number} y The y position of the click on the dragged object
22102 * @return {Boolean} true to continue the drag, false to cancel
22104 onInitDrag : function(x, y){
22105 this.proxy.update(this.dragData.ddel.cloneNode(true));
22106 this.onStartDrag(x, y);
22111 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
22113 afterRepair : function(){
22115 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
22117 this.dragging = false;
22121 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
22122 * the XY of this.dragData.ddel
22123 * @param {EventObject} e The mouse up event
22124 * @return {Array} The xy location (e.g. [100, 200])
22126 getRepairXY : function(e){
22127 return Roo.Element.fly(this.dragData.ddel).getXY();
22131 * Ext JS Library 1.1.1
22132 * Copyright(c) 2006-2007, Ext JS, LLC.
22134 * Originally Released Under LGPL - original licence link has changed is not relivant.
22137 * <script type="text/javascript">
22140 * @class Roo.dd.DropZone
22141 * @extends Roo.dd.DropTarget
22142 * This class provides a container DD instance that proxies for multiple child node targets.<br />
22143 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
22145 * @param {String/HTMLElement/Element} el The container element
22146 * @param {Object} config
22148 Roo.dd.DropZone = function(el, config){
22149 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
22152 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
22154 * Returns a custom data object associated with the DOM node that is the target of the event. By default
22155 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
22156 * provide your own custom lookup.
22157 * @param {Event} e The event
22158 * @return {Object} data The custom data
22160 getTargetFromEvent : function(e){
22161 return Roo.dd.Registry.getTargetFromEvent(e);
22165 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
22166 * that it has registered. This method has no default implementation and should be overridden to provide
22167 * node-specific processing if necessary.
22168 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22169 * {@link #getTargetFromEvent} for this node)
22170 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22171 * @param {Event} e The event
22172 * @param {Object} data An object containing arbitrary data supplied by the drag source
22174 onNodeEnter : function(n, dd, e, data){
22179 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
22180 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
22181 * overridden to provide the proper feedback.
22182 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22183 * {@link #getTargetFromEvent} for this node)
22184 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22185 * @param {Event} e The event
22186 * @param {Object} data An object containing arbitrary data supplied by the drag source
22187 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22188 * underlying {@link Roo.dd.StatusProxy} can be updated
22190 onNodeOver : function(n, dd, e, data){
22191 return this.dropAllowed;
22195 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
22196 * the drop node without dropping. This method has no default implementation and should be overridden to provide
22197 * node-specific processing if necessary.
22198 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22199 * {@link #getTargetFromEvent} for this node)
22200 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22201 * @param {Event} e The event
22202 * @param {Object} data An object containing arbitrary data supplied by the drag source
22204 onNodeOut : function(n, dd, e, data){
22209 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
22210 * the drop node. The default implementation returns false, so it should be overridden to provide the
22211 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
22212 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22213 * {@link #getTargetFromEvent} for this node)
22214 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22215 * @param {Event} e The event
22216 * @param {Object} data An object containing arbitrary data supplied by the drag source
22217 * @return {Boolean} True if the drop was valid, else false
22219 onNodeDrop : function(n, dd, e, data){
22224 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
22225 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
22226 * it should be overridden to provide the proper feedback if necessary.
22227 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22228 * @param {Event} e The event
22229 * @param {Object} data An object containing arbitrary data supplied by the drag source
22230 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22231 * underlying {@link Roo.dd.StatusProxy} can be updated
22233 onContainerOver : function(dd, e, data){
22234 return this.dropNotAllowed;
22238 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
22239 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
22240 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
22241 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
22242 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22243 * @param {Event} e The event
22244 * @param {Object} data An object containing arbitrary data supplied by the drag source
22245 * @return {Boolean} True if the drop was valid, else false
22247 onContainerDrop : function(dd, e, data){
22252 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
22253 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
22254 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
22255 * you should override this method and provide a custom implementation.
22256 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22257 * @param {Event} e The event
22258 * @param {Object} data An object containing arbitrary data supplied by the drag source
22259 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22260 * underlying {@link Roo.dd.StatusProxy} can be updated
22262 notifyEnter : function(dd, e, data){
22263 return this.dropNotAllowed;
22267 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
22268 * This method will be called on every mouse movement while the drag source is over the drop zone.
22269 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
22270 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
22271 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
22272 * registered node, it will call {@link #onContainerOver}.
22273 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22274 * @param {Event} e The event
22275 * @param {Object} data An object containing arbitrary data supplied by the drag source
22276 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22277 * underlying {@link Roo.dd.StatusProxy} can be updated
22279 notifyOver : function(dd, e, data){
22280 var n = this.getTargetFromEvent(e);
22281 if(!n){ // not over valid drop target
22282 if(this.lastOverNode){
22283 this.onNodeOut(this.lastOverNode, dd, e, data);
22284 this.lastOverNode = null;
22286 return this.onContainerOver(dd, e, data);
22288 if(this.lastOverNode != n){
22289 if(this.lastOverNode){
22290 this.onNodeOut(this.lastOverNode, dd, e, data);
22292 this.onNodeEnter(n, dd, e, data);
22293 this.lastOverNode = n;
22295 return this.onNodeOver(n, dd, e, data);
22299 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
22300 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
22301 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
22302 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
22303 * @param {Event} e The event
22304 * @param {Object} data An object containing arbitrary data supplied by the drag zone
22306 notifyOut : function(dd, e, data){
22307 if(this.lastOverNode){
22308 this.onNodeOut(this.lastOverNode, dd, e, data);
22309 this.lastOverNode = null;
22314 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
22315 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
22316 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
22317 * otherwise it will call {@link #onContainerDrop}.
22318 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22319 * @param {Event} e The event
22320 * @param {Object} data An object containing arbitrary data supplied by the drag source
22321 * @return {Boolean} True if the drop was valid, else false
22323 notifyDrop : function(dd, e, data){
22324 if(this.lastOverNode){
22325 this.onNodeOut(this.lastOverNode, dd, e, data);
22326 this.lastOverNode = null;
22328 var n = this.getTargetFromEvent(e);
22330 this.onNodeDrop(n, dd, e, data) :
22331 this.onContainerDrop(dd, e, data);
22335 triggerCacheRefresh : function(){
22336 Roo.dd.DDM.refreshCache(this.groups);