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 isEdge = ua.indexOf("edge") > -1,
61 isGecko = !isSafari && ua.indexOf("gecko") > -1,
62 isBorderBox = isIE && !isStrict,
63 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
64 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
65 isLinux = (ua.indexOf("linux") != -1),
66 isSecure = window.location.href.toLowerCase().indexOf("https") === 0,
67 isIOS = /iphone|ipad/.test(ua),
68 isAndroid = /android/.test(ua),
69 isTouch = (function() {
71 if (ua.indexOf('chrome') != -1 && ua.indexOf('android') == -1) {
72 window.addEventListener('touchstart', function __set_has_touch__ () {
74 window.removeEventListener('touchstart', __set_has_touch__);
76 return false; // no touch on chrome!?
78 document.createEvent("TouchEvent");
85 // remove css image flicker
88 document.execCommand("BackgroundImageCache", false, true);
94 * True if the browser is in strict mode
99 * True if the page is running over SSL
104 * True when the document is fully initialized and ready for action
109 * Turn on debugging output (currently only the factory uses this)
116 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
119 enableGarbageCollector : true,
122 * True to automatically purge event listeners after uncaching an element (defaults to false).
123 * Note: this only happens if enableGarbageCollector is true.
126 enableListenerCollection:false,
129 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
130 * the IE insecure content warning (defaults to javascript:false).
133 SSL_SECURE_URL : "javascript:false",
136 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
137 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
140 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
142 emptyFn : function(){},
145 * Copies all the properties of config to obj if they don't already exist.
146 * @param {Object} obj The receiver of the properties
147 * @param {Object} config The source of the properties
148 * @return {Object} returns obj
150 applyIf : function(o, c){
153 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
160 * Applies event listeners to elements by selectors when the document is ready.
161 * The event name is specified with an @ suffix.
164 // add a listener for click on all anchors in element with id foo
165 '#foo a@click' : function(e, t){
169 // add the same listener to multiple selectors (separated by comma BEFORE the @)
170 '#foo a, #bar span.some-class@mouseover' : function(){
175 * @param {Object} obj The list of behaviors to apply
177 addBehaviors : function(o){
179 Roo.onReady(function(){
184 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
186 var parts = b.split('@');
187 if(parts[1]){ // for Object prototype breakers
190 cache[s] = Roo.select(s);
192 cache[s].on(parts[1], o[b]);
199 * Generates unique ids. If the element already has an id, it is unchanged
200 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
201 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
202 * @return {String} The generated Id.
204 id : function(el, prefix){
205 prefix = prefix || "roo-gen";
207 var id = prefix + (++idSeed);
208 return el ? (el.id ? el.id : (el.id = id)) : id;
213 * Extends one class with another class and optionally overrides members with the passed literal. This class
214 * also adds the function "override()" to the class that can be used to override
215 * members on an instance.
216 * @param {Object} subclass The class inheriting the functionality
217 * @param {Object} superclass The class being extended
218 * @param {Object} overrides (optional) A literal with members
223 var io = function(o){
228 return function(sb, sp, overrides){
229 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
232 sb = function(){sp.apply(this, arguments);};
234 var F = function(){}, sbp, spp = sp.prototype;
236 sbp = sb.prototype = new F();
240 if(spp.constructor == Object.prototype.constructor){
245 sb.override = function(o){
249 Roo.override(sb, overrides);
255 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
257 Roo.override(MyClass, {
258 newMethod1: function(){
261 newMethod2: function(foo){
266 * @param {Object} origclass The class to override
267 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
268 * containing one or more methods.
271 override : function(origclass, overrides){
273 var p = origclass.prototype;
274 for(var method in overrides){
275 p[method] = overrides[method];
280 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
282 Roo.namespace('Company', 'Company.data');
283 Company.Widget = function() { ... }
284 Company.data.CustomStore = function(config) { ... }
286 * @param {String} namespace1
287 * @param {String} namespace2
288 * @param {String} etc
291 namespace : function(){
292 var a=arguments, o=null, i, j, d, rt;
293 for (i=0; i<a.length; ++i) {
297 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
298 for (j=1; j<d.length; ++j) {
299 o[d[j]]=o[d[j]] || {};
305 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
307 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
308 Roo.factory(conf, Roo.data);
310 * @param {String} classname
311 * @param {String} namespace (optional)
315 factory : function(c, ns)
317 // no xtype, no ns or c.xns - or forced off by c.xns
318 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
321 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
322 if (c.constructor == ns[c.xtype]) {// already created...
326 if (Roo.debug) { Roo.log("Roo.Factory(" + c.xtype + ")"); }
327 var ret = new ns[c.xtype](c);
331 c.xns = false; // prevent recursion..
335 * Logs to console if it can.
337 * @param {String|Object} string
342 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
349 * 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.
353 urlEncode : function(o){
359 var ov = o[key], k = Roo.encodeURIComponent(key);
360 var type = typeof ov;
361 if(type == 'undefined'){
363 }else if(type != "function" && type != "object"){
364 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
365 }else if(ov instanceof Array){
367 for(var i = 0, len = ov.length; i < len; i++) {
368 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
379 * Safe version of encodeURIComponent
380 * @param {String} data
384 encodeURIComponent : function (data)
387 return encodeURIComponent(data);
388 } catch(e) {} // should be an uri encode error.
390 if (data == '' || data == null){
393 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
394 function nibble_to_hex(nibble){
395 var chars = '0123456789ABCDEF';
396 return chars.charAt(nibble);
398 data = data.toString();
400 for(var i=0; i<data.length; i++){
401 var c = data.charCodeAt(i);
402 var bs = new Array();
405 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
406 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
407 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
408 bs[3] = 0x80 | (c & 0x3F);
409 }else if (c > 0x800){
411 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
412 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
413 bs[2] = 0x80 | (c & 0x3F);
416 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
417 bs[1] = 0x80 | (c & 0x3F);
422 for(var j=0; j<bs.length; j++){
424 var hex = nibble_to_hex((b & 0xF0) >>> 4)
425 + nibble_to_hex(b &0x0F);
434 * 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]}.
435 * @param {String} string
436 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
437 * @return {Object} A literal with members
439 urlDecode : function(string, overwrite){
440 if(!string || !string.length){
444 var pairs = string.split('&');
445 var pair, name, value;
446 for(var i = 0, len = pairs.length; i < len; i++){
447 pair = pairs[i].split('=');
448 name = decodeURIComponent(pair[0]);
449 value = decodeURIComponent(pair[1]);
450 if(overwrite !== true){
451 if(typeof obj[name] == "undefined"){
453 }else if(typeof obj[name] == "string"){
454 obj[name] = [obj[name]];
455 obj[name].push(value);
457 obj[name].push(value);
467 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
468 * passed array is not really an array, your function is called once with it.
469 * The supplied function is called with (Object item, Number index, Array allItems).
470 * @param {Array/NodeList/Mixed} array
471 * @param {Function} fn
472 * @param {Object} scope
474 each : function(array, fn, scope){
475 if(typeof array.length == "undefined" || typeof array == "string"){
478 for(var i = 0, len = array.length; i < len; i++){
479 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
484 combine : function(){
485 var as = arguments, l = as.length, r = [];
486 for(var i = 0; i < l; i++){
488 if(a instanceof Array){
490 }else if(a.length !== undefined && !a.substr){
491 r = r.concat(Array.prototype.slice.call(a, 0));
500 * Escapes the passed string for use in a regular expression
501 * @param {String} str
504 escapeRe : function(s) {
505 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
509 callback : function(cb, scope, args, delay){
510 if(typeof cb == "function"){
512 cb.defer(delay, scope, args || []);
514 cb.apply(scope, args || []);
520 * Return the dom node for the passed string (id), dom node, or Roo.Element
521 * @param {String/HTMLElement/Roo.Element} el
522 * @return HTMLElement
524 getDom : function(el){
528 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
532 * Shorthand for {@link Roo.ComponentMgr#get}
534 * @return Roo.Component
536 getCmp : function(id){
537 return Roo.ComponentMgr.get(id);
540 num : function(v, defaultValue){
541 if(typeof v != 'number'){
547 destroy : function(){
548 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
552 as.removeAllListeners();
556 if(typeof as.purgeListeners == 'function'){
559 if(typeof as.destroy == 'function'){
566 // inpired by a similar function in mootools library
568 * Returns the type of object that is passed in. If the object passed in is null or undefined it
569 * return false otherwise it returns one of the following values:<ul>
570 * <li><b>string</b>: If the object passed is a string</li>
571 * <li><b>number</b>: If the object passed is a number</li>
572 * <li><b>boolean</b>: If the object passed is a boolean value</li>
573 * <li><b>function</b>: If the object passed is a function reference</li>
574 * <li><b>object</b>: If the object passed is an object</li>
575 * <li><b>array</b>: If the object passed is an array</li>
576 * <li><b>regexp</b>: If the object passed is a regular expression</li>
577 * <li><b>element</b>: If the object passed is a DOM Element</li>
578 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
579 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
580 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
581 * @param {Mixed} object
585 if(o === undefined || o === null){
592 if(t == 'object' && o.nodeName) {
594 case 1: return 'element';
595 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
598 if(t == 'object' || t == 'function') {
599 switch(o.constructor) {
600 case Array: return 'array';
601 case RegExp: return 'regexp';
603 if(typeof o.length == 'number' && typeof o.item == 'function') {
611 * Returns true if the passed value is null, undefined or an empty string (optional).
612 * @param {Mixed} value The value to test
613 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
616 isEmpty : function(v, allowBlank){
617 return v === null || v === undefined || (!allowBlank ? v === '' : false);
625 isFirefox : isFirefox,
635 isBorderBox : isBorderBox,
637 isWindows : isWindows,
645 isAndroid : isAndroid,
650 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
651 * you may want to set this to true.
654 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
659 * Selects a single element as a Roo Element
660 * This is about as close as you can get to jQuery's $('do crazy stuff')
661 * @param {String} selector The selector/xpath query
662 * @param {Node} root (optional) The start of the query (defaults to document).
663 * @return {Roo.Element}
665 selectNode : function(selector, root)
667 var node = Roo.DomQuery.selectNode(selector,root);
668 return node ? Roo.get(node) : new Roo.Element(false);
676 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
677 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout",
680 "Roo.bootstrap.dash");
683 * Ext JS Library 1.1.1
684 * Copyright(c) 2006-2007, Ext JS, LLC.
686 * Originally Released Under LGPL - original licence link has changed is not relivant.
689 * <script type="text/javascript">
693 // wrappedn so fnCleanup is not in global scope...
695 function fnCleanUp() {
696 var p = Function.prototype;
697 delete p.createSequence;
699 delete p.createDelegate;
700 delete p.createCallback;
701 delete p.createInterceptor;
703 window.detachEvent("onunload", fnCleanUp);
705 window.attachEvent("onunload", fnCleanUp);
712 * These functions are available on every Function object (any JavaScript function).
714 Roo.apply(Function.prototype, {
716 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
717 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
718 * Will create a function that is bound to those 2 args.
719 * @return {Function} The new function
721 createCallback : function(/*args...*/){
722 // make args available, in function below
723 var args = arguments;
726 return method.apply(window, args);
731 * Creates a delegate (callback) that sets the scope to obj.
732 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
733 * Will create a function that is automatically scoped to this.
734 * @param {Object} obj (optional) The object for which the scope is set
735 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
736 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
737 * if a number the args are inserted at the specified position
738 * @return {Function} The new function
740 createDelegate : function(obj, args, appendArgs){
743 var callArgs = args || arguments;
744 if(appendArgs === true){
745 callArgs = Array.prototype.slice.call(arguments, 0);
746 callArgs = callArgs.concat(args);
747 }else if(typeof appendArgs == "number"){
748 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
749 var applyArgs = [appendArgs, 0].concat(args); // create method call params
750 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
752 return method.apply(obj || window, callArgs);
757 * Calls this function after the number of millseconds specified.
758 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
759 * @param {Object} obj (optional) The object for which the scope is set
760 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
761 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
762 * if a number the args are inserted at the specified position
763 * @return {Number} The timeout id that can be used with clearTimeout
765 defer : function(millis, obj, args, appendArgs){
766 var fn = this.createDelegate(obj, args, appendArgs);
768 return setTimeout(fn, millis);
774 * Create a combined function call sequence of the original function + the passed function.
775 * The resulting function returns the results of the original function.
776 * The passed fcn is called with the parameters of the original function
777 * @param {Function} fcn The function to sequence
778 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
779 * @return {Function} The new function
781 createSequence : function(fcn, scope){
782 if(typeof fcn != "function"){
787 var retval = method.apply(this || window, arguments);
788 fcn.apply(scope || this || window, arguments);
794 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
795 * The resulting function returns the results of the original function.
796 * The passed fcn is called with the parameters of the original function.
798 * @param {Function} fcn The function to call before the original
799 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
800 * @return {Function} The new function
802 createInterceptor : function(fcn, scope){
803 if(typeof fcn != "function"){
810 if(fcn.apply(scope || this || window, arguments) === false){
813 return method.apply(this || window, arguments);
819 * Ext JS Library 1.1.1
820 * Copyright(c) 2006-2007, Ext JS, LLC.
822 * Originally Released Under LGPL - original licence link has changed is not relivant.
825 * <script type="text/javascript">
828 Roo.applyIf(String, {
833 * Escapes the passed string for ' and \
834 * @param {String} string The string to escape
835 * @return {String} The escaped string
838 escape : function(string) {
839 return string.replace(/('|\\)/g, "\\$1");
843 * Pads the left side of a string with a specified character. This is especially useful
844 * for normalizing number and date strings. Example usage:
846 var s = String.leftPad('123', 5, '0');
847 // s now contains the string: '00123'
849 * @param {String} string The original string
850 * @param {Number} size The total length of the output string
851 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
852 * @return {String} The padded string
855 leftPad : function (val, size, ch) {
856 var result = new String(val);
857 if(ch === null || ch === undefined || ch === '') {
860 while (result.length < size) {
861 result = ch + result;
867 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
868 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
870 var cls = 'my-class', text = 'Some text';
871 var s = String.format('<div class="{0}">{1}</div>', cls, text);
872 // s now contains the string: '<div class="my-class">Some text</div>'
874 * @param {String} string The tokenized string to be formatted
875 * @param {String} value1 The value to replace token {0}
876 * @param {String} value2 Etc...
877 * @return {String} The formatted string
880 format : function(format){
881 var args = Array.prototype.slice.call(arguments, 1);
882 return format.replace(/\{(\d+)\}/g, function(m, i){
883 return Roo.util.Format.htmlEncode(args[i]);
889 * Utility function that allows you to easily switch a string between two alternating values. The passed value
890 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
891 * they are already different, the first value passed in is returned. Note that this method returns the new value
892 * but does not change the current string.
894 // alternate sort directions
895 sort = sort.toggle('ASC', 'DESC');
897 // instead of conditional logic:
898 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
900 * @param {String} value The value to compare to the current string
901 * @param {String} other The new value to use if the string already equals the first value passed in
902 * @return {String} The new value
905 String.prototype.toggle = function(value, other){
906 return this == value ? other : value;
909 * Ext JS Library 1.1.1
910 * Copyright(c) 2006-2007, Ext JS, LLC.
912 * Originally Released Under LGPL - original licence link has changed is not relivant.
915 * <script type="text/javascript">
921 Roo.applyIf(Number.prototype, {
923 * Checks whether or not the current number is within a desired range. If the number is already within the
924 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
925 * exceeded. Note that this method returns the constrained value but does not change the current number.
926 * @param {Number} min The minimum number in the range
927 * @param {Number} max The maximum number in the range
928 * @return {Number} The constrained value if outside the range, otherwise the current value
930 constrain : function(min, max){
931 return Math.min(Math.max(this, min), max);
935 * Ext JS Library 1.1.1
936 * Copyright(c) 2006-2007, Ext JS, LLC.
938 * Originally Released Under LGPL - original licence link has changed is not relivant.
941 * <script type="text/javascript">
946 Roo.applyIf(Array.prototype, {
949 * Checks whether or not the specified object exists in the array.
950 * @param {Object} o The object to check for
951 * @return {Number} The index of o in the array (or -1 if it is not found)
953 indexOf : function(o){
954 for (var i = 0, len = this.length; i < len; i++){
955 if(this[i] == o) { return i; }
961 * Removes the specified object from the array. If the object is not found nothing happens.
962 * @param {Object} o The object to remove
964 remove : function(o){
965 var index = this.indexOf(o);
967 this.splice(index, 1);
971 * Map (JS 1.6 compatibility)
972 * @param {Function} function to call
976 var len = this.length >>> 0;
977 if (typeof fun != "function") {
978 throw new TypeError();
980 var res = new Array(len);
981 var thisp = arguments[1];
982 for (var i = 0; i < len; i++)
985 res[i] = fun.call(thisp, this[i], i, this);
998 * Ext JS Library 1.1.1
999 * Copyright(c) 2006-2007, Ext JS, LLC.
1001 * Originally Released Under LGPL - original licence link has changed is not relivant.
1004 * <script type="text/javascript">
1010 * The date parsing and format syntax is a subset of
1011 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
1012 * supported will provide results equivalent to their PHP versions.
1014 * Following is the list of all currently supported formats:
1017 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
1019 Format Output Description
1020 ------ ---------- --------------------------------------------------------------
1021 d 10 Day of the month, 2 digits with leading zeros
1022 D Wed A textual representation of a day, three letters
1023 j 10 Day of the month without leading zeros
1024 l Wednesday A full textual representation of the day of the week
1025 S th English ordinal day of month suffix, 2 chars (use with j)
1026 w 3 Numeric representation of the day of the week
1027 z 9 The julian date, or day of the year (0-365)
1028 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
1029 F January A full textual representation of the month
1030 m 01 Numeric representation of a month, with leading zeros
1031 M Jan Month name abbreviation, three letters
1032 n 1 Numeric representation of a month, without leading zeros
1033 t 31 Number of days in the given month
1034 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1035 Y 2007 A full numeric representation of a year, 4 digits
1036 y 07 A two digit representation of a year
1037 a pm Lowercase Ante meridiem and Post meridiem
1038 A PM Uppercase Ante meridiem and Post meridiem
1039 g 3 12-hour format of an hour without leading zeros
1040 G 15 24-hour format of an hour without leading zeros
1041 h 03 12-hour format of an hour with leading zeros
1042 H 15 24-hour format of an hour with leading zeros
1043 i 05 Minutes with leading zeros
1044 s 01 Seconds, with leading zeros
1045 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1046 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1047 T CST Timezone setting of the machine running the code
1048 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1051 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1053 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1054 document.write(dt.format('Y-m-d')); //2007-01-10
1055 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1056 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
1059 * Here are some standard date/time patterns that you might find helpful. They
1060 * are not part of the source of Date.js, but to use them you can simply copy this
1061 * block of code into any script that is included after Date.js and they will also become
1062 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1065 ISO8601Long:"Y-m-d H:i:s",
1066 ISO8601Short:"Y-m-d",
1068 LongDate: "l, F d, Y",
1069 FullDateTime: "l, F d, Y g:i:s A",
1072 LongTime: "g:i:s A",
1073 SortableDateTime: "Y-m-d\\TH:i:s",
1074 UniversalSortableDateTime: "Y-m-d H:i:sO",
1081 var dt = new Date();
1082 document.write(dt.format(Date.patterns.ShortDate));
1087 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1088 * They generate precompiled functions from date formats instead of parsing and
1089 * processing the pattern every time you format a date. These functions are available
1090 * on every Date object (any javascript function).
1092 * The original article and download are here:
1093 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1100 Returns the number of milliseconds between this date and date
1101 @param {Date} date (optional) Defaults to now
1102 @return {Number} The diff in milliseconds
1103 @member Date getElapsed
1105 Date.prototype.getElapsed = function(date) {
1106 return Math.abs((date || new Date()).getTime()-this.getTime());
1108 // was in date file..
1112 Date.parseFunctions = {count:0};
1114 Date.parseRegexes = [];
1116 Date.formatFunctions = {count:0};
1119 Date.prototype.dateFormat = function(format) {
1120 if (Date.formatFunctions[format] == null) {
1121 Date.createNewFormat(format);
1123 var func = Date.formatFunctions[format];
1124 return this[func]();
1129 * Formats a date given the supplied format string
1130 * @param {String} format The format string
1131 * @return {String} The formatted date
1134 Date.prototype.format = Date.prototype.dateFormat;
1137 Date.createNewFormat = function(format) {
1138 var funcName = "format" + Date.formatFunctions.count++;
1139 Date.formatFunctions[format] = funcName;
1140 var code = "Date.prototype." + funcName + " = function(){return ";
1141 var special = false;
1143 for (var i = 0; i < format.length; ++i) {
1144 ch = format.charAt(i);
1145 if (!special && ch == "\\") {
1150 code += "'" + String.escape(ch) + "' + ";
1153 code += Date.getFormatCode(ch);
1156 /** eval:var:zzzzzzzzzzzzz */
1157 eval(code.substring(0, code.length - 3) + ";}");
1161 Date.getFormatCode = function(character) {
1162 switch (character) {
1164 return "String.leftPad(this.getDate(), 2, '0') + ";
1166 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1168 return "this.getDate() + ";
1170 return "Date.dayNames[this.getDay()] + ";
1172 return "this.getSuffix() + ";
1174 return "this.getDay() + ";
1176 return "this.getDayOfYear() + ";
1178 return "this.getWeekOfYear() + ";
1180 return "Date.monthNames[this.getMonth()] + ";
1182 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1184 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1186 return "(this.getMonth() + 1) + ";
1188 return "this.getDaysInMonth() + ";
1190 return "(this.isLeapYear() ? 1 : 0) + ";
1192 return "this.getFullYear() + ";
1194 return "('' + this.getFullYear()).substring(2, 4) + ";
1196 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1198 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1200 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1202 return "this.getHours() + ";
1204 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1206 return "String.leftPad(this.getHours(), 2, '0') + ";
1208 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1210 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1212 return "this.getGMTOffset() + ";
1214 return "this.getGMTColonOffset() + ";
1216 return "this.getTimezone() + ";
1218 return "(this.getTimezoneOffset() * -60) + ";
1220 return "'" + String.escape(character) + "' + ";
1225 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1226 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1227 * the date format that is not specified will default to the current date value for that part. Time parts can also
1228 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1229 * string or the parse operation will fail.
1232 //dt = Fri May 25 2007 (current date)
1233 var dt = new Date();
1235 //dt = Thu May 25 2006 (today's month/day in 2006)
1236 dt = Date.parseDate("2006", "Y");
1238 //dt = Sun Jan 15 2006 (all date parts specified)
1239 dt = Date.parseDate("2006-1-15", "Y-m-d");
1241 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1242 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1244 * @param {String} input The unparsed date as a string
1245 * @param {String} format The format the date is in
1246 * @return {Date} The parsed date
1249 Date.parseDate = function(input, format) {
1250 if (Date.parseFunctions[format] == null) {
1251 Date.createParser(format);
1253 var func = Date.parseFunctions[format];
1254 return Date[func](input);
1260 Date.createParser = function(format) {
1261 var funcName = "parse" + Date.parseFunctions.count++;
1262 var regexNum = Date.parseRegexes.length;
1263 var currentGroup = 1;
1264 Date.parseFunctions[format] = funcName;
1266 var code = "Date." + funcName + " = function(input){\n"
1267 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1268 + "var d = new Date();\n"
1269 + "y = d.getFullYear();\n"
1270 + "m = d.getMonth();\n"
1271 + "d = d.getDate();\n"
1272 + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
1273 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1274 + "if (results && results.length > 0) {";
1277 var special = false;
1279 for (var i = 0; i < format.length; ++i) {
1280 ch = format.charAt(i);
1281 if (!special && ch == "\\") {
1286 regex += String.escape(ch);
1289 var obj = Date.formatCodeToRegex(ch, currentGroup);
1290 currentGroup += obj.g;
1292 if (obj.g && obj.c) {
1298 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1299 + "{v = new Date(y, m, d, h, i, s);}\n"
1300 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1301 + "{v = new Date(y, m, d, h, i);}\n"
1302 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1303 + "{v = new Date(y, m, d, h);}\n"
1304 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1305 + "{v = new Date(y, m, d);}\n"
1306 + "else if (y >= 0 && m >= 0)\n"
1307 + "{v = new Date(y, m);}\n"
1308 + "else if (y >= 0)\n"
1309 + "{v = new Date(y);}\n"
1310 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1311 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1312 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1315 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1316 /** eval:var:zzzzzzzzzzzzz */
1321 Date.formatCodeToRegex = function(character, currentGroup) {
1322 switch (character) {
1326 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1329 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1330 s:"(\\d{1,2})"}; // day of month without leading zeroes
1333 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1334 s:"(\\d{2})"}; // day of month with leading zeroes
1338 s:"(?:" + Date.dayNames.join("|") + ")"};
1342 s:"(?:st|nd|rd|th)"};
1357 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1358 s:"(" + Date.monthNames.join("|") + ")"};
1361 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1362 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1365 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1366 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1369 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1370 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1381 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1385 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1386 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1390 c:"if (results[" + currentGroup + "] == 'am') {\n"
1391 + "if (h == 12) { h = 0; }\n"
1392 + "} else { if (h < 12) { h += 12; }}",
1396 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1397 + "if (h == 12) { h = 0; }\n"
1398 + "} else { if (h < 12) { h += 12; }}",
1403 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1404 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1408 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1409 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1412 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1416 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1421 "o = results[", currentGroup, "];\n",
1422 "var sn = o.substring(0,1);\n", // get + / - sign
1423 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1424 "var mn = o.substring(3,5) % 60;\n", // get minutes
1425 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1426 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1428 s:"([+\-]\\d{2,4})"};
1434 "o = results[", currentGroup, "];\n",
1435 "var sn = o.substring(0,1);\n",
1436 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1437 "var mn = o.substring(4,6) % 60;\n",
1438 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1439 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1445 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1448 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1449 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1450 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1454 s:String.escape(character)};
1459 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1460 * @return {String} The abbreviated timezone name (e.g. 'CST')
1462 Date.prototype.getTimezone = function() {
1463 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1467 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1468 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1470 Date.prototype.getGMTOffset = function() {
1471 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1472 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1473 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1477 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1478 * @return {String} 2-characters representing hours and 2-characters representing minutes
1479 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1481 Date.prototype.getGMTColonOffset = function() {
1482 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1483 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1485 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1489 * Get the numeric day number of the year, adjusted for leap year.
1490 * @return {Number} 0 through 364 (365 in leap years)
1492 Date.prototype.getDayOfYear = function() {
1494 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1495 for (var i = 0; i < this.getMonth(); ++i) {
1496 num += Date.daysInMonth[i];
1498 return num + this.getDate() - 1;
1502 * Get the string representation of the numeric week number of the year
1503 * (equivalent to the format specifier 'W').
1504 * @return {String} '00' through '52'
1506 Date.prototype.getWeekOfYear = function() {
1507 // Skip to Thursday of this week
1508 var now = this.getDayOfYear() + (4 - this.getDay());
1509 // Find the first Thursday of the year
1510 var jan1 = new Date(this.getFullYear(), 0, 1);
1511 var then = (7 - jan1.getDay() + 4);
1512 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1516 * Whether or not the current date is in a leap year.
1517 * @return {Boolean} True if the current date is in a leap year, else false
1519 Date.prototype.isLeapYear = function() {
1520 var year = this.getFullYear();
1521 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1525 * Get the first day of the current month, adjusted for leap year. The returned value
1526 * is the numeric day index within the week (0-6) which can be used in conjunction with
1527 * the {@link #monthNames} array to retrieve the textual day name.
1530 var dt = new Date('1/10/2007');
1531 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1533 * @return {Number} The day number (0-6)
1535 Date.prototype.getFirstDayOfMonth = function() {
1536 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1537 return (day < 0) ? (day + 7) : day;
1541 * Get the last day of the current month, adjusted for leap year. The returned value
1542 * is the numeric day index within the week (0-6) which can be used in conjunction with
1543 * the {@link #monthNames} array to retrieve the textual day name.
1546 var dt = new Date('1/10/2007');
1547 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1549 * @return {Number} The day number (0-6)
1551 Date.prototype.getLastDayOfMonth = function() {
1552 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1553 return (day < 0) ? (day + 7) : day;
1558 * Get the first date of this date's month
1561 Date.prototype.getFirstDateOfMonth = function() {
1562 return new Date(this.getFullYear(), this.getMonth(), 1);
1566 * Get the last date of this date's month
1569 Date.prototype.getLastDateOfMonth = function() {
1570 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1573 * Get the number of days in the current month, adjusted for leap year.
1574 * @return {Number} The number of days in the month
1576 Date.prototype.getDaysInMonth = function() {
1577 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1578 return Date.daysInMonth[this.getMonth()];
1582 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1583 * @return {String} 'st, 'nd', 'rd' or 'th'
1585 Date.prototype.getSuffix = function() {
1586 switch (this.getDate()) {
1603 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1606 * An array of textual month names.
1607 * Override these values for international dates, for example...
1608 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1627 * An array of textual day names.
1628 * Override these values for international dates, for example...
1629 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1645 Date.monthNumbers = {
1660 * Creates and returns a new Date instance with the exact same date value as the called instance.
1661 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1662 * variable will also be changed. When the intention is to create a new variable that will not
1663 * modify the original instance, you should create a clone.
1665 * Example of correctly cloning a date:
1668 var orig = new Date('10/1/2006');
1671 document.write(orig); //returns 'Thu Oct 05 2006'!
1674 var orig = new Date('10/1/2006');
1675 var copy = orig.clone();
1677 document.write(orig); //returns 'Thu Oct 01 2006'
1679 * @return {Date} The new Date instance
1681 Date.prototype.clone = function() {
1682 return new Date(this.getTime());
1686 * Clears any time information from this date
1687 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1688 @return {Date} this or the clone
1690 Date.prototype.clearTime = function(clone){
1692 return this.clone().clearTime();
1697 this.setMilliseconds(0);
1702 // safari setMonth is broken -- check that this is only donw once...
1703 if(Roo.isSafari && typeof(Date.brokenSetMonth) == 'undefined'){
1704 Date.brokenSetMonth = Date.prototype.setMonth;
1705 Date.prototype.setMonth = function(num){
1707 var n = Math.ceil(-num);
1708 var back_year = Math.ceil(n/12);
1709 var month = (n % 12) ? 12 - n % 12 : 0 ;
1710 this.setFullYear(this.getFullYear() - back_year);
1711 return Date.brokenSetMonth.call(this, month);
1713 return Date.brokenSetMonth.apply(this, arguments);
1718 /** Date interval constant
1722 /** Date interval constant
1726 /** Date interval constant
1730 /** Date interval constant
1734 /** Date interval constant
1738 /** Date interval constant
1742 /** Date interval constant
1748 * Provides a convenient method of performing basic date arithmetic. This method
1749 * does not modify the Date instance being called - it creates and returns
1750 * a new Date instance containing the resulting date value.
1755 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1756 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1758 //Negative values will subtract correctly:
1759 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1760 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1762 //You can even chain several calls together in one line!
1763 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1764 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1767 * @param {String} interval A valid date interval enum value
1768 * @param {Number} value The amount to add to the current date
1769 * @return {Date} The new Date instance
1771 Date.prototype.add = function(interval, value){
1772 var d = this.clone();
1773 if (!interval || value === 0) { return d; }
1774 switch(interval.toLowerCase()){
1776 d.setMilliseconds(this.getMilliseconds() + value);
1779 d.setSeconds(this.getSeconds() + value);
1782 d.setMinutes(this.getMinutes() + value);
1785 d.setHours(this.getHours() + value);
1788 d.setDate(this.getDate() + value);
1791 var day = this.getDate();
1793 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1796 d.setMonth(this.getMonth() + value);
1799 d.setFullYear(this.getFullYear() + value);
1806 * Ext JS Library 1.1.1
1807 * Copyright(c) 2006-2007, Ext JS, LLC.
1809 * Originally Released Under LGPL - original licence link has changed is not relivant.
1812 * <script type="text/javascript">
1816 * @class Roo.lib.Dom
1819 * Dom utils (from YIU afaik)
1824 * Get the view width
1825 * @param {Boolean} full True will get the full document, otherwise it's the view width
1826 * @return {Number} The width
1829 getViewWidth : function(full) {
1830 return full ? this.getDocumentWidth() : this.getViewportWidth();
1833 * Get the view height
1834 * @param {Boolean} full True will get the full document, otherwise it's the view height
1835 * @return {Number} The height
1837 getViewHeight : function(full) {
1838 return full ? this.getDocumentHeight() : this.getViewportHeight();
1841 getDocumentHeight: function() {
1842 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1843 return Math.max(scrollHeight, this.getViewportHeight());
1846 getDocumentWidth: function() {
1847 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1848 return Math.max(scrollWidth, this.getViewportWidth());
1851 getViewportHeight: function() {
1852 var height = self.innerHeight;
1853 var mode = document.compatMode;
1855 if ((mode || Roo.isIE) && !Roo.isOpera) {
1856 height = (mode == "CSS1Compat") ?
1857 document.documentElement.clientHeight :
1858 document.body.clientHeight;
1864 getViewportWidth: function() {
1865 var width = self.innerWidth;
1866 var mode = document.compatMode;
1868 if (mode || Roo.isIE) {
1869 width = (mode == "CSS1Compat") ?
1870 document.documentElement.clientWidth :
1871 document.body.clientWidth;
1876 isAncestor : function(p, c) {
1883 if (p.contains && !Roo.isSafari) {
1884 return p.contains(c);
1885 } else if (p.compareDocumentPosition) {
1886 return !!(p.compareDocumentPosition(c) & 16);
1888 var parent = c.parentNode;
1893 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1896 parent = parent.parentNode;
1902 getRegion : function(el) {
1903 return Roo.lib.Region.getRegion(el);
1906 getY : function(el) {
1907 return this.getXY(el)[1];
1910 getX : function(el) {
1911 return this.getXY(el)[0];
1914 getXY : function(el) {
1915 var p, pe, b, scroll, bd = document.body;
1916 el = Roo.getDom(el);
1917 var fly = Roo.lib.AnimBase.fly;
1918 if (el.getBoundingClientRect) {
1919 b = el.getBoundingClientRect();
1920 scroll = fly(document).getScroll();
1921 return [b.left + scroll.left, b.top + scroll.top];
1927 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1934 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1941 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1942 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1949 if (p != el && pe.getStyle('overflow') != 'visible') {
1957 if (Roo.isSafari && hasAbsolute) {
1962 if (Roo.isGecko && !hasAbsolute) {
1964 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1965 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1969 while (p && p != bd) {
1970 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1982 setXY : function(el, xy) {
1983 el = Roo.fly(el, '_setXY');
1985 var pts = el.translatePoints(xy);
1986 if (xy[0] !== false) {
1987 el.dom.style.left = pts.left + "px";
1989 if (xy[1] !== false) {
1990 el.dom.style.top = pts.top + "px";
1994 setX : function(el, x) {
1995 this.setXY(el, [x, false]);
1998 setY : function(el, y) {
1999 this.setXY(el, [false, y]);
2003 * Portions of this file are based on pieces of Yahoo User Interface Library
2004 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2005 * YUI licensed under the BSD License:
2006 * http://developer.yahoo.net/yui/license.txt
2007 * <script type="text/javascript">
2011 Roo.lib.Event = function() {
2012 var loadComplete = false;
2014 var unloadListeners = [];
2016 var onAvailStack = [];
2018 var lastError = null;
2031 startInterval: function() {
2032 if (!this._interval) {
2034 var callback = function() {
2035 self._tryPreloadAttach();
2037 this._interval = setInterval(callback, this.POLL_INTERVAL);
2042 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2043 onAvailStack.push({ id: p_id,
2046 override: p_override,
2047 checkReady: false });
2049 retryCount = this.POLL_RETRYS;
2050 this.startInterval();
2054 addListener: function(el, eventName, fn) {
2055 el = Roo.getDom(el);
2060 if ("unload" == eventName) {
2061 unloadListeners[unloadListeners.length] =
2062 [el, eventName, fn];
2066 var wrappedFn = function(e) {
2067 return fn(Roo.lib.Event.getEvent(e));
2070 var li = [el, eventName, fn, wrappedFn];
2072 var index = listeners.length;
2073 listeners[index] = li;
2075 this.doAdd(el, eventName, wrappedFn, false);
2081 removeListener: function(el, eventName, fn) {
2084 el = Roo.getDom(el);
2087 return this.purgeElement(el, false, eventName);
2091 if ("unload" == eventName) {
2093 for (i = 0,len = unloadListeners.length; i < len; i++) {
2094 var li = unloadListeners[i];
2097 li[1] == eventName &&
2099 unloadListeners.splice(i, 1);
2107 var cacheItem = null;
2110 var index = arguments[3];
2112 if ("undefined" == typeof index) {
2113 index = this._getCacheIndex(el, eventName, fn);
2117 cacheItem = listeners[index];
2120 if (!el || !cacheItem) {
2124 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2126 delete listeners[index][this.WFN];
2127 delete listeners[index][this.FN];
2128 listeners.splice(index, 1);
2135 getTarget: function(ev, resolveTextNode) {
2136 ev = ev.browserEvent || ev;
2137 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2138 var t = ev.target || ev.srcElement;
2139 return this.resolveTextNode(t);
2143 resolveTextNode: function(node) {
2144 if (Roo.isSafari && node && 3 == node.nodeType) {
2145 return node.parentNode;
2152 getPageX: function(ev) {
2153 ev = ev.browserEvent || ev;
2154 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2156 if (!x && 0 !== x) {
2157 x = ev.clientX || 0;
2160 x += this.getScroll()[1];
2168 getPageY: function(ev) {
2169 ev = ev.browserEvent || ev;
2170 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2172 if (!y && 0 !== y) {
2173 y = ev.clientY || 0;
2176 y += this.getScroll()[0];
2185 getXY: function(ev) {
2186 ev = ev.browserEvent || ev;
2187 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2188 return [this.getPageX(ev), this.getPageY(ev)];
2192 getRelatedTarget: function(ev) {
2193 ev = ev.browserEvent || ev;
2194 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2195 var t = ev.relatedTarget;
2197 if (ev.type == "mouseout") {
2199 } else if (ev.type == "mouseover") {
2204 return this.resolveTextNode(t);
2208 getTime: function(ev) {
2209 ev = ev.browserEvent || ev;
2210 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2212 var t = new Date().getTime();
2216 this.lastError = ex;
2225 stopEvent: function(ev) {
2226 this.stopPropagation(ev);
2227 this.preventDefault(ev);
2231 stopPropagation: function(ev) {
2232 ev = ev.browserEvent || ev;
2233 if (ev.stopPropagation) {
2234 ev.stopPropagation();
2236 ev.cancelBubble = true;
2241 preventDefault: function(ev) {
2242 ev = ev.browserEvent || ev;
2243 if(ev.preventDefault) {
2244 ev.preventDefault();
2246 ev.returnValue = false;
2251 getEvent: function(e) {
2252 var ev = e || window.event;
2254 var c = this.getEvent.caller;
2256 ev = c.arguments[0];
2257 if (ev && Event == ev.constructor) {
2267 getCharCode: function(ev) {
2268 ev = ev.browserEvent || ev;
2269 return ev.charCode || ev.keyCode || 0;
2273 _getCacheIndex: function(el, eventName, fn) {
2274 for (var i = 0,len = listeners.length; i < len; ++i) {
2275 var li = listeners[i];
2277 li[this.FN] == fn &&
2278 li[this.EL] == el &&
2279 li[this.TYPE] == eventName) {
2291 getEl: function(id) {
2292 return document.getElementById(id);
2296 clearCache: function() {
2300 _load: function(e) {
2301 loadComplete = true;
2302 var EU = Roo.lib.Event;
2306 EU.doRemove(window, "load", EU._load);
2311 _tryPreloadAttach: function() {
2320 var tryAgain = !loadComplete;
2322 tryAgain = (retryCount > 0);
2327 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2328 var item = onAvailStack[i];
2330 var el = this.getEl(item.id);
2333 if (!item.checkReady ||
2336 (document && document.body)) {
2339 if (item.override) {
2340 if (item.override === true) {
2343 scope = item.override;
2346 item.fn.call(scope, item.obj);
2347 onAvailStack[i] = null;
2350 notAvail.push(item);
2355 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2359 this.startInterval();
2361 clearInterval(this._interval);
2362 this._interval = null;
2365 this.locked = false;
2372 purgeElement: function(el, recurse, eventName) {
2373 var elListeners = this.getListeners(el, eventName);
2375 for (var i = 0,len = elListeners.length; i < len; ++i) {
2376 var l = elListeners[i];
2377 this.removeListener(el, l.type, l.fn);
2381 if (recurse && el && el.childNodes) {
2382 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2383 this.purgeElement(el.childNodes[i], recurse, eventName);
2389 getListeners: function(el, eventName) {
2390 var results = [], searchLists;
2392 searchLists = [listeners, unloadListeners];
2393 } else if (eventName == "unload") {
2394 searchLists = [unloadListeners];
2396 searchLists = [listeners];
2399 for (var j = 0; j < searchLists.length; ++j) {
2400 var searchList = searchLists[j];
2401 if (searchList && searchList.length > 0) {
2402 for (var i = 0,len = searchList.length; i < len; ++i) {
2403 var l = searchList[i];
2404 if (l && l[this.EL] === el &&
2405 (!eventName || eventName === l[this.TYPE])) {
2410 adjust: l[this.ADJ_SCOPE],
2418 return (results.length) ? results : null;
2422 _unload: function(e) {
2424 var EU = Roo.lib.Event, i, j, l, len, index;
2426 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2427 l = unloadListeners[i];
2430 if (l[EU.ADJ_SCOPE]) {
2431 if (l[EU.ADJ_SCOPE] === true) {
2434 scope = l[EU.ADJ_SCOPE];
2437 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2438 unloadListeners[i] = null;
2444 unloadListeners = null;
2446 if (listeners && listeners.length > 0) {
2447 j = listeners.length;
2450 l = listeners[index];
2452 EU.removeListener(l[EU.EL], l[EU.TYPE],
2462 EU.doRemove(window, "unload", EU._unload);
2467 getScroll: function() {
2468 var dd = document.documentElement, db = document.body;
2469 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2470 return [dd.scrollTop, dd.scrollLeft];
2472 return [db.scrollTop, db.scrollLeft];
2479 doAdd: function () {
2480 if (window.addEventListener) {
2481 return function(el, eventName, fn, capture) {
2482 el.addEventListener(eventName, fn, (capture));
2484 } else if (window.attachEvent) {
2485 return function(el, eventName, fn, capture) {
2486 el.attachEvent("on" + eventName, fn);
2495 doRemove: function() {
2496 if (window.removeEventListener) {
2497 return function (el, eventName, fn, capture) {
2498 el.removeEventListener(eventName, fn, (capture));
2500 } else if (window.detachEvent) {
2501 return function (el, eventName, fn) {
2502 el.detachEvent("on" + eventName, fn);
2514 var E = Roo.lib.Event;
2515 E.on = E.addListener;
2516 E.un = E.removeListener;
2518 if (document && document.body) {
2521 E.doAdd(window, "load", E._load);
2523 E.doAdd(window, "unload", E._unload);
2524 E._tryPreloadAttach();
2528 * Portions of this file are based on pieces of Yahoo User Interface Library
2529 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2530 * YUI licensed under the BSD License:
2531 * http://developer.yahoo.net/yui/license.txt
2532 * <script type="text/javascript">
2538 * @class Roo.lib.Ajax
2545 request : function(method, uri, cb, data, options) {
2547 var hs = options.headers;
2550 if(hs.hasOwnProperty(h)){
2551 this.initHeader(h, hs[h], false);
2555 if(options.xmlData){
2556 this.initHeader('Content-Type', 'text/xml', false);
2558 data = options.xmlData;
2562 return this.asyncRequest(method, uri, cb, data);
2565 serializeForm : function(form) {
2566 if(typeof form == 'string') {
2567 form = (document.getElementById(form) || document.forms[form]);
2570 var el, name, val, disabled, data = '', hasSubmit = false;
2571 for (var i = 0; i < form.elements.length; i++) {
2572 el = form.elements[i];
2573 disabled = form.elements[i].disabled;
2574 name = form.elements[i].name;
2575 val = form.elements[i].value;
2577 if (!disabled && name){
2581 case 'select-multiple':
2582 for (var j = 0; j < el.options.length; j++) {
2583 if (el.options[j].selected) {
2585 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2588 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2596 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2609 if(hasSubmit == false) {
2610 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2615 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2620 data = data.substr(0, data.length - 1);
2628 useDefaultHeader:true,
2630 defaultPostHeader:'application/x-www-form-urlencoded',
2632 useDefaultXhrHeader:true,
2634 defaultXhrHeader:'XMLHttpRequest',
2636 hasDefaultHeaders:true,
2648 setProgId:function(id)
2650 this.activeX.unshift(id);
2653 setDefaultPostHeader:function(b)
2655 this.useDefaultHeader = b;
2658 setDefaultXhrHeader:function(b)
2660 this.useDefaultXhrHeader = b;
2663 setPollingInterval:function(i)
2665 if (typeof i == 'number' && isFinite(i)) {
2666 this.pollInterval = i;
2670 createXhrObject:function(transactionId)
2676 http = new XMLHttpRequest();
2678 obj = { conn:http, tId:transactionId };
2682 for (var i = 0; i < this.activeX.length; ++i) {
2686 http = new ActiveXObject(this.activeX[i]);
2688 obj = { conn:http, tId:transactionId };
2701 getConnectionObject:function()
2704 var tId = this.transactionId;
2708 o = this.createXhrObject(tId);
2710 this.transactionId++;
2721 asyncRequest:function(method, uri, callback, postData)
2723 var o = this.getConnectionObject();
2729 o.conn.open(method, uri, true);
2731 if (this.useDefaultXhrHeader) {
2732 if (!this.defaultHeaders['X-Requested-With']) {
2733 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2737 if(postData && this.useDefaultHeader){
2738 this.initHeader('Content-Type', this.defaultPostHeader);
2741 if (this.hasDefaultHeaders || this.hasHeaders) {
2745 this.handleReadyState(o, callback);
2746 o.conn.send(postData || null);
2752 handleReadyState:function(o, callback)
2756 if (callback && callback.timeout) {
2758 this.timeout[o.tId] = window.setTimeout(function() {
2759 oConn.abort(o, callback, true);
2760 }, callback.timeout);
2763 this.poll[o.tId] = window.setInterval(
2765 if (o.conn && o.conn.readyState == 4) {
2766 window.clearInterval(oConn.poll[o.tId]);
2767 delete oConn.poll[o.tId];
2769 if(callback && callback.timeout) {
2770 window.clearTimeout(oConn.timeout[o.tId]);
2771 delete oConn.timeout[o.tId];
2774 oConn.handleTransactionResponse(o, callback);
2777 , this.pollInterval);
2780 handleTransactionResponse:function(o, callback, isAbort)
2784 this.releaseObject(o);
2788 var httpStatus, responseObject;
2792 if (o.conn.status !== undefined && o.conn.status != 0) {
2793 httpStatus = o.conn.status;
2805 if (httpStatus >= 200 && httpStatus < 300) {
2806 responseObject = this.createResponseObject(o, callback.argument);
2807 if (callback.success) {
2808 if (!callback.scope) {
2809 callback.success(responseObject);
2814 callback.success.apply(callback.scope, [responseObject]);
2819 switch (httpStatus) {
2827 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2828 if (callback.failure) {
2829 if (!callback.scope) {
2830 callback.failure(responseObject);
2833 callback.failure.apply(callback.scope, [responseObject]);
2838 responseObject = this.createResponseObject(o, callback.argument);
2839 if (callback.failure) {
2840 if (!callback.scope) {
2841 callback.failure(responseObject);
2844 callback.failure.apply(callback.scope, [responseObject]);
2850 this.releaseObject(o);
2851 responseObject = null;
2854 createResponseObject:function(o, callbackArg)
2861 var headerStr = o.conn.getAllResponseHeaders();
2862 var header = headerStr.split('\n');
2863 for (var i = 0; i < header.length; i++) {
2864 var delimitPos = header[i].indexOf(':');
2865 if (delimitPos != -1) {
2866 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2874 obj.status = o.conn.status;
2875 obj.statusText = o.conn.statusText;
2876 obj.getResponseHeader = headerObj;
2877 obj.getAllResponseHeaders = headerStr;
2878 obj.responseText = o.conn.responseText;
2879 obj.responseXML = o.conn.responseXML;
2881 if (typeof callbackArg !== undefined) {
2882 obj.argument = callbackArg;
2888 createExceptionObject:function(tId, callbackArg, isAbort)
2891 var COMM_ERROR = 'communication failure';
2892 var ABORT_CODE = -1;
2893 var ABORT_ERROR = 'transaction aborted';
2899 obj.status = ABORT_CODE;
2900 obj.statusText = ABORT_ERROR;
2903 obj.status = COMM_CODE;
2904 obj.statusText = COMM_ERROR;
2908 obj.argument = callbackArg;
2914 initHeader:function(label, value, isDefault)
2916 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2918 if (headerObj[label] === undefined) {
2919 headerObj[label] = value;
2924 headerObj[label] = value + "," + headerObj[label];
2928 this.hasDefaultHeaders = true;
2931 this.hasHeaders = true;
2936 setHeader:function(o)
2938 if (this.hasDefaultHeaders) {
2939 for (var prop in this.defaultHeaders) {
2940 if (this.defaultHeaders.hasOwnProperty(prop)) {
2941 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2946 if (this.hasHeaders) {
2947 for (var prop in this.headers) {
2948 if (this.headers.hasOwnProperty(prop)) {
2949 o.conn.setRequestHeader(prop, this.headers[prop]);
2953 this.hasHeaders = false;
2957 resetDefaultHeaders:function() {
2958 delete this.defaultHeaders;
2959 this.defaultHeaders = {};
2960 this.hasDefaultHeaders = false;
2963 abort:function(o, callback, isTimeout)
2965 if(this.isCallInProgress(o)) {
2967 window.clearInterval(this.poll[o.tId]);
2968 delete this.poll[o.tId];
2970 delete this.timeout[o.tId];
2973 this.handleTransactionResponse(o, callback, true);
2983 isCallInProgress:function(o)
2986 return o.conn.readyState != 4 && o.conn.readyState != 0;
2995 releaseObject:function(o)
3004 'MSXML2.XMLHTTP.3.0',
3012 * Portions of this file are based on pieces of Yahoo User Interface Library
3013 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3014 * YUI licensed under the BSD License:
3015 * http://developer.yahoo.net/yui/license.txt
3016 * <script type="text/javascript">
3020 Roo.lib.Region = function(t, r, b, l) {
3030 Roo.lib.Region.prototype = {
3031 contains : function(region) {
3032 return ( region.left >= this.left &&
3033 region.right <= this.right &&
3034 region.top >= this.top &&
3035 region.bottom <= this.bottom );
3039 getArea : function() {
3040 return ( (this.bottom - this.top) * (this.right - this.left) );
3043 intersect : function(region) {
3044 var t = Math.max(this.top, region.top);
3045 var r = Math.min(this.right, region.right);
3046 var b = Math.min(this.bottom, region.bottom);
3047 var l = Math.max(this.left, region.left);
3049 if (b >= t && r >= l) {
3050 return new Roo.lib.Region(t, r, b, l);
3055 union : function(region) {
3056 var t = Math.min(this.top, region.top);
3057 var r = Math.max(this.right, region.right);
3058 var b = Math.max(this.bottom, region.bottom);
3059 var l = Math.min(this.left, region.left);
3061 return new Roo.lib.Region(t, r, b, l);
3064 adjust : function(t, l, b, r) {
3073 Roo.lib.Region.getRegion = function(el) {
3074 var p = Roo.lib.Dom.getXY(el);
3077 var r = p[0] + el.offsetWidth;
3078 var b = p[1] + el.offsetHeight;
3081 return new Roo.lib.Region(t, r, b, l);
3084 * Portions of this file are based on pieces of Yahoo User Interface Library
3085 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3086 * YUI licensed under the BSD License:
3087 * http://developer.yahoo.net/yui/license.txt
3088 * <script type="text/javascript">
3091 //@@dep Roo.lib.Region
3094 Roo.lib.Point = function(x, y) {
3095 if (x instanceof Array) {
3099 this.x = this.right = this.left = this[0] = x;
3100 this.y = this.top = this.bottom = this[1] = y;
3103 Roo.lib.Point.prototype = new Roo.lib.Region();
3105 * Portions of this file are based on pieces of Yahoo User Interface Library
3106 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3107 * YUI licensed under the BSD License:
3108 * http://developer.yahoo.net/yui/license.txt
3109 * <script type="text/javascript">
3116 scroll : function(el, args, duration, easing, cb, scope) {
3117 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3120 motion : function(el, args, duration, easing, cb, scope) {
3121 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3124 color : function(el, args, duration, easing, cb, scope) {
3125 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3128 run : function(el, args, duration, easing, cb, scope, type) {
3129 type = type || Roo.lib.AnimBase;
3130 if (typeof easing == "string") {
3131 easing = Roo.lib.Easing[easing];
3133 var anim = new type(el, args, duration, easing);
3134 anim.animateX(function() {
3135 Roo.callback(cb, scope);
3141 * Portions of this file are based on pieces of Yahoo User Interface Library
3142 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3143 * YUI licensed under the BSD License:
3144 * http://developer.yahoo.net/yui/license.txt
3145 * <script type="text/javascript">
3153 if (!libFlyweight) {
3154 libFlyweight = new Roo.Element.Flyweight();
3156 libFlyweight.dom = el;
3157 return libFlyweight;
3160 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3164 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3166 this.init(el, attributes, duration, method);
3170 Roo.lib.AnimBase.fly = fly;
3174 Roo.lib.AnimBase.prototype = {
3176 toString: function() {
3177 var el = this.getEl();
3178 var id = el.id || el.tagName;
3179 return ("Anim " + id);
3183 noNegatives: /width|height|opacity|padding/i,
3184 offsetAttribute: /^((width|height)|(top|left))$/,
3185 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3186 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3190 doMethod: function(attr, start, end) {
3191 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3195 setAttribute: function(attr, val, unit) {
3196 if (this.patterns.noNegatives.test(attr)) {
3197 val = (val > 0) ? val : 0;
3200 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3204 getAttribute: function(attr) {
3205 var el = this.getEl();
3206 var val = fly(el).getStyle(attr);
3208 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3209 return parseFloat(val);
3212 var a = this.patterns.offsetAttribute.exec(attr) || [];
3213 var pos = !!( a[3] );
3214 var box = !!( a[2] );
3217 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3218 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3227 getDefaultUnit: function(attr) {
3228 if (this.patterns.defaultUnit.test(attr)) {
3235 animateX : function(callback, scope) {
3236 var f = function() {
3237 this.onComplete.removeListener(f);
3238 if (typeof callback == "function") {
3239 callback.call(scope || this, this);
3242 this.onComplete.addListener(f, this);
3247 setRuntimeAttribute: function(attr) {
3250 var attributes = this.attributes;
3252 this.runtimeAttributes[attr] = {};
3254 var isset = function(prop) {
3255 return (typeof prop !== 'undefined');
3258 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3262 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3265 if (isset(attributes[attr]['to'])) {
3266 end = attributes[attr]['to'];
3267 } else if (isset(attributes[attr]['by'])) {
3268 if (start.constructor == Array) {
3270 for (var i = 0, len = start.length; i < len; ++i) {
3271 end[i] = start[i] + attributes[attr]['by'][i];
3274 end = start + attributes[attr]['by'];
3278 this.runtimeAttributes[attr].start = start;
3279 this.runtimeAttributes[attr].end = end;
3282 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3286 init: function(el, attributes, duration, method) {
3288 var isAnimated = false;
3291 var startTime = null;
3294 var actualFrames = 0;
3297 el = Roo.getDom(el);
3300 this.attributes = attributes || {};
3303 this.duration = duration || 1;
3306 this.method = method || Roo.lib.Easing.easeNone;
3309 this.useSeconds = true;
3312 this.currentFrame = 0;
3315 this.totalFrames = Roo.lib.AnimMgr.fps;
3318 this.getEl = function() {
3323 this.isAnimated = function() {
3328 this.getStartTime = function() {
3332 this.runtimeAttributes = {};
3335 this.animate = function() {
3336 if (this.isAnimated()) {
3340 this.currentFrame = 0;
3342 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3344 Roo.lib.AnimMgr.registerElement(this);
3348 this.stop = function(finish) {
3350 this.currentFrame = this.totalFrames;
3351 this._onTween.fire();
3353 Roo.lib.AnimMgr.stop(this);
3356 var onStart = function() {
3357 this.onStart.fire();
3359 this.runtimeAttributes = {};
3360 for (var attr in this.attributes) {
3361 this.setRuntimeAttribute(attr);
3366 startTime = new Date();
3370 var onTween = function() {
3372 duration: new Date() - this.getStartTime(),
3373 currentFrame: this.currentFrame
3376 data.toString = function() {
3378 'duration: ' + data.duration +
3379 ', currentFrame: ' + data.currentFrame
3383 this.onTween.fire(data);
3385 var runtimeAttributes = this.runtimeAttributes;
3387 for (var attr in runtimeAttributes) {
3388 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3394 var onComplete = function() {
3395 var actual_duration = (new Date() - startTime) / 1000 ;
3398 duration: actual_duration,
3399 frames: actualFrames,
3400 fps: actualFrames / actual_duration
3403 data.toString = function() {
3405 'duration: ' + data.duration +
3406 ', frames: ' + data.frames +
3407 ', fps: ' + data.fps
3413 this.onComplete.fire(data);
3417 this._onStart = new Roo.util.Event(this);
3418 this.onStart = new Roo.util.Event(this);
3419 this.onTween = new Roo.util.Event(this);
3420 this._onTween = new Roo.util.Event(this);
3421 this.onComplete = new Roo.util.Event(this);
3422 this._onComplete = new Roo.util.Event(this);
3423 this._onStart.addListener(onStart);
3424 this._onTween.addListener(onTween);
3425 this._onComplete.addListener(onComplete);
3430 * Portions of this file are based on pieces of Yahoo User Interface Library
3431 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3432 * YUI licensed under the BSD License:
3433 * http://developer.yahoo.net/yui/license.txt
3434 * <script type="text/javascript">
3438 Roo.lib.AnimMgr = new function() {
3455 this.registerElement = function(tween) {
3456 queue[queue.length] = tween;
3458 tween._onStart.fire();
3463 this.unRegister = function(tween, index) {
3464 tween._onComplete.fire();
3465 index = index || getIndex(tween);
3467 queue.splice(index, 1);
3471 if (tweenCount <= 0) {
3477 this.start = function() {
3478 if (thread === null) {
3479 thread = setInterval(this.run, this.delay);
3484 this.stop = function(tween) {
3486 clearInterval(thread);
3488 for (var i = 0, len = queue.length; i < len; ++i) {
3489 if (queue[0].isAnimated()) {
3490 this.unRegister(queue[0], 0);
3499 this.unRegister(tween);
3504 this.run = function() {
3505 for (var i = 0, len = queue.length; i < len; ++i) {
3506 var tween = queue[i];
3507 if (!tween || !tween.isAnimated()) {
3511 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3513 tween.currentFrame += 1;
3515 if (tween.useSeconds) {
3516 correctFrame(tween);
3518 tween._onTween.fire();
3521 Roo.lib.AnimMgr.stop(tween, i);
3526 var getIndex = function(anim) {
3527 for (var i = 0, len = queue.length; i < len; ++i) {
3528 if (queue[i] == anim) {
3536 var correctFrame = function(tween) {
3537 var frames = tween.totalFrames;
3538 var frame = tween.currentFrame;
3539 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3540 var elapsed = (new Date() - tween.getStartTime());
3543 if (elapsed < tween.duration * 1000) {
3544 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3546 tweak = frames - (frame + 1);
3548 if (tweak > 0 && isFinite(tweak)) {
3549 if (tween.currentFrame + tweak >= frames) {
3550 tweak = frames - (frame + 1);
3553 tween.currentFrame += tweak;
3559 * Portions of this file are based on pieces of Yahoo User Interface Library
3560 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3561 * YUI licensed under the BSD License:
3562 * http://developer.yahoo.net/yui/license.txt
3563 * <script type="text/javascript">
3566 Roo.lib.Bezier = new function() {
3568 this.getPosition = function(points, t) {
3569 var n = points.length;
3572 for (var i = 0; i < n; ++i) {
3573 tmp[i] = [points[i][0], points[i][1]];
3576 for (var j = 1; j < n; ++j) {
3577 for (i = 0; i < n - j; ++i) {
3578 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3579 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3583 return [ tmp[0][0], tmp[0][1] ];
3587 * Portions of this file are based on pieces of Yahoo User Interface Library
3588 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3589 * YUI licensed under the BSD License:
3590 * http://developer.yahoo.net/yui/license.txt
3591 * <script type="text/javascript">
3596 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3597 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3600 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3602 var fly = Roo.lib.AnimBase.fly;
3604 var superclass = Y.ColorAnim.superclass;
3605 var proto = Y.ColorAnim.prototype;
3607 proto.toString = function() {
3608 var el = this.getEl();
3609 var id = el.id || el.tagName;
3610 return ("ColorAnim " + id);
3613 proto.patterns.color = /color$/i;
3614 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3615 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3616 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3617 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3620 proto.parseColor = function(s) {
3621 if (s.length == 3) {
3625 var c = this.patterns.hex.exec(s);
3626 if (c && c.length == 4) {
3627 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3630 c = this.patterns.rgb.exec(s);
3631 if (c && c.length == 4) {
3632 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3635 c = this.patterns.hex3.exec(s);
3636 if (c && c.length == 4) {
3637 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3642 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3643 proto.getAttribute = function(attr) {
3644 var el = this.getEl();
3645 if (this.patterns.color.test(attr)) {
3646 var val = fly(el).getStyle(attr);
3648 if (this.patterns.transparent.test(val)) {
3649 var parent = el.parentNode;
3650 val = fly(parent).getStyle(attr);
3652 while (parent && this.patterns.transparent.test(val)) {
3653 parent = parent.parentNode;
3654 val = fly(parent).getStyle(attr);
3655 if (parent.tagName.toUpperCase() == 'HTML') {
3661 val = superclass.getAttribute.call(this, attr);
3666 proto.getAttribute = function(attr) {
3667 var el = this.getEl();
3668 if (this.patterns.color.test(attr)) {
3669 var val = fly(el).getStyle(attr);
3671 if (this.patterns.transparent.test(val)) {
3672 var parent = el.parentNode;
3673 val = fly(parent).getStyle(attr);
3675 while (parent && this.patterns.transparent.test(val)) {
3676 parent = parent.parentNode;
3677 val = fly(parent).getStyle(attr);
3678 if (parent.tagName.toUpperCase() == 'HTML') {
3684 val = superclass.getAttribute.call(this, attr);
3690 proto.doMethod = function(attr, start, end) {
3693 if (this.patterns.color.test(attr)) {
3695 for (var i = 0, len = start.length; i < len; ++i) {
3696 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3699 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3702 val = superclass.doMethod.call(this, attr, start, end);
3708 proto.setRuntimeAttribute = function(attr) {
3709 superclass.setRuntimeAttribute.call(this, attr);
3711 if (this.patterns.color.test(attr)) {
3712 var attributes = this.attributes;
3713 var start = this.parseColor(this.runtimeAttributes[attr].start);
3714 var end = this.parseColor(this.runtimeAttributes[attr].end);
3716 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3717 end = this.parseColor(attributes[attr].by);
3719 for (var i = 0, len = start.length; i < len; ++i) {
3720 end[i] = start[i] + end[i];
3724 this.runtimeAttributes[attr].start = start;
3725 this.runtimeAttributes[attr].end = end;
3731 * Portions of this file are based on pieces of Yahoo User Interface Library
3732 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3733 * YUI licensed under the BSD License:
3734 * http://developer.yahoo.net/yui/license.txt
3735 * <script type="text/javascript">
3741 easeNone: function (t, b, c, d) {
3742 return c * t / d + b;
3746 easeIn: function (t, b, c, d) {
3747 return c * (t /= d) * t + b;
3751 easeOut: function (t, b, c, d) {
3752 return -c * (t /= d) * (t - 2) + b;
3756 easeBoth: function (t, b, c, d) {
3757 if ((t /= d / 2) < 1) {
3758 return c / 2 * t * t + b;
3761 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3765 easeInStrong: function (t, b, c, d) {
3766 return c * (t /= d) * t * t * t + b;
3770 easeOutStrong: function (t, b, c, d) {
3771 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3775 easeBothStrong: function (t, b, c, d) {
3776 if ((t /= d / 2) < 1) {
3777 return c / 2 * t * t * t * t + b;
3780 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3785 elasticIn: function (t, b, c, d, a, p) {
3789 if ((t /= d) == 1) {
3796 if (!a || a < Math.abs(c)) {
3801 var s = p / (2 * Math.PI) * Math.asin(c / a);
3804 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3808 elasticOut: function (t, b, c, d, a, p) {
3812 if ((t /= d) == 1) {
3819 if (!a || a < Math.abs(c)) {
3824 var s = p / (2 * Math.PI) * Math.asin(c / a);
3827 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3831 elasticBoth: function (t, b, c, d, a, p) {
3836 if ((t /= d / 2) == 2) {
3844 if (!a || a < Math.abs(c)) {
3849 var s = p / (2 * Math.PI) * Math.asin(c / a);
3853 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3854 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3856 return a * Math.pow(2, -10 * (t -= 1)) *
3857 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3862 backIn: function (t, b, c, d, s) {
3863 if (typeof s == 'undefined') {
3866 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3870 backOut: function (t, b, c, d, s) {
3871 if (typeof s == 'undefined') {
3874 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3878 backBoth: function (t, b, c, d, s) {
3879 if (typeof s == 'undefined') {
3883 if ((t /= d / 2 ) < 1) {
3884 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3886 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3890 bounceIn: function (t, b, c, d) {
3891 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3895 bounceOut: function (t, b, c, d) {
3896 if ((t /= d) < (1 / 2.75)) {
3897 return c * (7.5625 * t * t) + b;
3898 } else if (t < (2 / 2.75)) {
3899 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3900 } else if (t < (2.5 / 2.75)) {
3901 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3903 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3907 bounceBoth: function (t, b, c, d) {
3909 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3911 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3914 * Portions of this file are based on pieces of Yahoo User Interface Library
3915 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3916 * YUI licensed under the BSD License:
3917 * http://developer.yahoo.net/yui/license.txt
3918 * <script type="text/javascript">
3922 Roo.lib.Motion = function(el, attributes, duration, method) {
3924 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3928 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3932 var superclass = Y.Motion.superclass;
3933 var proto = Y.Motion.prototype;
3935 proto.toString = function() {
3936 var el = this.getEl();
3937 var id = el.id || el.tagName;
3938 return ("Motion " + id);
3941 proto.patterns.points = /^points$/i;
3943 proto.setAttribute = function(attr, val, unit) {
3944 if (this.patterns.points.test(attr)) {
3945 unit = unit || 'px';
3946 superclass.setAttribute.call(this, 'left', val[0], unit);
3947 superclass.setAttribute.call(this, 'top', val[1], unit);
3949 superclass.setAttribute.call(this, attr, val, unit);
3953 proto.getAttribute = function(attr) {
3954 if (this.patterns.points.test(attr)) {
3956 superclass.getAttribute.call(this, 'left'),
3957 superclass.getAttribute.call(this, 'top')
3960 val = superclass.getAttribute.call(this, attr);
3966 proto.doMethod = function(attr, start, end) {
3969 if (this.patterns.points.test(attr)) {
3970 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3971 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3973 val = superclass.doMethod.call(this, attr, start, end);
3978 proto.setRuntimeAttribute = function(attr) {
3979 if (this.patterns.points.test(attr)) {
3980 var el = this.getEl();
3981 var attributes = this.attributes;
3983 var control = attributes['points']['control'] || [];
3987 if (control.length > 0 && !(control[0] instanceof Array)) {
3988 control = [control];
3991 for (i = 0,len = control.length; i < len; ++i) {
3992 tmp[i] = control[i];
3997 Roo.fly(el).position();
3999 if (isset(attributes['points']['from'])) {
4000 Roo.lib.Dom.setXY(el, attributes['points']['from']);
4003 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
4006 start = this.getAttribute('points');
4009 if (isset(attributes['points']['to'])) {
4010 end = translateValues.call(this, attributes['points']['to'], start);
4012 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4013 for (i = 0,len = control.length; i < len; ++i) {
4014 control[i] = translateValues.call(this, control[i], start);
4018 } else if (isset(attributes['points']['by'])) {
4019 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
4021 for (i = 0,len = control.length; i < len; ++i) {
4022 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
4026 this.runtimeAttributes[attr] = [start];
4028 if (control.length > 0) {
4029 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4032 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4035 superclass.setRuntimeAttribute.call(this, attr);
4039 var translateValues = function(val, start) {
4040 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4041 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4046 var isset = function(prop) {
4047 return (typeof prop !== 'undefined');
4051 * Portions of this file are based on pieces of Yahoo User Interface Library
4052 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4053 * YUI licensed under the BSD License:
4054 * http://developer.yahoo.net/yui/license.txt
4055 * <script type="text/javascript">
4059 Roo.lib.Scroll = function(el, attributes, duration, method) {
4061 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4065 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4069 var superclass = Y.Scroll.superclass;
4070 var proto = Y.Scroll.prototype;
4072 proto.toString = function() {
4073 var el = this.getEl();
4074 var id = el.id || el.tagName;
4075 return ("Scroll " + id);
4078 proto.doMethod = function(attr, start, end) {
4081 if (attr == 'scroll') {
4083 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4084 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4088 val = superclass.doMethod.call(this, attr, start, end);
4093 proto.getAttribute = function(attr) {
4095 var el = this.getEl();
4097 if (attr == 'scroll') {
4098 val = [ el.scrollLeft, el.scrollTop ];
4100 val = superclass.getAttribute.call(this, attr);
4106 proto.setAttribute = function(attr, val, unit) {
4107 var el = this.getEl();
4109 if (attr == 'scroll') {
4110 el.scrollLeft = val[0];
4111 el.scrollTop = val[1];
4113 superclass.setAttribute.call(this, attr, val, unit);
4119 * Ext JS Library 1.1.1
4120 * Copyright(c) 2006-2007, Ext JS, LLC.
4122 * Originally Released Under LGPL - original licence link has changed is not relivant.
4125 * <script type="text/javascript">
4129 // nasty IE9 hack - what a pile of crap that is..
4131 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4132 Range.prototype.createContextualFragment = function (html) {
4133 var doc = window.document;
4134 var container = doc.createElement("div");
4135 container.innerHTML = html;
4136 var frag = doc.createDocumentFragment(), n;
4137 while ((n = container.firstChild)) {
4138 frag.appendChild(n);
4145 * @class Roo.DomHelper
4146 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4147 * 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>.
4150 Roo.DomHelper = function(){
4151 var tempTableEl = null;
4152 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4153 var tableRe = /^table|tbody|tr|td$/i;
4155 // build as innerHTML where available
4157 var createHtml = function(o){
4158 if(typeof o == 'string'){
4167 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") { continue; }
4168 if(attr == "style"){
4170 if(typeof s == "function"){
4173 if(typeof s == "string"){
4174 b += ' style="' + s + '"';
4175 }else if(typeof s == "object"){
4178 if(typeof s[key] != "function"){
4179 b += key + ":" + s[key] + ";";
4186 b += ' class="' + o["cls"] + '"';
4187 }else if(attr == "htmlFor"){
4188 b += ' for="' + o["htmlFor"] + '"';
4190 b += " " + attr + '="' + o[attr] + '"';
4194 if(emptyTags.test(o.tag)){
4198 var cn = o.children || o.cn;
4200 //http://bugs.kde.org/show_bug.cgi?id=71506
4201 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4202 for(var i = 0, len = cn.length; i < len; i++) {
4203 b += createHtml(cn[i], b);
4206 b += createHtml(cn, b);
4212 b += "</" + o.tag + ">";
4219 var createDom = function(o, parentNode){
4221 // defininition craeted..
4223 if (o.ns && o.ns != 'html') {
4225 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4226 xmlns[o.ns] = o.xmlns;
4229 if (typeof(xmlns[o.ns]) == 'undefined') {
4230 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4236 if (typeof(o) == 'string') {
4237 return parentNode.appendChild(document.createTextNode(o));
4239 o.tag = o.tag || div;
4240 if (o.ns && Roo.isIE) {
4242 o.tag = o.ns + ':' + o.tag;
4245 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4246 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4249 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4250 attr == "style" || typeof o[attr] == "function") { continue; }
4252 if(attr=="cls" && Roo.isIE){
4253 el.className = o["cls"];
4255 if(useSet) { el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);}
4261 Roo.DomHelper.applyStyles(el, o.style);
4262 var cn = o.children || o.cn;
4264 //http://bugs.kde.org/show_bug.cgi?id=71506
4265 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4266 for(var i = 0, len = cn.length; i < len; i++) {
4267 createDom(cn[i], el);
4274 el.innerHTML = o.html;
4277 parentNode.appendChild(el);
4282 var ieTable = function(depth, s, h, e){
4283 tempTableEl.innerHTML = [s, h, e].join('');
4284 var i = -1, el = tempTableEl;
4291 // kill repeat to save bytes
4295 tbe = '</tbody>'+te,
4301 * Nasty code for IE's broken table implementation
4303 var insertIntoTable = function(tag, where, el, html){
4305 tempTableEl = document.createElement('div');
4310 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4313 if(where == 'beforebegin'){
4317 before = el.nextSibling;
4320 node = ieTable(4, trs, html, tre);
4322 else if(tag == 'tr'){
4323 if(where == 'beforebegin'){
4326 node = ieTable(3, tbs, html, tbe);
4327 } else if(where == 'afterend'){
4328 before = el.nextSibling;
4330 node = ieTable(3, tbs, html, tbe);
4331 } else{ // INTO a TR
4332 if(where == 'afterbegin'){
4333 before = el.firstChild;
4335 node = ieTable(4, trs, html, tre);
4337 } else if(tag == 'tbody'){
4338 if(where == 'beforebegin'){
4341 node = ieTable(2, ts, html, te);
4342 } else if(where == 'afterend'){
4343 before = el.nextSibling;
4345 node = ieTable(2, ts, html, te);
4347 if(where == 'afterbegin'){
4348 before = el.firstChild;
4350 node = ieTable(3, tbs, html, tbe);
4353 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4356 if(where == 'afterbegin'){
4357 before = el.firstChild;
4359 node = ieTable(2, ts, html, te);
4361 el.insertBefore(node, before);
4366 /** True to force the use of DOM instead of html fragments @type Boolean */
4370 * Returns the markup for the passed Element(s) config
4371 * @param {Object} o The Dom object spec (and children)
4374 markup : function(o){
4375 return createHtml(o);
4379 * Applies a style specification to an element
4380 * @param {String/HTMLElement} el The element to apply styles to
4381 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4382 * a function which returns such a specification.
4384 applyStyles : function(el, styles){
4387 if(typeof styles == "string"){
4388 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4390 while ((matches = re.exec(styles)) != null){
4391 el.setStyle(matches[1], matches[2]);
4393 }else if (typeof styles == "object"){
4394 for (var style in styles){
4395 el.setStyle(style, styles[style]);
4397 }else if (typeof styles == "function"){
4398 Roo.DomHelper.applyStyles(el, styles.call());
4404 * Inserts an HTML fragment into the Dom
4405 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4406 * @param {HTMLElement} el The context element
4407 * @param {String} html The HTML fragmenet
4408 * @return {HTMLElement} The new node
4410 insertHtml : function(where, el, html){
4411 where = where.toLowerCase();
4412 if(el.insertAdjacentHTML){
4413 if(tableRe.test(el.tagName)){
4415 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4421 el.insertAdjacentHTML('BeforeBegin', html);
4422 return el.previousSibling;
4424 el.insertAdjacentHTML('AfterBegin', html);
4425 return el.firstChild;
4427 el.insertAdjacentHTML('BeforeEnd', html);
4428 return el.lastChild;
4430 el.insertAdjacentHTML('AfterEnd', html);
4431 return el.nextSibling;
4433 throw 'Illegal insertion point -> "' + where + '"';
4435 var range = el.ownerDocument.createRange();
4439 range.setStartBefore(el);
4440 frag = range.createContextualFragment(html);
4441 el.parentNode.insertBefore(frag, el);
4442 return el.previousSibling;
4445 range.setStartBefore(el.firstChild);
4446 frag = range.createContextualFragment(html);
4447 el.insertBefore(frag, el.firstChild);
4448 return el.firstChild;
4450 el.innerHTML = html;
4451 return el.firstChild;
4455 range.setStartAfter(el.lastChild);
4456 frag = range.createContextualFragment(html);
4457 el.appendChild(frag);
4458 return el.lastChild;
4460 el.innerHTML = html;
4461 return el.lastChild;
4464 range.setStartAfter(el);
4465 frag = range.createContextualFragment(html);
4466 el.parentNode.insertBefore(frag, el.nextSibling);
4467 return el.nextSibling;
4469 throw 'Illegal insertion point -> "' + where + '"';
4473 * Creates new Dom element(s) and inserts them before el
4474 * @param {String/HTMLElement/Element} el The context element
4475 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4476 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4477 * @return {HTMLElement/Roo.Element} The new node
4479 insertBefore : function(el, o, returnElement){
4480 return this.doInsert(el, o, returnElement, "beforeBegin");
4484 * Creates new Dom element(s) and inserts them after el
4485 * @param {String/HTMLElement/Element} el The context element
4486 * @param {Object} o The Dom object spec (and children)
4487 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4488 * @return {HTMLElement/Roo.Element} The new node
4490 insertAfter : function(el, o, returnElement){
4491 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4495 * Creates new Dom element(s) and inserts them as the first child of el
4496 * @param {String/HTMLElement/Element} el The context element
4497 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4498 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4499 * @return {HTMLElement/Roo.Element} The new node
4501 insertFirst : function(el, o, returnElement){
4502 return this.doInsert(el, o, returnElement, "afterBegin");
4506 doInsert : function(el, o, returnElement, pos, sibling){
4507 el = Roo.getDom(el);
4509 if(this.useDom || o.ns){
4510 newNode = createDom(o, null);
4511 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4513 var html = createHtml(o);
4514 newNode = this.insertHtml(pos, el, html);
4516 return returnElement ? Roo.get(newNode, true) : newNode;
4520 * Creates new Dom element(s) and appends them to el
4521 * @param {String/HTMLElement/Element} el The context element
4522 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4523 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4524 * @return {HTMLElement/Roo.Element} The new node
4526 append : function(el, o, returnElement){
4527 el = Roo.getDom(el);
4529 if(this.useDom || o.ns){
4530 newNode = createDom(o, null);
4531 el.appendChild(newNode);
4533 var html = createHtml(o);
4534 newNode = this.insertHtml("beforeEnd", el, html);
4536 return returnElement ? Roo.get(newNode, true) : newNode;
4540 * Creates new Dom element(s) and overwrites the contents of el with them
4541 * @param {String/HTMLElement/Element} el The context element
4542 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4543 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4544 * @return {HTMLElement/Roo.Element} The new node
4546 overwrite : function(el, o, returnElement){
4547 el = Roo.getDom(el);
4550 while (el.childNodes.length) {
4551 el.removeChild(el.firstChild);
4555 el.innerHTML = createHtml(o);
4558 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4562 * Creates a new Roo.DomHelper.Template from the Dom object spec
4563 * @param {Object} o The Dom object spec (and children)
4564 * @return {Roo.DomHelper.Template} The new template
4566 createTemplate : function(o){
4567 var html = createHtml(o);
4568 return new Roo.Template(html);
4574 * Ext JS Library 1.1.1
4575 * Copyright(c) 2006-2007, Ext JS, LLC.
4577 * Originally Released Under LGPL - original licence link has changed is not relivant.
4580 * <script type="text/javascript">
4584 * @class Roo.Template
4585 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4586 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4589 var t = new Roo.Template({
4590 html : '<div name="{id}">' +
4591 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4593 myformat: function (value, allValues) {
4594 return 'XX' + value;
4597 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4599 * For more information see this blog post with examples:
4600 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4601 - Create Elements using DOM, HTML fragments and Templates</a>.
4603 * @param {Object} cfg - Configuration object.
4605 Roo.Template = function(cfg){
4607 if(cfg instanceof Array){
4609 }else if(arguments.length > 1){
4610 cfg = Array.prototype.join.call(arguments, "");
4614 if (typeof(cfg) == 'object') {
4625 Roo.Template.prototype = {
4628 * @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..
4629 * it should be fixed so that template is observable...
4633 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4637 * Returns an HTML fragment of this template with the specified values applied.
4638 * @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'})
4639 * @return {String} The HTML fragment
4641 applyTemplate : function(values){
4645 return this.compiled(values);
4647 var useF = this.disableFormats !== true;
4648 var fm = Roo.util.Format, tpl = this;
4649 var fn = function(m, name, format, args){
4651 if(format.substr(0, 5) == "this."){
4652 return tpl.call(format.substr(5), values[name], values);
4655 // quoted values are required for strings in compiled templates,
4656 // but for non compiled we need to strip them
4657 // quoted reversed for jsmin
4658 var re = /^\s*['"](.*)["']\s*$/;
4659 args = args.split(',');
4660 for(var i = 0, len = args.length; i < len; i++){
4661 args[i] = args[i].replace(re, "$1");
4663 args = [values[name]].concat(args);
4665 args = [values[name]];
4667 return fm[format].apply(fm, args);
4670 return values[name] !== undefined ? values[name] : "";
4673 return this.html.replace(this.re, fn);
4691 this.loading = true;
4692 this.compiled = false;
4694 var cx = new Roo.data.Connection();
4698 success : function (response) {
4700 _t.html = response.responseText;
4704 failure : function(response) {
4705 Roo.log("Template failed to load from " + _t.url);
4712 * Sets the HTML used as the template and optionally compiles it.
4713 * @param {String} html
4714 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4715 * @return {Roo.Template} this
4717 set : function(html, compile){
4719 this.compiled = null;
4727 * True to disable format functions (defaults to false)
4730 disableFormats : false,
4733 * The regular expression used to match template variables
4737 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4740 * Compiles the template into an internal function, eliminating the RegEx overhead.
4741 * @return {Roo.Template} this
4743 compile : function(){
4744 var fm = Roo.util.Format;
4745 var useF = this.disableFormats !== true;
4746 var sep = Roo.isGecko ? "+" : ",";
4747 var fn = function(m, name, format, args){
4749 args = args ? ',' + args : "";
4750 if(format.substr(0, 5) != "this."){
4751 format = "fm." + format + '(';
4753 format = 'this.call("'+ format.substr(5) + '", ';
4757 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4759 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4762 // branched to use + in gecko and [].join() in others
4764 body = "this.compiled = function(values){ return '" +
4765 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4768 body = ["this.compiled = function(values){ return ['"];
4769 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4770 body.push("'].join('');};");
4771 body = body.join('');
4781 // private function used to call members
4782 call : function(fnName, value, allValues){
4783 return this[fnName](value, allValues);
4787 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4788 * @param {String/HTMLElement/Roo.Element} el The context element
4789 * @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'})
4790 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4791 * @return {HTMLElement/Roo.Element} The new node or Element
4793 insertFirst: function(el, values, returnElement){
4794 return this.doInsert('afterBegin', el, values, returnElement);
4798 * Applies the supplied values to the template and inserts the new node(s) before el.
4799 * @param {String/HTMLElement/Roo.Element} el The context element
4800 * @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'})
4801 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4802 * @return {HTMLElement/Roo.Element} The new node or Element
4804 insertBefore: function(el, values, returnElement){
4805 return this.doInsert('beforeBegin', el, values, returnElement);
4809 * Applies the supplied values to the template and inserts the new node(s) after el.
4810 * @param {String/HTMLElement/Roo.Element} el The context element
4811 * @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'})
4812 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4813 * @return {HTMLElement/Roo.Element} The new node or Element
4815 insertAfter : function(el, values, returnElement){
4816 return this.doInsert('afterEnd', el, values, returnElement);
4820 * Applies the supplied values to the template and appends the new node(s) to el.
4821 * @param {String/HTMLElement/Roo.Element} el The context element
4822 * @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'})
4823 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4824 * @return {HTMLElement/Roo.Element} The new node or Element
4826 append : function(el, values, returnElement){
4827 return this.doInsert('beforeEnd', el, values, returnElement);
4830 doInsert : function(where, el, values, returnEl){
4831 el = Roo.getDom(el);
4832 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4833 return returnEl ? Roo.get(newNode, true) : newNode;
4837 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4838 * @param {String/HTMLElement/Roo.Element} el The context element
4839 * @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'})
4840 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4841 * @return {HTMLElement/Roo.Element} The new node or Element
4843 overwrite : function(el, values, returnElement){
4844 el = Roo.getDom(el);
4845 el.innerHTML = this.applyTemplate(values);
4846 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4850 * Alias for {@link #applyTemplate}
4853 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4856 Roo.DomHelper.Template = Roo.Template;
4859 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4860 * @param {String/HTMLElement} el A DOM element or its id
4861 * @returns {Roo.Template} The created template
4864 Roo.Template.from = function(el){
4865 el = Roo.getDom(el);
4866 return new Roo.Template(el.value || el.innerHTML);
4869 * Ext JS Library 1.1.1
4870 * Copyright(c) 2006-2007, Ext JS, LLC.
4872 * Originally Released Under LGPL - original licence link has changed is not relivant.
4875 * <script type="text/javascript">
4880 * This is code is also distributed under MIT license for use
4881 * with jQuery and prototype JavaScript libraries.
4884 * @class Roo.DomQuery
4885 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).
4887 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>
4890 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.
4892 <h4>Element Selectors:</h4>
4894 <li> <b>*</b> any element</li>
4895 <li> <b>E</b> an element with the tag E</li>
4896 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4897 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4898 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4899 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4901 <h4>Attribute Selectors:</h4>
4902 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4904 <li> <b>E[foo]</b> has an attribute "foo"</li>
4905 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4906 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4907 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4908 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4909 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4910 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4912 <h4>Pseudo Classes:</h4>
4914 <li> <b>E:first-child</b> E is the first child of its parent</li>
4915 <li> <b>E:last-child</b> E is the last child of its parent</li>
4916 <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>
4917 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4918 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4919 <li> <b>E:only-child</b> E is the only child of its parent</li>
4920 <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>
4921 <li> <b>E:first</b> the first E in the resultset</li>
4922 <li> <b>E:last</b> the last E in the resultset</li>
4923 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4924 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4925 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4926 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4927 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4928 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4929 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4930 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4931 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4933 <h4>CSS Value Selectors:</h4>
4935 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4936 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4937 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4938 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4939 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4940 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4944 Roo.DomQuery = function(){
4945 var cache = {}, simpleCache = {}, valueCache = {};
4946 var nonSpace = /\S/;
4947 var trimRe = /^\s+|\s+$/g;
4948 var tplRe = /\{(\d+)\}/g;
4949 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4950 var tagTokenRe = /^(#)?([\w-\*]+)/;
4951 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4953 function child(p, index){
4955 var n = p.firstChild;
4957 if(n.nodeType == 1){
4968 while((n = n.nextSibling) && n.nodeType != 1);
4973 while((n = n.previousSibling) && n.nodeType != 1);
4977 function children(d){
4978 var n = d.firstChild, ni = -1;
4980 var nx = n.nextSibling;
4981 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4991 function byClassName(c, a, v){
4995 var r = [], ri = -1, cn;
4996 for(var i = 0, ci; ci = c[i]; i++){
4997 if((' '+ci.className+' ').indexOf(v) != -1){
5004 function attrValue(n, attr){
5005 if(!n.tagName && typeof n.length != "undefined"){
5014 if(attr == "class" || attr == "className"){
5017 return n.getAttribute(attr) || n[attr];
5021 function getNodes(ns, mode, tagName){
5022 var result = [], ri = -1, cs;
5026 tagName = tagName || "*";
5027 if(typeof ns.getElementsByTagName != "undefined"){
5031 for(var i = 0, ni; ni = ns[i]; i++){
5032 cs = ni.getElementsByTagName(tagName);
5033 for(var j = 0, ci; ci = cs[j]; j++){
5037 }else if(mode == "/" || mode == ">"){
5038 var utag = tagName.toUpperCase();
5039 for(var i = 0, ni, cn; ni = ns[i]; i++){
5040 cn = ni.children || ni.childNodes;
5041 for(var j = 0, cj; cj = cn[j]; j++){
5042 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5047 }else if(mode == "+"){
5048 var utag = tagName.toUpperCase();
5049 for(var i = 0, n; n = ns[i]; i++){
5050 while((n = n.nextSibling) && n.nodeType != 1);
5051 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5055 }else if(mode == "~"){
5056 for(var i = 0, n; n = ns[i]; i++){
5057 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5066 function concat(a, b){
5070 for(var i = 0, l = b.length; i < l; i++){
5076 function byTag(cs, tagName){
5077 if(cs.tagName || cs == document){
5083 var r = [], ri = -1;
5084 tagName = tagName.toLowerCase();
5085 for(var i = 0, ci; ci = cs[i]; i++){
5086 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5093 function byId(cs, attr, id){
5094 if(cs.tagName || cs == document){
5100 var r = [], ri = -1;
5101 for(var i = 0,ci; ci = cs[i]; i++){
5102 if(ci && ci.id == id){
5110 function byAttribute(cs, attr, value, op, custom){
5111 var r = [], ri = -1, st = custom=="{";
5112 var f = Roo.DomQuery.operators[op];
5113 for(var i = 0, ci; ci = cs[i]; i++){
5116 a = Roo.DomQuery.getStyle(ci, attr);
5118 else if(attr == "class" || attr == "className"){
5120 }else if(attr == "for"){
5122 }else if(attr == "href"){
5123 a = ci.getAttribute("href", 2);
5125 a = ci.getAttribute(attr);
5127 if((f && f(a, value)) || (!f && a)){
5134 function byPseudo(cs, name, value){
5135 return Roo.DomQuery.pseudos[name](cs, value);
5138 // This is for IE MSXML which does not support expandos.
5139 // IE runs the same speed using setAttribute, however FF slows way down
5140 // and Safari completely fails so they need to continue to use expandos.
5141 var isIE = window.ActiveXObject ? true : false;
5143 // this eval is stop the compressor from
5144 // renaming the variable to something shorter
5146 /** eval:var:batch */
5151 function nodupIEXml(cs){
5153 cs[0].setAttribute("_nodup", d);
5155 for(var i = 1, len = cs.length; i < len; i++){
5157 if(!c.getAttribute("_nodup") != d){
5158 c.setAttribute("_nodup", d);
5162 for(var i = 0, len = cs.length; i < len; i++){
5163 cs[i].removeAttribute("_nodup");
5172 var len = cs.length, c, i, r = cs, cj, ri = -1;
5173 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5176 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5177 return nodupIEXml(cs);
5181 for(i = 1; c = cs[i]; i++){
5186 for(var j = 0; j < i; j++){
5189 for(j = i+1; cj = cs[j]; j++){
5201 function quickDiffIEXml(c1, c2){
5203 for(var i = 0, len = c1.length; i < len; i++){
5204 c1[i].setAttribute("_qdiff", d);
5207 for(var i = 0, len = c2.length; i < len; i++){
5208 if(c2[i].getAttribute("_qdiff") != d){
5209 r[r.length] = c2[i];
5212 for(var i = 0, len = c1.length; i < len; i++){
5213 c1[i].removeAttribute("_qdiff");
5218 function quickDiff(c1, c2){
5219 var len1 = c1.length;
5223 if(isIE && c1[0].selectSingleNode){
5224 return quickDiffIEXml(c1, c2);
5227 for(var i = 0; i < len1; i++){
5231 for(var i = 0, len = c2.length; i < len; i++){
5232 if(c2[i]._qdiff != d){
5233 r[r.length] = c2[i];
5239 function quickId(ns, mode, root, id){
5241 var d = root.ownerDocument || root;
5242 return d.getElementById(id);
5244 ns = getNodes(ns, mode, "*");
5245 return byId(ns, null, id);
5249 getStyle : function(el, name){
5250 return Roo.fly(el).getStyle(name);
5253 * Compiles a selector/xpath query into a reusable function. The returned function
5254 * takes one parameter "root" (optional), which is the context node from where the query should start.
5255 * @param {String} selector The selector/xpath query
5256 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5257 * @return {Function}
5259 compile : function(path, type){
5260 type = type || "select";
5262 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5263 var q = path, mode, lq;
5264 var tk = Roo.DomQuery.matchers;
5265 var tklen = tk.length;
5268 // accept leading mode switch
5269 var lmode = q.match(modeRe);
5270 if(lmode && lmode[1]){
5271 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5272 q = q.replace(lmode[1], "");
5274 // strip leading slashes
5275 while(path.substr(0, 1)=="/"){
5276 path = path.substr(1);
5279 while(q && lq != q){
5281 var tm = q.match(tagTokenRe);
5282 if(type == "select"){
5285 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5287 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5289 q = q.replace(tm[0], "");
5290 }else if(q.substr(0, 1) != '@'){
5291 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5296 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5298 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5300 q = q.replace(tm[0], "");
5303 while(!(mm = q.match(modeRe))){
5304 var matched = false;
5305 for(var j = 0; j < tklen; j++){
5307 var m = q.match(t.re);
5309 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5312 q = q.replace(m[0], "");
5317 // prevent infinite loop on bad selector
5319 throw 'Error parsing selector, parsing failed at "' + q + '"';
5323 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5324 q = q.replace(mm[1], "");
5327 fn[fn.length] = "return nodup(n);\n}";
5330 * list of variables that need from compression as they are used by eval.
5340 * eval:var:byClassName
5342 * eval:var:byAttribute
5343 * eval:var:attrValue
5351 * Selects a group of elements.
5352 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5353 * @param {Node} root (optional) The start of the query (defaults to document).
5356 select : function(path, root, type){
5357 if(!root || root == document){
5360 if(typeof root == "string"){
5361 root = document.getElementById(root);
5363 var paths = path.split(",");
5365 for(var i = 0, len = paths.length; i < len; i++){
5366 var p = paths[i].replace(trimRe, "");
5368 cache[p] = Roo.DomQuery.compile(p);
5370 throw p + " is not a valid selector";
5373 var result = cache[p](root);
5374 if(result && result != document){
5375 results = results.concat(result);
5378 if(paths.length > 1){
5379 return nodup(results);
5385 * Selects a single element.
5386 * @param {String} selector The selector/xpath query
5387 * @param {Node} root (optional) The start of the query (defaults to document).
5390 selectNode : function(path, root){
5391 return Roo.DomQuery.select(path, root)[0];
5395 * Selects the value of a node, optionally replacing null with the defaultValue.
5396 * @param {String} selector The selector/xpath query
5397 * @param {Node} root (optional) The start of the query (defaults to document).
5398 * @param {String} defaultValue
5400 selectValue : function(path, root, defaultValue){
5401 path = path.replace(trimRe, "");
5402 if(!valueCache[path]){
5403 valueCache[path] = Roo.DomQuery.compile(path, "select");
5405 var n = valueCache[path](root);
5406 n = n[0] ? n[0] : n;
5407 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5408 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5412 * Selects the value of a node, parsing integers and floats.
5413 * @param {String} selector The selector/xpath query
5414 * @param {Node} root (optional) The start of the query (defaults to document).
5415 * @param {Number} defaultValue
5418 selectNumber : function(path, root, defaultValue){
5419 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5420 return parseFloat(v);
5424 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5425 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5426 * @param {String} selector The simple selector to test
5429 is : function(el, ss){
5430 if(typeof el == "string"){
5431 el = document.getElementById(el);
5433 var isArray = (el instanceof Array);
5434 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5435 return isArray ? (result.length == el.length) : (result.length > 0);
5439 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5440 * @param {Array} el An array of elements to filter
5441 * @param {String} selector The simple selector to test
5442 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5443 * the selector instead of the ones that match
5446 filter : function(els, ss, nonMatches){
5447 ss = ss.replace(trimRe, "");
5448 if(!simpleCache[ss]){
5449 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5451 var result = simpleCache[ss](els);
5452 return nonMatches ? quickDiff(result, els) : result;
5456 * Collection of matching regular expressions and code snippets.
5460 select: 'n = byClassName(n, null, " {1} ");'
5462 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5463 select: 'n = byPseudo(n, "{1}", "{2}");'
5465 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5466 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5469 select: 'n = byId(n, null, "{1}");'
5472 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5477 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5478 * 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, > <.
5481 "=" : function(a, v){
5484 "!=" : function(a, v){
5487 "^=" : function(a, v){
5488 return a && a.substr(0, v.length) == v;
5490 "$=" : function(a, v){
5491 return a && a.substr(a.length-v.length) == v;
5493 "*=" : function(a, v){
5494 return a && a.indexOf(v) !== -1;
5496 "%=" : function(a, v){
5497 return (a % v) == 0;
5499 "|=" : function(a, v){
5500 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5502 "~=" : function(a, v){
5503 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5508 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5509 * and the argument (if any) supplied in the selector.
5512 "first-child" : function(c){
5513 var r = [], ri = -1, n;
5514 for(var i = 0, ci; ci = n = c[i]; i++){
5515 while((n = n.previousSibling) && n.nodeType != 1);
5523 "last-child" : function(c){
5524 var r = [], ri = -1, n;
5525 for(var i = 0, ci; ci = n = c[i]; i++){
5526 while((n = n.nextSibling) && n.nodeType != 1);
5534 "nth-child" : function(c, a) {
5535 var r = [], ri = -1;
5536 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5537 var f = (m[1] || 1) - 0, l = m[2] - 0;
5538 for(var i = 0, n; n = c[i]; i++){
5539 var pn = n.parentNode;
5540 if (batch != pn._batch) {
5542 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5543 if(cn.nodeType == 1){
5550 if (l == 0 || n.nodeIndex == l){
5553 } else if ((n.nodeIndex + l) % f == 0){
5561 "only-child" : function(c){
5562 var r = [], ri = -1;;
5563 for(var i = 0, ci; ci = c[i]; i++){
5564 if(!prev(ci) && !next(ci)){
5571 "empty" : function(c){
5572 var r = [], ri = -1;
5573 for(var i = 0, ci; ci = c[i]; i++){
5574 var cns = ci.childNodes, j = 0, cn, empty = true;
5577 if(cn.nodeType == 1 || cn.nodeType == 3){
5589 "contains" : function(c, v){
5590 var r = [], ri = -1;
5591 for(var i = 0, ci; ci = c[i]; i++){
5592 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5599 "nodeValue" : function(c, v){
5600 var r = [], ri = -1;
5601 for(var i = 0, ci; ci = c[i]; i++){
5602 if(ci.firstChild && ci.firstChild.nodeValue == v){
5609 "checked" : function(c){
5610 var r = [], ri = -1;
5611 for(var i = 0, ci; ci = c[i]; i++){
5612 if(ci.checked == true){
5619 "not" : function(c, ss){
5620 return Roo.DomQuery.filter(c, ss, true);
5623 "odd" : function(c){
5624 return this["nth-child"](c, "odd");
5627 "even" : function(c){
5628 return this["nth-child"](c, "even");
5631 "nth" : function(c, a){
5632 return c[a-1] || [];
5635 "first" : function(c){
5639 "last" : function(c){
5640 return c[c.length-1] || [];
5643 "has" : function(c, ss){
5644 var s = Roo.DomQuery.select;
5645 var r = [], ri = -1;
5646 for(var i = 0, ci; ci = c[i]; i++){
5647 if(s(ss, ci).length > 0){
5654 "next" : function(c, ss){
5655 var is = Roo.DomQuery.is;
5656 var r = [], ri = -1;
5657 for(var i = 0, ci; ci = c[i]; i++){
5666 "prev" : function(c, ss){
5667 var is = Roo.DomQuery.is;
5668 var r = [], ri = -1;
5669 for(var i = 0, ci; ci = c[i]; i++){
5682 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5683 * @param {String} path The selector/xpath query
5684 * @param {Node} root (optional) The start of the query (defaults to document).
5689 Roo.query = Roo.DomQuery.select;
5692 * Ext JS Library 1.1.1
5693 * Copyright(c) 2006-2007, Ext JS, LLC.
5695 * Originally Released Under LGPL - original licence link has changed is not relivant.
5698 * <script type="text/javascript">
5702 * @class Roo.util.Observable
5703 * Base class that provides a common interface for publishing events. Subclasses are expected to
5704 * to have a property "events" with all the events defined.<br>
5707 Employee = function(name){
5714 Roo.extend(Employee, Roo.util.Observable);
5716 * @param {Object} config properties to use (incuding events / listeners)
5719 Roo.util.Observable = function(cfg){
5722 this.addEvents(cfg.events || {});
5724 delete cfg.events; // make sure
5727 Roo.apply(this, cfg);
5730 this.on(this.listeners);
5731 delete this.listeners;
5734 Roo.util.Observable.prototype = {
5736 * @cfg {Object} listeners list of events and functions to call for this object,
5740 'click' : function(e) {
5750 * Fires the specified event with the passed parameters (minus the event name).
5751 * @param {String} eventName
5752 * @param {Object...} args Variable number of parameters are passed to handlers
5753 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5755 fireEvent : function(){
5756 var ce = this.events[arguments[0].toLowerCase()];
5757 if(typeof ce == "object"){
5758 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5765 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5768 * Appends an event handler to this component
5769 * @param {String} eventName The type of event to listen for
5770 * @param {Function} handler The method the event invokes
5771 * @param {Object} scope (optional) The scope in which to execute the handler
5772 * function. The handler function's "this" context.
5773 * @param {Object} options (optional) An object containing handler configuration
5774 * properties. This may contain any of the following properties:<ul>
5775 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5776 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5777 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5778 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5779 * by the specified number of milliseconds. If the event fires again within that time, the original
5780 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5783 * <b>Combining Options</b><br>
5784 * Using the options argument, it is possible to combine different types of listeners:<br>
5786 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5788 el.on('click', this.onClick, this, {
5795 * <b>Attaching multiple handlers in 1 call</b><br>
5796 * The method also allows for a single argument to be passed which is a config object containing properties
5797 * which specify multiple handlers.
5806 fn: this.onMouseOver,
5810 fn: this.onMouseOut,
5816 * Or a shorthand syntax which passes the same scope object to all handlers:
5819 'click': this.onClick,
5820 'mouseover': this.onMouseOver,
5821 'mouseout': this.onMouseOut,
5826 addListener : function(eventName, fn, scope, o){
5827 if(typeof eventName == "object"){
5830 if(this.filterOptRe.test(e)){
5833 if(typeof o[e] == "function"){
5835 this.addListener(e, o[e], o.scope, o);
5837 // individual options
5838 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5843 o = (!o || typeof o == "boolean") ? {} : o;
5844 eventName = eventName.toLowerCase();
5845 var ce = this.events[eventName] || true;
5846 if(typeof ce == "boolean"){
5847 ce = new Roo.util.Event(this, eventName);
5848 this.events[eventName] = ce;
5850 ce.addListener(fn, scope, o);
5854 * Removes a listener
5855 * @param {String} eventName The type of event to listen for
5856 * @param {Function} handler The handler to remove
5857 * @param {Object} scope (optional) The scope (this object) for the handler
5859 removeListener : function(eventName, fn, scope){
5860 var ce = this.events[eventName.toLowerCase()];
5861 if(typeof ce == "object"){
5862 ce.removeListener(fn, scope);
5867 * Removes all listeners for this object
5869 purgeListeners : function(){
5870 for(var evt in this.events){
5871 if(typeof this.events[evt] == "object"){
5872 this.events[evt].clearListeners();
5877 relayEvents : function(o, events){
5878 var createHandler = function(ename){
5880 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5883 for(var i = 0, len = events.length; i < len; i++){
5884 var ename = events[i];
5885 if(!this.events[ename]){ this.events[ename] = true; };
5886 o.on(ename, createHandler(ename), this);
5891 * Used to define events on this Observable
5892 * @param {Object} object The object with the events defined
5894 addEvents : function(o){
5898 Roo.applyIf(this.events, o);
5902 * Checks to see if this object has any listeners for a specified event
5903 * @param {String} eventName The name of the event to check for
5904 * @return {Boolean} True if the event is being listened for, else false
5906 hasListener : function(eventName){
5907 var e = this.events[eventName];
5908 return typeof e == "object" && e.listeners.length > 0;
5912 * Appends an event handler to this element (shorthand for addListener)
5913 * @param {String} eventName The type of event to listen for
5914 * @param {Function} handler The method the event invokes
5915 * @param {Object} scope (optional) The scope in which to execute the handler
5916 * function. The handler function's "this" context.
5917 * @param {Object} options (optional)
5920 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5922 * Removes a listener (shorthand for removeListener)
5923 * @param {String} eventName The type of event to listen for
5924 * @param {Function} handler The handler to remove
5925 * @param {Object} scope (optional) The scope (this object) for the handler
5928 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5931 * Starts capture on the specified Observable. All events will be passed
5932 * to the supplied function with the event name + standard signature of the event
5933 * <b>before</b> the event is fired. If the supplied function returns false,
5934 * the event will not fire.
5935 * @param {Observable} o The Observable to capture
5936 * @param {Function} fn The function to call
5937 * @param {Object} scope (optional) The scope (this object) for the fn
5940 Roo.util.Observable.capture = function(o, fn, scope){
5941 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5945 * Removes <b>all</b> added captures from the Observable.
5946 * @param {Observable} o The Observable to release
5949 Roo.util.Observable.releaseCapture = function(o){
5950 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5955 var createBuffered = function(h, o, scope){
5956 var task = new Roo.util.DelayedTask();
5958 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5962 var createSingle = function(h, e, fn, scope){
5964 e.removeListener(fn, scope);
5965 return h.apply(scope, arguments);
5969 var createDelayed = function(h, o, scope){
5971 var args = Array.prototype.slice.call(arguments, 0);
5972 setTimeout(function(){
5973 h.apply(scope, args);
5978 Roo.util.Event = function(obj, name){
5981 this.listeners = [];
5984 Roo.util.Event.prototype = {
5985 addListener : function(fn, scope, options){
5986 var o = options || {};
5987 scope = scope || this.obj;
5988 if(!this.isListening(fn, scope)){
5989 var l = {fn: fn, scope: scope, options: o};
5992 h = createDelayed(h, o, scope);
5995 h = createSingle(h, this, fn, scope);
5998 h = createBuffered(h, o, scope);
6001 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
6002 this.listeners.push(l);
6004 this.listeners = this.listeners.slice(0);
6005 this.listeners.push(l);
6010 findListener : function(fn, scope){
6011 scope = scope || this.obj;
6012 var ls = this.listeners;
6013 for(var i = 0, len = ls.length; i < len; i++){
6015 if(l.fn == fn && l.scope == scope){
6022 isListening : function(fn, scope){
6023 return this.findListener(fn, scope) != -1;
6026 removeListener : function(fn, scope){
6028 if((index = this.findListener(fn, scope)) != -1){
6030 this.listeners.splice(index, 1);
6032 this.listeners = this.listeners.slice(0);
6033 this.listeners.splice(index, 1);
6040 clearListeners : function(){
6041 this.listeners = [];
6045 var ls = this.listeners, scope, len = ls.length;
6048 var args = Array.prototype.slice.call(arguments, 0);
6049 for(var i = 0; i < len; i++){
6051 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6052 this.firing = false;
6056 this.firing = false;
6063 * Copyright(c) 2007-2017, Roo J Solutions Ltd
6070 * @class Roo.Document
6071 * @extends Roo.util.Observable
6072 * This is a convience class to wrap up the main document loading code.. , rather than adding Roo.onReady(......)
6074 * @param {Object} config the methods and properties of the 'base' class for the application.
6076 * Generic Page handler - implement this to start your app..
6079 * MyProject = new Roo.Document({
6081 'load' : true // your events..
6084 'ready' : function() {
6085 // fired on Roo.onReady()
6090 Roo.Document = function(cfg) {
6095 Roo.util.Observable.call(this,cfg);
6099 Roo.onReady(function() {
6100 _this.fireEvent('ready');
6106 Roo.extend(Roo.Document, Roo.util.Observable, {});/*
6108 * Ext JS Library 1.1.1
6109 * Copyright(c) 2006-2007, Ext JS, LLC.
6111 * Originally Released Under LGPL - original licence link has changed is not relivant.
6114 * <script type="text/javascript">
6118 * @class Roo.EventManager
6119 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6120 * several useful events directly.
6121 * See {@link Roo.EventObject} for more details on normalized event objects.
6124 Roo.EventManager = function(){
6125 var docReadyEvent, docReadyProcId, docReadyState = false;
6126 var resizeEvent, resizeTask, textEvent, textSize;
6127 var E = Roo.lib.Event;
6128 var D = Roo.lib.Dom;
6133 var fireDocReady = function(){
6135 docReadyState = true;
6138 clearInterval(docReadyProcId);
6140 if(Roo.isGecko || Roo.isOpera) {
6141 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6144 var defer = document.getElementById("ie-deferred-loader");
6146 defer.onreadystatechange = null;
6147 defer.parentNode.removeChild(defer);
6151 docReadyEvent.fire();
6152 docReadyEvent.clearListeners();
6157 var initDocReady = function(){
6158 docReadyEvent = new Roo.util.Event();
6159 if(Roo.isGecko || Roo.isOpera) {
6160 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6162 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6163 var defer = document.getElementById("ie-deferred-loader");
6164 defer.onreadystatechange = function(){
6165 if(this.readyState == "complete"){
6169 }else if(Roo.isSafari){
6170 docReadyProcId = setInterval(function(){
6171 var rs = document.readyState;
6172 if(rs == "complete") {
6177 // no matter what, make sure it fires on load
6178 E.on(window, "load", fireDocReady);
6181 var createBuffered = function(h, o){
6182 var task = new Roo.util.DelayedTask(h);
6184 // create new event object impl so new events don't wipe out properties
6185 e = new Roo.EventObjectImpl(e);
6186 task.delay(o.buffer, h, null, [e]);
6190 var createSingle = function(h, el, ename, fn){
6192 Roo.EventManager.removeListener(el, ename, fn);
6197 var createDelayed = function(h, o){
6199 // create new event object impl so new events don't wipe out properties
6200 e = new Roo.EventObjectImpl(e);
6201 setTimeout(function(){
6206 var transitionEndVal = false;
6208 var transitionEnd = function()
6210 if (transitionEndVal) {
6211 return transitionEndVal;
6213 var el = document.createElement('div');
6215 var transEndEventNames = {
6216 WebkitTransition : 'webkitTransitionEnd',
6217 MozTransition : 'transitionend',
6218 OTransition : 'oTransitionEnd otransitionend',
6219 transition : 'transitionend'
6222 for (var name in transEndEventNames) {
6223 if (el.style[name] !== undefined) {
6224 transitionEndVal = transEndEventNames[name];
6225 return transitionEndVal ;
6231 var listen = function(element, ename, opt, fn, scope){
6232 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6233 fn = fn || o.fn; scope = scope || o.scope;
6234 var el = Roo.getDom(element);
6238 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6241 if (ename == 'transitionend') {
6242 ename = transitionEnd();
6244 var h = function(e){
6245 e = Roo.EventObject.setEvent(e);
6248 t = e.getTarget(o.delegate, el);
6255 if(o.stopEvent === true){
6258 if(o.preventDefault === true){
6261 if(o.stopPropagation === true){
6262 e.stopPropagation();
6265 if(o.normalized === false){
6269 fn.call(scope || el, e, t, o);
6272 h = createDelayed(h, o);
6275 h = createSingle(h, el, ename, fn);
6278 h = createBuffered(h, o);
6280 fn._handlers = fn._handlers || [];
6283 fn._handlers.push([Roo.id(el), ename, h]);
6288 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6289 el.addEventListener("DOMMouseScroll", h, false);
6290 E.on(window, 'unload', function(){
6291 el.removeEventListener("DOMMouseScroll", h, false);
6294 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6295 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6300 var stopListening = function(el, ename, fn){
6301 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6303 for(var i = 0, len = hds.length; i < len; i++){
6305 if(h[0] == id && h[1] == ename){
6312 E.un(el, ename, hd);
6313 el = Roo.getDom(el);
6314 if(ename == "mousewheel" && el.addEventListener){
6315 el.removeEventListener("DOMMouseScroll", hd, false);
6317 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6318 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6322 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6329 * @scope Roo.EventManager
6334 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6335 * object with a Roo.EventObject
6336 * @param {Function} fn The method the event invokes
6337 * @param {Object} scope An object that becomes the scope of the handler
6338 * @param {boolean} override If true, the obj passed in becomes
6339 * the execution scope of the listener
6340 * @return {Function} The wrapped function
6343 wrap : function(fn, scope, override){
6345 Roo.EventObject.setEvent(e);
6346 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6351 * Appends an event handler to an element (shorthand for addListener)
6352 * @param {String/HTMLElement} element The html element or id to assign the
6353 * @param {String} eventName The type of event to listen for
6354 * @param {Function} handler The method the event invokes
6355 * @param {Object} scope (optional) The scope in which to execute the handler
6356 * function. The handler function's "this" context.
6357 * @param {Object} options (optional) An object containing handler configuration
6358 * properties. This may contain any of the following properties:<ul>
6359 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6360 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6361 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6362 * <li>preventDefault {Boolean} True to prevent the default action</li>
6363 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6364 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6365 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6366 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6367 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6368 * by the specified number of milliseconds. If the event fires again within that time, the original
6369 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6372 * <b>Combining Options</b><br>
6373 * Using the options argument, it is possible to combine different types of listeners:<br>
6375 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6377 el.on('click', this.onClick, this, {
6384 * <b>Attaching multiple handlers in 1 call</b><br>
6385 * The method also allows for a single argument to be passed which is a config object containing properties
6386 * which specify multiple handlers.
6396 fn: this.onMouseOver
6405 * Or a shorthand syntax:<br>
6408 'click' : this.onClick,
6409 'mouseover' : this.onMouseOver,
6410 'mouseout' : this.onMouseOut
6414 addListener : function(element, eventName, fn, scope, options){
6415 if(typeof eventName == "object"){
6421 if(typeof o[e] == "function"){
6423 listen(element, e, o, o[e], o.scope);
6425 // individual options
6426 listen(element, e, o[e]);
6431 return listen(element, eventName, options, fn, scope);
6435 * Removes an event handler
6437 * @param {String/HTMLElement} element The id or html element to remove the
6439 * @param {String} eventName The type of event
6440 * @param {Function} fn
6441 * @return {Boolean} True if a listener was actually removed
6443 removeListener : function(element, eventName, fn){
6444 return stopListening(element, eventName, fn);
6448 * Fires when the document is ready (before onload and before images are loaded). Can be
6449 * accessed shorthanded Roo.onReady().
6450 * @param {Function} fn The method the event invokes
6451 * @param {Object} scope An object that becomes the scope of the handler
6452 * @param {boolean} options
6454 onDocumentReady : function(fn, scope, options){
6455 if(docReadyState){ // if it already fired
6456 docReadyEvent.addListener(fn, scope, options);
6457 docReadyEvent.fire();
6458 docReadyEvent.clearListeners();
6464 docReadyEvent.addListener(fn, scope, options);
6468 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6469 * @param {Function} fn The method the event invokes
6470 * @param {Object} scope An object that becomes the scope of the handler
6471 * @param {boolean} options
6473 onWindowResize : function(fn, scope, options){
6475 resizeEvent = new Roo.util.Event();
6476 resizeTask = new Roo.util.DelayedTask(function(){
6477 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6479 E.on(window, "resize", function(){
6481 resizeTask.delay(50);
6483 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6487 resizeEvent.addListener(fn, scope, options);
6491 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6492 * @param {Function} fn The method the event invokes
6493 * @param {Object} scope An object that becomes the scope of the handler
6494 * @param {boolean} options
6496 onTextResize : function(fn, scope, options){
6498 textEvent = new Roo.util.Event();
6499 var textEl = new Roo.Element(document.createElement('div'));
6500 textEl.dom.className = 'x-text-resize';
6501 textEl.dom.innerHTML = 'X';
6502 textEl.appendTo(document.body);
6503 textSize = textEl.dom.offsetHeight;
6504 setInterval(function(){
6505 if(textEl.dom.offsetHeight != textSize){
6506 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6508 }, this.textResizeInterval);
6510 textEvent.addListener(fn, scope, options);
6514 * Removes the passed window resize listener.
6515 * @param {Function} fn The method the event invokes
6516 * @param {Object} scope The scope of handler
6518 removeResizeListener : function(fn, scope){
6520 resizeEvent.removeListener(fn, scope);
6525 fireResize : function(){
6527 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6531 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6535 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6537 textResizeInterval : 50
6542 * @scopeAlias pub=Roo.EventManager
6546 * Appends an event handler to an element (shorthand for addListener)
6547 * @param {String/HTMLElement} element The html element or id to assign the
6548 * @param {String} eventName The type of event to listen for
6549 * @param {Function} handler The method the event invokes
6550 * @param {Object} scope (optional) The scope in which to execute the handler
6551 * function. The handler function's "this" context.
6552 * @param {Object} options (optional) An object containing handler configuration
6553 * properties. This may contain any of the following properties:<ul>
6554 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6555 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6556 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6557 * <li>preventDefault {Boolean} True to prevent the default action</li>
6558 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6559 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6560 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6561 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6562 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6563 * by the specified number of milliseconds. If the event fires again within that time, the original
6564 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6567 * <b>Combining Options</b><br>
6568 * Using the options argument, it is possible to combine different types of listeners:<br>
6570 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6572 el.on('click', this.onClick, this, {
6579 * <b>Attaching multiple handlers in 1 call</b><br>
6580 * The method also allows for a single argument to be passed which is a config object containing properties
6581 * which specify multiple handlers.
6591 fn: this.onMouseOver
6600 * Or a shorthand syntax:<br>
6603 'click' : this.onClick,
6604 'mouseover' : this.onMouseOver,
6605 'mouseout' : this.onMouseOut
6609 pub.on = pub.addListener;
6610 pub.un = pub.removeListener;
6612 pub.stoppedMouseDownEvent = new Roo.util.Event();
6616 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6617 * @param {Function} fn The method the event invokes
6618 * @param {Object} scope An object that becomes the scope of the handler
6619 * @param {boolean} override If true, the obj passed in becomes
6620 * the execution scope of the listener
6624 Roo.onReady = Roo.EventManager.onDocumentReady;
6626 Roo.onReady(function(){
6627 var bd = Roo.get(document.body);
6630 Roo.log('--------doc ready------');
6634 : Roo.isIE11 ? "roo-ie11"
6635 : Roo.isEdge ? "roo-edge"
6636 : Roo.isGecko ? "roo-gecko"
6637 : Roo.isOpera ? "roo-opera"
6638 : Roo.isSafari ? "roo-safari" : ""];
6641 cls.push("roo-mac");
6644 cls.push("roo-linux");
6647 cls.push("roo-ios");
6650 cls.push("roo-touch");
6652 if(Roo.isBorderBox){
6653 cls.push('roo-border-box');
6655 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6656 var p = bd.dom.parentNode;
6658 p.className += ' roo-strict';
6661 bd.addClass(cls.join(' '));
6665 * @class Roo.EventObject
6666 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6667 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6670 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6672 var target = e.getTarget();
6675 var myDiv = Roo.get("myDiv");
6676 myDiv.on("click", handleClick);
6678 Roo.EventManager.on("myDiv", 'click', handleClick);
6679 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6683 Roo.EventObject = function(){
6685 var E = Roo.lib.Event;
6687 // safari keypress events for special keys return bad keycodes
6690 63235 : 39, // right
6693 63276 : 33, // page up
6694 63277 : 34, // page down
6695 63272 : 46, // delete
6700 // normalize button clicks
6701 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6702 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6704 Roo.EventObjectImpl = function(e){
6706 this.setEvent(e.browserEvent || e);
6709 Roo.EventObjectImpl.prototype = {
6711 * Used to fix doc tools.
6712 * @scope Roo.EventObject.prototype
6718 /** The normal browser event */
6719 browserEvent : null,
6720 /** The button pressed in a mouse event */
6722 /** True if the shift key was down during the event */
6724 /** True if the control key was down during the event */
6726 /** True if the alt key was down during the event */
6785 setEvent : function(e){
6786 if(e == this || (e && e.browserEvent)){ // already wrapped
6789 this.browserEvent = e;
6791 // normalize buttons
6792 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6793 if(e.type == 'click' && this.button == -1){
6797 this.shiftKey = e.shiftKey;
6798 // mac metaKey behaves like ctrlKey
6799 this.ctrlKey = e.ctrlKey || e.metaKey;
6800 this.altKey = e.altKey;
6801 // in getKey these will be normalized for the mac
6802 this.keyCode = e.keyCode;
6803 // keyup warnings on firefox.
6804 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6805 // cache the target for the delayed and or buffered events
6806 this.target = E.getTarget(e);
6808 this.xy = E.getXY(e);
6811 this.shiftKey = false;
6812 this.ctrlKey = false;
6813 this.altKey = false;
6823 * Stop the event (preventDefault and stopPropagation)
6825 stopEvent : function(){
6826 if(this.browserEvent){
6827 if(this.browserEvent.type == 'mousedown'){
6828 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6830 E.stopEvent(this.browserEvent);
6835 * Prevents the browsers default handling of the event.
6837 preventDefault : function(){
6838 if(this.browserEvent){
6839 E.preventDefault(this.browserEvent);
6844 isNavKeyPress : function(){
6845 var k = this.keyCode;
6846 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6847 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6850 isSpecialKey : function(){
6851 var k = this.keyCode;
6852 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6853 (k == 16) || (k == 17) ||
6854 (k >= 18 && k <= 20) ||
6855 (k >= 33 && k <= 35) ||
6856 (k >= 36 && k <= 39) ||
6857 (k >= 44 && k <= 45);
6860 * Cancels bubbling of the event.
6862 stopPropagation : function(){
6863 if(this.browserEvent){
6864 if(this.type == 'mousedown'){
6865 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6867 E.stopPropagation(this.browserEvent);
6872 * Gets the key code for the event.
6875 getCharCode : function(){
6876 return this.charCode || this.keyCode;
6880 * Returns a normalized keyCode for the event.
6881 * @return {Number} The key code
6883 getKey : function(){
6884 var k = this.keyCode || this.charCode;
6885 return Roo.isSafari ? (safariKeys[k] || k) : k;
6889 * Gets the x coordinate of the event.
6892 getPageX : function(){
6897 * Gets the y coordinate of the event.
6900 getPageY : function(){
6905 * Gets the time of the event.
6908 getTime : function(){
6909 if(this.browserEvent){
6910 return E.getTime(this.browserEvent);
6916 * Gets the page coordinates of the event.
6917 * @return {Array} The xy values like [x, y]
6924 * Gets the target for the event.
6925 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6926 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6927 search as a number or element (defaults to 10 || document.body)
6928 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6929 * @return {HTMLelement}
6931 getTarget : function(selector, maxDepth, returnEl){
6932 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6935 * Gets the related target.
6936 * @return {HTMLElement}
6938 getRelatedTarget : function(){
6939 if(this.browserEvent){
6940 return E.getRelatedTarget(this.browserEvent);
6946 * Normalizes mouse wheel delta across browsers
6947 * @return {Number} The delta
6949 getWheelDelta : function(){
6950 var e = this.browserEvent;
6952 if(e.wheelDelta){ /* IE/Opera. */
6953 delta = e.wheelDelta/120;
6954 }else if(e.detail){ /* Mozilla case. */
6955 delta = -e.detail/3;
6961 * Returns true if the control, meta, shift or alt key was pressed during this event.
6964 hasModifier : function(){
6965 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6969 * Returns true if the target of this event equals el or is a child of el
6970 * @param {String/HTMLElement/Element} el
6971 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6974 within : function(el, related){
6975 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6976 return t && Roo.fly(el).contains(t);
6979 getPoint : function(){
6980 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6984 return new Roo.EventObjectImpl();
6989 * Ext JS Library 1.1.1
6990 * Copyright(c) 2006-2007, Ext JS, LLC.
6992 * Originally Released Under LGPL - original licence link has changed is not relivant.
6995 * <script type="text/javascript">
6999 // was in Composite Element!??!?!
7002 var D = Roo.lib.Dom;
7003 var E = Roo.lib.Event;
7004 var A = Roo.lib.Anim;
7006 // local style camelizing for speed
7008 var camelRe = /(-[a-z])/gi;
7009 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
7010 var view = document.defaultView;
7013 * @class Roo.Element
7014 * Represents an Element in the DOM.<br><br>
7017 var el = Roo.get("my-div");
7020 var el = getEl("my-div");
7022 // or with a DOM element
7023 var el = Roo.get(myDivElement);
7025 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
7026 * each call instead of constructing a new one.<br><br>
7027 * <b>Animations</b><br />
7028 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
7029 * should either be a boolean (true) or an object literal with animation options. The animation options are:
7031 Option Default Description
7032 --------- -------- ---------------------------------------------
7033 duration .35 The duration of the animation in seconds
7034 easing easeOut The YUI easing method
7035 callback none A function to execute when the anim completes
7036 scope this The scope (this) of the callback function
7038 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
7039 * manipulate the animation. Here's an example:
7041 var el = Roo.get("my-div");
7046 // default animation
7047 el.setWidth(100, true);
7049 // animation with some options set
7056 // using the "anim" property to get the Anim object
7062 el.setWidth(100, opt);
7064 if(opt.anim.isAnimated()){
7068 * <b> Composite (Collections of) Elements</b><br />
7069 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
7070 * @constructor Create a new Element directly.
7071 * @param {String/HTMLElement} element
7072 * @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).
7074 Roo.Element = function(element, forceNew){
7075 var dom = typeof element == "string" ?
7076 document.getElementById(element) : element;
7077 if(!dom){ // invalid id/element
7081 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7082 return Roo.Element.cache[id];
7092 * The DOM element ID
7095 this.id = id || Roo.id(dom);
7098 var El = Roo.Element;
7102 * The element's default display mode (defaults to "")
7105 originalDisplay : "",
7109 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7115 * Sets the element's visibility mode. When setVisible() is called it
7116 * will use this to determine whether to set the visibility or the display property.
7117 * @param visMode Element.VISIBILITY or Element.DISPLAY
7118 * @return {Roo.Element} this
7120 setVisibilityMode : function(visMode){
7121 this.visibilityMode = visMode;
7125 * Convenience method for setVisibilityMode(Element.DISPLAY)
7126 * @param {String} display (optional) What to set display to when visible
7127 * @return {Roo.Element} this
7129 enableDisplayMode : function(display){
7130 this.setVisibilityMode(El.DISPLAY);
7131 if(typeof display != "undefined") { this.originalDisplay = display; }
7136 * 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)
7137 * @param {String} selector The simple selector to test
7138 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7139 search as a number or element (defaults to 10 || document.body)
7140 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7141 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7143 findParent : function(simpleSelector, maxDepth, returnEl){
7144 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7145 maxDepth = maxDepth || 50;
7146 if(typeof maxDepth != "number"){
7147 stopEl = Roo.getDom(maxDepth);
7150 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7151 if(dq.is(p, simpleSelector)){
7152 return returnEl ? Roo.get(p) : p;
7162 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7163 * @param {String} selector The simple selector to test
7164 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7165 search as a number or element (defaults to 10 || document.body)
7166 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7167 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7169 findParentNode : function(simpleSelector, maxDepth, returnEl){
7170 var p = Roo.fly(this.dom.parentNode, '_internal');
7171 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7175 * Looks at the scrollable parent element
7177 findScrollableParent : function()
7179 var overflowRegex = /(auto|scroll)/;
7181 if(this.getStyle('position') === 'fixed'){
7182 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7185 var excludeStaticParent = this.getStyle('position') === "absolute";
7187 for (var parent = this; (parent = Roo.get(parent.dom.parentNode));){
7189 if (excludeStaticParent && parent.getStyle('position') === "static") {
7193 if (overflowRegex.test(parent.getStyle('overflow') + parent.getStyle('overflow-x') + parent.getStyle('overflow-y'))){
7197 if(parent.dom.nodeName.toLowerCase() == 'body'){
7198 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7202 return Roo.isAndroid ? Roo.get(document.documentElement) : Roo.get(document.body);
7206 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7207 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7208 * @param {String} selector The simple selector to test
7209 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7210 search as a number or element (defaults to 10 || document.body)
7211 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7213 up : function(simpleSelector, maxDepth){
7214 return this.findParentNode(simpleSelector, maxDepth, true);
7220 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7221 * @param {String} selector The simple selector to test
7222 * @return {Boolean} True if this element matches the selector, else false
7224 is : function(simpleSelector){
7225 return Roo.DomQuery.is(this.dom, simpleSelector);
7229 * Perform animation on this element.
7230 * @param {Object} args The YUI animation control args
7231 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7232 * @param {Function} onComplete (optional) Function to call when animation completes
7233 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7234 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7235 * @return {Roo.Element} this
7237 animate : function(args, duration, onComplete, easing, animType){
7238 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7243 * @private Internal animation call
7245 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7246 animType = animType || 'run';
7248 var anim = Roo.lib.Anim[animType](
7250 (opt.duration || defaultDur) || .35,
7251 (opt.easing || defaultEase) || 'easeOut',
7253 Roo.callback(cb, this);
7254 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7262 // private legacy anim prep
7263 preanim : function(a, i){
7264 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7268 * Removes worthless text nodes
7269 * @param {Boolean} forceReclean (optional) By default the element
7270 * keeps track if it has been cleaned already so
7271 * you can call this over and over. However, if you update the element and
7272 * need to force a reclean, you can pass true.
7274 clean : function(forceReclean){
7275 if(this.isCleaned && forceReclean !== true){
7279 var d = this.dom, n = d.firstChild, ni = -1;
7281 var nx = n.nextSibling;
7282 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7289 this.isCleaned = true;
7294 calcOffsetsTo : function(el){
7297 var restorePos = false;
7298 if(el.getStyle('position') == 'static'){
7299 el.position('relative');
7304 while(op && op != d && op.tagName != 'HTML'){
7307 op = op.offsetParent;
7310 el.position('static');
7316 * Scrolls this element into view within the passed container.
7317 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7318 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7319 * @return {Roo.Element} this
7321 scrollIntoView : function(container, hscroll){
7322 var c = Roo.getDom(container) || document.body;
7325 var o = this.calcOffsetsTo(c),
7328 b = t+el.offsetHeight,
7329 r = l+el.offsetWidth;
7331 var ch = c.clientHeight;
7332 var ct = parseInt(c.scrollTop, 10);
7333 var cl = parseInt(c.scrollLeft, 10);
7335 var cr = cl + c.clientWidth;
7343 if(hscroll !== false){
7347 c.scrollLeft = r-c.clientWidth;
7354 scrollChildIntoView : function(child, hscroll){
7355 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7359 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7360 * the new height may not be available immediately.
7361 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7362 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7363 * @param {Function} onComplete (optional) Function to call when animation completes
7364 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7365 * @return {Roo.Element} this
7367 autoHeight : function(animate, duration, onComplete, easing){
7368 var oldHeight = this.getHeight();
7370 this.setHeight(1); // force clipping
7371 setTimeout(function(){
7372 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7374 this.setHeight(height);
7376 if(typeof onComplete == "function"){
7380 this.setHeight(oldHeight); // restore original height
7381 this.setHeight(height, animate, duration, function(){
7383 if(typeof onComplete == "function") { onComplete(); }
7384 }.createDelegate(this), easing);
7386 }.createDelegate(this), 0);
7391 * Returns true if this element is an ancestor of the passed element
7392 * @param {HTMLElement/String} el The element to check
7393 * @return {Boolean} True if this element is an ancestor of el, else false
7395 contains : function(el){
7396 if(!el){return false;}
7397 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7401 * Checks whether the element is currently visible using both visibility and display properties.
7402 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7403 * @return {Boolean} True if the element is currently visible, else false
7405 isVisible : function(deep) {
7406 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7407 if(deep !== true || !vis){
7410 var p = this.dom.parentNode;
7411 while(p && p.tagName.toLowerCase() != "body"){
7412 if(!Roo.fly(p, '_isVisible').isVisible()){
7421 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7422 * @param {String} selector The CSS selector
7423 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7424 * @return {CompositeElement/CompositeElementLite} The composite element
7426 select : function(selector, unique){
7427 return El.select(selector, unique, this.dom);
7431 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7432 * @param {String} selector The CSS selector
7433 * @return {Array} An array of the matched nodes
7435 query : function(selector, unique){
7436 return Roo.DomQuery.select(selector, this.dom);
7440 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7441 * @param {String} selector The CSS selector
7442 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7443 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7445 child : function(selector, returnDom){
7446 var n = Roo.DomQuery.selectNode(selector, this.dom);
7447 return returnDom ? n : Roo.get(n);
7451 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7452 * @param {String} selector The CSS selector
7453 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7454 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7456 down : function(selector, returnDom){
7457 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7458 return returnDom ? n : Roo.get(n);
7462 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7463 * @param {String} group The group the DD object is member of
7464 * @param {Object} config The DD config object
7465 * @param {Object} overrides An object containing methods to override/implement on the DD object
7466 * @return {Roo.dd.DD} The DD object
7468 initDD : function(group, config, overrides){
7469 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7470 return Roo.apply(dd, overrides);
7474 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7475 * @param {String} group The group the DDProxy object is member of
7476 * @param {Object} config The DDProxy config object
7477 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7478 * @return {Roo.dd.DDProxy} The DDProxy object
7480 initDDProxy : function(group, config, overrides){
7481 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7482 return Roo.apply(dd, overrides);
7486 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7487 * @param {String} group The group the DDTarget object is member of
7488 * @param {Object} config The DDTarget config object
7489 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7490 * @return {Roo.dd.DDTarget} The DDTarget object
7492 initDDTarget : function(group, config, overrides){
7493 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7494 return Roo.apply(dd, overrides);
7498 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7499 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7500 * @param {Boolean} visible Whether the element is visible
7501 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7502 * @return {Roo.Element} this
7504 setVisible : function(visible, animate){
7506 if(this.visibilityMode == El.DISPLAY){
7507 this.setDisplayed(visible);
7510 this.dom.style.visibility = visible ? "visible" : "hidden";
7513 // closure for composites
7515 var visMode = this.visibilityMode;
7517 this.setOpacity(.01);
7518 this.setVisible(true);
7520 this.anim({opacity: { to: (visible?1:0) }},
7521 this.preanim(arguments, 1),
7522 null, .35, 'easeIn', function(){
7524 if(visMode == El.DISPLAY){
7525 dom.style.display = "none";
7527 dom.style.visibility = "hidden";
7529 Roo.get(dom).setOpacity(1);
7537 * Returns true if display is not "none"
7540 isDisplayed : function() {
7541 return this.getStyle("display") != "none";
7545 * Toggles the element's visibility or display, depending on visibility mode.
7546 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7547 * @return {Roo.Element} this
7549 toggle : function(animate){
7550 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7555 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7556 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7557 * @return {Roo.Element} this
7559 setDisplayed : function(value) {
7560 if(typeof value == "boolean"){
7561 value = value ? this.originalDisplay : "none";
7563 this.setStyle("display", value);
7568 * Tries to focus the element. Any exceptions are caught and ignored.
7569 * @return {Roo.Element} this
7571 focus : function() {
7579 * Tries to blur the element. Any exceptions are caught and ignored.
7580 * @return {Roo.Element} this
7590 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7591 * @param {String/Array} className The CSS class to add, or an array of classes
7592 * @return {Roo.Element} this
7594 addClass : function(className){
7595 if(className instanceof Array){
7596 for(var i = 0, len = className.length; i < len; i++) {
7597 this.addClass(className[i]);
7600 if(className && !this.hasClass(className)){
7601 this.dom.className = this.dom.className + " " + className;
7608 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7609 * @param {String/Array} className The CSS class to add, or an array of classes
7610 * @return {Roo.Element} this
7612 radioClass : function(className){
7613 var siblings = this.dom.parentNode.childNodes;
7614 for(var i = 0; i < siblings.length; i++) {
7615 var s = siblings[i];
7616 if(s.nodeType == 1){
7617 Roo.get(s).removeClass(className);
7620 this.addClass(className);
7625 * Removes one or more CSS classes from the element.
7626 * @param {String/Array} className The CSS class to remove, or an array of classes
7627 * @return {Roo.Element} this
7629 removeClass : function(className){
7630 if(!className || !this.dom.className){
7633 if(className instanceof Array){
7634 for(var i = 0, len = className.length; i < len; i++) {
7635 this.removeClass(className[i]);
7638 if(this.hasClass(className)){
7639 var re = this.classReCache[className];
7641 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7642 this.classReCache[className] = re;
7644 this.dom.className =
7645 this.dom.className.replace(re, " ");
7655 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7656 * @param {String} className The CSS class to toggle
7657 * @return {Roo.Element} this
7659 toggleClass : function(className){
7660 if(this.hasClass(className)){
7661 this.removeClass(className);
7663 this.addClass(className);
7669 * Checks if the specified CSS class exists on this element's DOM node.
7670 * @param {String} className The CSS class to check for
7671 * @return {Boolean} True if the class exists, else false
7673 hasClass : function(className){
7674 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7678 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7679 * @param {String} oldClassName The CSS class to replace
7680 * @param {String} newClassName The replacement CSS class
7681 * @return {Roo.Element} this
7683 replaceClass : function(oldClassName, newClassName){
7684 this.removeClass(oldClassName);
7685 this.addClass(newClassName);
7690 * Returns an object with properties matching the styles requested.
7691 * For example, el.getStyles('color', 'font-size', 'width') might return
7692 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7693 * @param {String} style1 A style name
7694 * @param {String} style2 A style name
7695 * @param {String} etc.
7696 * @return {Object} The style object
7698 getStyles : function(){
7699 var a = arguments, len = a.length, r = {};
7700 for(var i = 0; i < len; i++){
7701 r[a[i]] = this.getStyle(a[i]);
7707 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7708 * @param {String} property The style property whose value is returned.
7709 * @return {String} The current value of the style property for this element.
7711 getStyle : function(){
7712 return view && view.getComputedStyle ?
7714 var el = this.dom, v, cs, camel;
7715 if(prop == 'float'){
7718 if(el.style && (v = el.style[prop])){
7721 if(cs = view.getComputedStyle(el, "")){
7722 if(!(camel = propCache[prop])){
7723 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7730 var el = this.dom, v, cs, camel;
7731 if(prop == 'opacity'){
7732 if(typeof el.style.filter == 'string'){
7733 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7735 var fv = parseFloat(m[1]);
7737 return fv ? fv / 100 : 0;
7742 }else if(prop == 'float'){
7743 prop = "styleFloat";
7745 if(!(camel = propCache[prop])){
7746 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7748 if(v = el.style[camel]){
7751 if(cs = el.currentStyle){
7759 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7760 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7761 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7762 * @return {Roo.Element} this
7764 setStyle : function(prop, value){
7765 if(typeof prop == "string"){
7767 if (prop == 'float') {
7768 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7773 if(!(camel = propCache[prop])){
7774 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7777 if(camel == 'opacity') {
7778 this.setOpacity(value);
7780 this.dom.style[camel] = value;
7783 for(var style in prop){
7784 if(typeof prop[style] != "function"){
7785 this.setStyle(style, prop[style]);
7793 * More flexible version of {@link #setStyle} for setting style properties.
7794 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7795 * a function which returns such a specification.
7796 * @return {Roo.Element} this
7798 applyStyles : function(style){
7799 Roo.DomHelper.applyStyles(this.dom, style);
7804 * 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).
7805 * @return {Number} The X position of the element
7808 return D.getX(this.dom);
7812 * 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).
7813 * @return {Number} The Y position of the element
7816 return D.getY(this.dom);
7820 * 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).
7821 * @return {Array} The XY position of the element
7824 return D.getXY(this.dom);
7828 * 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).
7829 * @param {Number} The X position of the element
7830 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7831 * @return {Roo.Element} this
7833 setX : function(x, animate){
7835 D.setX(this.dom, x);
7837 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7843 * 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).
7844 * @param {Number} The Y position of the element
7845 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7846 * @return {Roo.Element} this
7848 setY : function(y, animate){
7850 D.setY(this.dom, y);
7852 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7858 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7859 * @param {String} left The left CSS property value
7860 * @return {Roo.Element} this
7862 setLeft : function(left){
7863 this.setStyle("left", this.addUnits(left));
7868 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7869 * @param {String} top The top CSS property value
7870 * @return {Roo.Element} this
7872 setTop : function(top){
7873 this.setStyle("top", this.addUnits(top));
7878 * Sets the element's CSS right style.
7879 * @param {String} right The right CSS property value
7880 * @return {Roo.Element} this
7882 setRight : function(right){
7883 this.setStyle("right", this.addUnits(right));
7888 * Sets the element's CSS bottom style.
7889 * @param {String} bottom The bottom CSS property value
7890 * @return {Roo.Element} this
7892 setBottom : function(bottom){
7893 this.setStyle("bottom", this.addUnits(bottom));
7898 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7899 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7900 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7901 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7902 * @return {Roo.Element} this
7904 setXY : function(pos, animate){
7906 D.setXY(this.dom, pos);
7908 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7914 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7915 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7916 * @param {Number} x X value for new position (coordinates are page-based)
7917 * @param {Number} y Y value for new position (coordinates are page-based)
7918 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7919 * @return {Roo.Element} this
7921 setLocation : function(x, y, animate){
7922 this.setXY([x, y], this.preanim(arguments, 2));
7927 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7928 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7929 * @param {Number} x X value for new position (coordinates are page-based)
7930 * @param {Number} y Y value for new position (coordinates are page-based)
7931 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7932 * @return {Roo.Element} this
7934 moveTo : function(x, y, animate){
7935 this.setXY([x, y], this.preanim(arguments, 2));
7940 * Returns the region of the given element.
7941 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7942 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7944 getRegion : function(){
7945 return D.getRegion(this.dom);
7949 * Returns the offset height of the element
7950 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7951 * @return {Number} The element's height
7953 getHeight : function(contentHeight){
7954 var h = this.dom.offsetHeight || 0;
7955 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7959 * Returns the offset width of the element
7960 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7961 * @return {Number} The element's width
7963 getWidth : function(contentWidth){
7964 var w = this.dom.offsetWidth || 0;
7965 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7969 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7970 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7971 * if a height has not been set using CSS.
7974 getComputedHeight : function(){
7975 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7977 h = parseInt(this.getStyle('height'), 10) || 0;
7978 if(!this.isBorderBox()){
7979 h += this.getFrameWidth('tb');
7986 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7987 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7988 * if a width has not been set using CSS.
7991 getComputedWidth : function(){
7992 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7994 w = parseInt(this.getStyle('width'), 10) || 0;
7995 if(!this.isBorderBox()){
7996 w += this.getFrameWidth('lr');
8003 * Returns the size of the element.
8004 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
8005 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
8007 getSize : function(contentSize){
8008 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
8012 * Returns the width and height of the viewport.
8013 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
8015 getViewSize : function(){
8016 var d = this.dom, doc = document, aw = 0, ah = 0;
8017 if(d == doc || d == doc.body){
8018 return {width : D.getViewWidth(), height: D.getViewHeight()};
8021 width : d.clientWidth,
8022 height: d.clientHeight
8028 * Returns the value of the "value" attribute
8029 * @param {Boolean} asNumber true to parse the value as a number
8030 * @return {String/Number}
8032 getValue : function(asNumber){
8033 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
8037 adjustWidth : function(width){
8038 if(typeof width == "number"){
8039 if(this.autoBoxAdjust && !this.isBorderBox()){
8040 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8050 adjustHeight : function(height){
8051 if(typeof height == "number"){
8052 if(this.autoBoxAdjust && !this.isBorderBox()){
8053 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8063 * Set the width of the element
8064 * @param {Number} width The new width
8065 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8066 * @return {Roo.Element} this
8068 setWidth : function(width, animate){
8069 width = this.adjustWidth(width);
8071 this.dom.style.width = this.addUnits(width);
8073 this.anim({width: {to: width}}, this.preanim(arguments, 1));
8079 * Set the height of the element
8080 * @param {Number} height The new height
8081 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8082 * @return {Roo.Element} this
8084 setHeight : function(height, animate){
8085 height = this.adjustHeight(height);
8087 this.dom.style.height = this.addUnits(height);
8089 this.anim({height: {to: height}}, this.preanim(arguments, 1));
8095 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
8096 * @param {Number} width The new width
8097 * @param {Number} height The new height
8098 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8099 * @return {Roo.Element} this
8101 setSize : function(width, height, animate){
8102 if(typeof width == "object"){ // in case of object from getSize()
8103 height = width.height; width = width.width;
8105 width = this.adjustWidth(width); height = this.adjustHeight(height);
8107 this.dom.style.width = this.addUnits(width);
8108 this.dom.style.height = this.addUnits(height);
8110 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8116 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8117 * @param {Number} x X value for new position (coordinates are page-based)
8118 * @param {Number} y Y value for new position (coordinates are page-based)
8119 * @param {Number} width The new width
8120 * @param {Number} height The new height
8121 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8122 * @return {Roo.Element} this
8124 setBounds : function(x, y, width, height, animate){
8126 this.setSize(width, height);
8127 this.setLocation(x, y);
8129 width = this.adjustWidth(width); height = this.adjustHeight(height);
8130 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8131 this.preanim(arguments, 4), 'motion');
8137 * 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.
8138 * @param {Roo.lib.Region} region The region to fill
8139 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8140 * @return {Roo.Element} this
8142 setRegion : function(region, animate){
8143 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8148 * Appends an event handler
8150 * @param {String} eventName The type of event to append
8151 * @param {Function} fn The method the event invokes
8152 * @param {Object} scope (optional) The scope (this object) of the fn
8153 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8155 addListener : function(eventName, fn, scope, options){
8157 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8162 * Removes an event handler from this element
8163 * @param {String} eventName the type of event to remove
8164 * @param {Function} fn the method the event invokes
8165 * @return {Roo.Element} this
8167 removeListener : function(eventName, fn){
8168 Roo.EventManager.removeListener(this.dom, eventName, fn);
8173 * Removes all previous added listeners from this element
8174 * @return {Roo.Element} this
8176 removeAllListeners : function(){
8177 E.purgeElement(this.dom);
8181 relayEvent : function(eventName, observable){
8182 this.on(eventName, function(e){
8183 observable.fireEvent(eventName, e);
8188 * Set the opacity of the element
8189 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8190 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8191 * @return {Roo.Element} this
8193 setOpacity : function(opacity, animate){
8195 var s = this.dom.style;
8198 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8199 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8201 s.opacity = opacity;
8204 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8210 * Gets the left X coordinate
8211 * @param {Boolean} local True to get the local css position instead of page coordinate
8214 getLeft : function(local){
8218 return parseInt(this.getStyle("left"), 10) || 0;
8223 * Gets the right X coordinate of the element (element X position + element width)
8224 * @param {Boolean} local True to get the local css position instead of page coordinate
8227 getRight : function(local){
8229 return this.getX() + this.getWidth();
8231 return (this.getLeft(true) + this.getWidth()) || 0;
8236 * Gets the top Y coordinate
8237 * @param {Boolean} local True to get the local css position instead of page coordinate
8240 getTop : function(local) {
8244 return parseInt(this.getStyle("top"), 10) || 0;
8249 * Gets the bottom Y coordinate of the element (element Y position + element height)
8250 * @param {Boolean} local True to get the local css position instead of page coordinate
8253 getBottom : function(local){
8255 return this.getY() + this.getHeight();
8257 return (this.getTop(true) + this.getHeight()) || 0;
8262 * Initializes positioning on this element. If a desired position is not passed, it will make the
8263 * the element positioned relative IF it is not already positioned.
8264 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8265 * @param {Number} zIndex (optional) The zIndex to apply
8266 * @param {Number} x (optional) Set the page X position
8267 * @param {Number} y (optional) Set the page Y position
8269 position : function(pos, zIndex, x, y){
8271 if(this.getStyle('position') == 'static'){
8272 this.setStyle('position', 'relative');
8275 this.setStyle("position", pos);
8278 this.setStyle("z-index", zIndex);
8280 if(x !== undefined && y !== undefined){
8282 }else if(x !== undefined){
8284 }else if(y !== undefined){
8290 * Clear positioning back to the default when the document was loaded
8291 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8292 * @return {Roo.Element} this
8294 clearPositioning : function(value){
8302 "position" : "static"
8308 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8309 * snapshot before performing an update and then restoring the element.
8312 getPositioning : function(){
8313 var l = this.getStyle("left");
8314 var t = this.getStyle("top");
8316 "position" : this.getStyle("position"),
8318 "right" : l ? "" : this.getStyle("right"),
8320 "bottom" : t ? "" : this.getStyle("bottom"),
8321 "z-index" : this.getStyle("z-index")
8326 * Gets the width of the border(s) for the specified side(s)
8327 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8328 * passing lr would get the border (l)eft width + the border (r)ight width.
8329 * @return {Number} The width of the sides passed added together
8331 getBorderWidth : function(side){
8332 return this.addStyles(side, El.borders);
8336 * Gets the width of the padding(s) for the specified side(s)
8337 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8338 * passing lr would get the padding (l)eft + the padding (r)ight.
8339 * @return {Number} The padding of the sides passed added together
8341 getPadding : function(side){
8342 return this.addStyles(side, El.paddings);
8346 * Set positioning with an object returned by getPositioning().
8347 * @param {Object} posCfg
8348 * @return {Roo.Element} this
8350 setPositioning : function(pc){
8351 this.applyStyles(pc);
8352 if(pc.right == "auto"){
8353 this.dom.style.right = "";
8355 if(pc.bottom == "auto"){
8356 this.dom.style.bottom = "";
8362 fixDisplay : function(){
8363 if(this.getStyle("display") == "none"){
8364 this.setStyle("visibility", "hidden");
8365 this.setStyle("display", this.originalDisplay); // first try reverting to default
8366 if(this.getStyle("display") == "none"){ // if that fails, default to block
8367 this.setStyle("display", "block");
8373 * Quick set left and top adding default units
8374 * @param {String} left The left CSS property value
8375 * @param {String} top The top CSS property value
8376 * @return {Roo.Element} this
8378 setLeftTop : function(left, top){
8379 this.dom.style.left = this.addUnits(left);
8380 this.dom.style.top = this.addUnits(top);
8385 * Move this element relative to its current position.
8386 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8387 * @param {Number} distance How far to move the element in pixels
8388 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8389 * @return {Roo.Element} this
8391 move : function(direction, distance, animate){
8392 var xy = this.getXY();
8393 direction = direction.toLowerCase();
8397 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8401 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8406 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8411 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8418 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8419 * @return {Roo.Element} this
8422 if(!this.isClipped){
8423 this.isClipped = true;
8424 this.originalClip = {
8425 "o": this.getStyle("overflow"),
8426 "x": this.getStyle("overflow-x"),
8427 "y": this.getStyle("overflow-y")
8429 this.setStyle("overflow", "hidden");
8430 this.setStyle("overflow-x", "hidden");
8431 this.setStyle("overflow-y", "hidden");
8437 * Return clipping (overflow) to original clipping before clip() was called
8438 * @return {Roo.Element} this
8440 unclip : function(){
8442 this.isClipped = false;
8443 var o = this.originalClip;
8444 if(o.o){this.setStyle("overflow", o.o);}
8445 if(o.x){this.setStyle("overflow-x", o.x);}
8446 if(o.y){this.setStyle("overflow-y", o.y);}
8453 * Gets the x,y coordinates specified by the anchor position on the element.
8454 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8455 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8456 * {width: (target width), height: (target height)} (defaults to the element's current size)
8457 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8458 * @return {Array} [x, y] An array containing the element's x and y coordinates
8460 getAnchorXY : function(anchor, local, s){
8461 //Passing a different size is useful for pre-calculating anchors,
8462 //especially for anchored animations that change the el size.
8464 var w, h, vp = false;
8467 if(d == document.body || d == document){
8469 w = D.getViewWidth(); h = D.getViewHeight();
8471 w = this.getWidth(); h = this.getHeight();
8474 w = s.width; h = s.height;
8476 var x = 0, y = 0, r = Math.round;
8477 switch((anchor || "tl").toLowerCase()){
8519 var sc = this.getScroll();
8520 return [x + sc.left, y + sc.top];
8522 //Add the element's offset xy
8523 var o = this.getXY();
8524 return [x+o[0], y+o[1]];
8528 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8529 * supported position values.
8530 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8531 * @param {String} position The position to align to.
8532 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8533 * @return {Array} [x, y]
8535 getAlignToXY : function(el, p, o){
8539 throw "Element.alignTo with an element that doesn't exist";
8541 var c = false; //constrain to viewport
8542 var p1 = "", p2 = "";
8549 }else if(p.indexOf("-") == -1){
8552 p = p.toLowerCase();
8553 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8555 throw "Element.alignTo with an invalid alignment " + p;
8557 p1 = m[1]; p2 = m[2]; c = !!m[3];
8559 //Subtract the aligned el's internal xy from the target's offset xy
8560 //plus custom offset to get the aligned el's new offset xy
8561 var a1 = this.getAnchorXY(p1, true);
8562 var a2 = el.getAnchorXY(p2, false);
8563 var x = a2[0] - a1[0] + o[0];
8564 var y = a2[1] - a1[1] + o[1];
8566 //constrain the aligned el to viewport if necessary
8567 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8568 // 5px of margin for ie
8569 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8571 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8572 //perpendicular to the vp border, allow the aligned el to slide on that border,
8573 //otherwise swap the aligned el to the opposite border of the target.
8574 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8575 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8576 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8577 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8580 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8581 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8583 if((x+w) > dw + scrollX){
8584 x = swapX ? r.left-w : dw+scrollX-w;
8587 x = swapX ? r.right : scrollX;
8589 if((y+h) > dh + scrollY){
8590 y = swapY ? r.top-h : dh+scrollY-h;
8593 y = swapY ? r.bottom : scrollY;
8600 getConstrainToXY : function(){
8601 var os = {top:0, left:0, bottom:0, right: 0};
8603 return function(el, local, offsets, proposedXY){
8605 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8607 var vw, vh, vx = 0, vy = 0;
8608 if(el.dom == document.body || el.dom == document){
8609 vw = Roo.lib.Dom.getViewWidth();
8610 vh = Roo.lib.Dom.getViewHeight();
8612 vw = el.dom.clientWidth;
8613 vh = el.dom.clientHeight;
8615 var vxy = el.getXY();
8621 var s = el.getScroll();
8623 vx += offsets.left + s.left;
8624 vy += offsets.top + s.top;
8626 vw -= offsets.right;
8627 vh -= offsets.bottom;
8632 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8633 var x = xy[0], y = xy[1];
8634 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8636 // only move it if it needs it
8639 // first validate right/bottom
8648 // then make sure top/left isn't negative
8657 return moved ? [x, y] : false;
8662 adjustForConstraints : function(xy, parent, offsets){
8663 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8667 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8668 * document it aligns it to the viewport.
8669 * The position parameter is optional, and can be specified in any one of the following formats:
8671 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8672 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8673 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8674 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8675 * <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
8676 * element's anchor point, and the second value is used as the target's anchor point.</li>
8678 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8679 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8680 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8681 * that specified in order to enforce the viewport constraints.
8682 * Following are all of the supported anchor positions:
8685 ----- -----------------------------
8686 tl The top left corner (default)
8687 t The center of the top edge
8688 tr The top right corner
8689 l The center of the left edge
8690 c In the center of the element
8691 r The center of the right edge
8692 bl The bottom left corner
8693 b The center of the bottom edge
8694 br The bottom right corner
8698 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8699 el.alignTo("other-el");
8701 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8702 el.alignTo("other-el", "tr?");
8704 // align the bottom right corner of el with the center left edge of other-el
8705 el.alignTo("other-el", "br-l?");
8707 // align the center of el with the bottom left corner of other-el and
8708 // adjust the x position by -6 pixels (and the y position by 0)
8709 el.alignTo("other-el", "c-bl", [-6, 0]);
8711 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8712 * @param {String} position The position to align to.
8713 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8714 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8715 * @return {Roo.Element} this
8717 alignTo : function(element, position, offsets, animate){
8718 var xy = this.getAlignToXY(element, position, offsets);
8719 this.setXY(xy, this.preanim(arguments, 3));
8724 * Anchors an element to another element and realigns it when the window is resized.
8725 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8726 * @param {String} position The position to align to.
8727 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8728 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8729 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8730 * is a number, it is used as the buffer delay (defaults to 50ms).
8731 * @param {Function} callback The function to call after the animation finishes
8732 * @return {Roo.Element} this
8734 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8735 var action = function(){
8736 this.alignTo(el, alignment, offsets, animate);
8737 Roo.callback(callback, this);
8739 Roo.EventManager.onWindowResize(action, this);
8740 var tm = typeof monitorScroll;
8741 if(tm != 'undefined'){
8742 Roo.EventManager.on(window, 'scroll', action, this,
8743 {buffer: tm == 'number' ? monitorScroll : 50});
8745 action.call(this); // align immediately
8749 * Clears any opacity settings from this element. Required in some cases for IE.
8750 * @return {Roo.Element} this
8752 clearOpacity : function(){
8753 if (window.ActiveXObject) {
8754 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8755 this.dom.style.filter = "";
8758 this.dom.style.opacity = "";
8759 this.dom.style["-moz-opacity"] = "";
8760 this.dom.style["-khtml-opacity"] = "";
8766 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8767 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8768 * @return {Roo.Element} this
8770 hide : function(animate){
8771 this.setVisible(false, this.preanim(arguments, 0));
8776 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8777 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8778 * @return {Roo.Element} this
8780 show : function(animate){
8781 this.setVisible(true, this.preanim(arguments, 0));
8786 * @private Test if size has a unit, otherwise appends the default
8788 addUnits : function(size){
8789 return Roo.Element.addUnits(size, this.defaultUnit);
8793 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8794 * @return {Roo.Element} this
8796 beginMeasure : function(){
8798 if(el.offsetWidth || el.offsetHeight){
8799 return this; // offsets work already
8802 var p = this.dom, b = document.body; // start with this element
8803 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8804 var pe = Roo.get(p);
8805 if(pe.getStyle('display') == 'none'){
8806 changed.push({el: p, visibility: pe.getStyle("visibility")});
8807 p.style.visibility = "hidden";
8808 p.style.display = "block";
8812 this._measureChanged = changed;
8818 * Restores displays to before beginMeasure was called
8819 * @return {Roo.Element} this
8821 endMeasure : function(){
8822 var changed = this._measureChanged;
8824 for(var i = 0, len = changed.length; i < len; i++) {
8826 r.el.style.visibility = r.visibility;
8827 r.el.style.display = "none";
8829 this._measureChanged = null;
8835 * Update the innerHTML of this element, optionally searching for and processing scripts
8836 * @param {String} html The new HTML
8837 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8838 * @param {Function} callback For async script loading you can be noticed when the update completes
8839 * @return {Roo.Element} this
8841 update : function(html, loadScripts, callback){
8842 if(typeof html == "undefined"){
8845 if(loadScripts !== true){
8846 this.dom.innerHTML = html;
8847 if(typeof callback == "function"){
8855 html += '<span id="' + id + '"></span>';
8857 E.onAvailable(id, function(){
8858 var hd = document.getElementsByTagName("head")[0];
8859 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8860 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8861 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8864 while(match = re.exec(html)){
8865 var attrs = match[1];
8866 var srcMatch = attrs ? attrs.match(srcRe) : false;
8867 if(srcMatch && srcMatch[2]){
8868 var s = document.createElement("script");
8869 s.src = srcMatch[2];
8870 var typeMatch = attrs.match(typeRe);
8871 if(typeMatch && typeMatch[2]){
8872 s.type = typeMatch[2];
8875 }else if(match[2] && match[2].length > 0){
8876 if(window.execScript) {
8877 window.execScript(match[2]);
8885 window.eval(match[2]);
8889 var el = document.getElementById(id);
8890 if(el){el.parentNode.removeChild(el);}
8891 if(typeof callback == "function"){
8895 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8900 * Direct access to the UpdateManager update() method (takes the same parameters).
8901 * @param {String/Function} url The url for this request or a function to call to get the url
8902 * @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}
8903 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8904 * @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.
8905 * @return {Roo.Element} this
8908 var um = this.getUpdateManager();
8909 um.update.apply(um, arguments);
8914 * Gets this element's UpdateManager
8915 * @return {Roo.UpdateManager} The UpdateManager
8917 getUpdateManager : function(){
8918 if(!this.updateManager){
8919 this.updateManager = new Roo.UpdateManager(this);
8921 return this.updateManager;
8925 * Disables text selection for this element (normalized across browsers)
8926 * @return {Roo.Element} this
8928 unselectable : function(){
8929 this.dom.unselectable = "on";
8930 this.swallowEvent("selectstart", true);
8931 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8932 this.addClass("x-unselectable");
8937 * Calculates the x, y to center this element on the screen
8938 * @return {Array} The x, y values [x, y]
8940 getCenterXY : function(){
8941 return this.getAlignToXY(document, 'c-c');
8945 * Centers the Element in either the viewport, or another Element.
8946 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8948 center : function(centerIn){
8949 this.alignTo(centerIn || document, 'c-c');
8954 * Tests various css rules/browsers to determine if this element uses a border box
8957 isBorderBox : function(){
8958 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8962 * Return a box {x, y, width, height} that can be used to set another elements
8963 * size/location to match this element.
8964 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8965 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8966 * @return {Object} box An object in the format {x, y, width, height}
8968 getBox : function(contentBox, local){
8973 var left = parseInt(this.getStyle("left"), 10) || 0;
8974 var top = parseInt(this.getStyle("top"), 10) || 0;
8977 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8979 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8981 var l = this.getBorderWidth("l")+this.getPadding("l");
8982 var r = this.getBorderWidth("r")+this.getPadding("r");
8983 var t = this.getBorderWidth("t")+this.getPadding("t");
8984 var b = this.getBorderWidth("b")+this.getPadding("b");
8985 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)};
8987 bx.right = bx.x + bx.width;
8988 bx.bottom = bx.y + bx.height;
8993 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8994 for more information about the sides.
8995 * @param {String} sides
8998 getFrameWidth : function(sides, onlyContentBox){
8999 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
9003 * 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.
9004 * @param {Object} box The box to fill {x, y, width, height}
9005 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
9006 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9007 * @return {Roo.Element} this
9009 setBox : function(box, adjust, animate){
9010 var w = box.width, h = box.height;
9011 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
9012 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
9013 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
9015 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
9020 * Forces the browser to repaint this element
9021 * @return {Roo.Element} this
9023 repaint : function(){
9025 this.addClass("x-repaint");
9026 setTimeout(function(){
9027 Roo.get(dom).removeClass("x-repaint");
9033 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
9034 * then it returns the calculated width of the sides (see getPadding)
9035 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
9036 * @return {Object/Number}
9038 getMargins : function(side){
9041 top: parseInt(this.getStyle("margin-top"), 10) || 0,
9042 left: parseInt(this.getStyle("margin-left"), 10) || 0,
9043 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
9044 right: parseInt(this.getStyle("margin-right"), 10) || 0
9047 return this.addStyles(side, El.margins);
9052 addStyles : function(sides, styles){
9054 for(var i = 0, len = sides.length; i < len; i++){
9055 v = this.getStyle(styles[sides.charAt(i)]);
9057 w = parseInt(v, 10);
9065 * Creates a proxy element of this element
9066 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
9067 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
9068 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
9069 * @return {Roo.Element} The new proxy element
9071 createProxy : function(config, renderTo, matchBox){
9073 renderTo = Roo.getDom(renderTo);
9075 renderTo = document.body;
9077 config = typeof config == "object" ?
9078 config : {tag : "div", cls: config};
9079 var proxy = Roo.DomHelper.append(renderTo, config, true);
9081 proxy.setBox(this.getBox());
9087 * Puts a mask over this element to disable user interaction. Requires core.css.
9088 * This method can only be applied to elements which accept child nodes.
9089 * @param {String} msg (optional) A message to display in the mask
9090 * @param {String} msgCls (optional) A css class to apply to the msg element
9091 * @return {Element} The mask element
9093 mask : function(msg, msgCls)
9095 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
9096 this.setStyle("position", "relative");
9099 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
9101 this.addClass("x-masked");
9102 this._mask.setDisplayed(true);
9107 while (dom && dom.style) {
9108 if (!isNaN(parseInt(dom.style.zIndex))) {
9109 z = Math.max(z, parseInt(dom.style.zIndex));
9111 dom = dom.parentNode;
9113 // if we are masking the body - then it hides everything..
9114 if (this.dom == document.body) {
9116 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9117 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9120 if(typeof msg == 'string'){
9122 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9124 var mm = this._maskMsg;
9125 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9126 if (mm.dom.firstChild) { // weird IE issue?
9127 mm.dom.firstChild.innerHTML = msg;
9129 mm.setDisplayed(true);
9131 mm.setStyle('z-index', z + 102);
9133 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9134 this._mask.setHeight(this.getHeight());
9136 this._mask.setStyle('z-index', z + 100);
9142 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9143 * it is cached for reuse.
9145 unmask : function(removeEl){
9147 if(removeEl === true){
9148 this._mask.remove();
9151 this._maskMsg.remove();
9152 delete this._maskMsg;
9155 this._mask.setDisplayed(false);
9157 this._maskMsg.setDisplayed(false);
9161 this.removeClass("x-masked");
9165 * Returns true if this element is masked
9168 isMasked : function(){
9169 return this._mask && this._mask.isVisible();
9173 * Creates an iframe shim for this element to keep selects and other windowed objects from
9175 * @return {Roo.Element} The new shim element
9177 createShim : function(){
9178 var el = document.createElement('iframe');
9179 el.frameBorder = 'no';
9180 el.className = 'roo-shim';
9181 if(Roo.isIE && Roo.isSecure){
9182 el.src = Roo.SSL_SECURE_URL;
9184 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9185 shim.autoBoxAdjust = false;
9190 * Removes this element from the DOM and deletes it from the cache
9192 remove : function(){
9193 if(this.dom.parentNode){
9194 this.dom.parentNode.removeChild(this.dom);
9196 delete El.cache[this.dom.id];
9200 * Sets up event handlers to add and remove a css class when the mouse is over this element
9201 * @param {String} className
9202 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9203 * mouseout events for children elements
9204 * @return {Roo.Element} this
9206 addClassOnOver : function(className, preventFlicker){
9207 this.on("mouseover", function(){
9208 Roo.fly(this, '_internal').addClass(className);
9210 var removeFn = function(e){
9211 if(preventFlicker !== true || !e.within(this, true)){
9212 Roo.fly(this, '_internal').removeClass(className);
9215 this.on("mouseout", removeFn, this.dom);
9220 * Sets up event handlers to add and remove a css class when this element has the focus
9221 * @param {String} className
9222 * @return {Roo.Element} this
9224 addClassOnFocus : function(className){
9225 this.on("focus", function(){
9226 Roo.fly(this, '_internal').addClass(className);
9228 this.on("blur", function(){
9229 Roo.fly(this, '_internal').removeClass(className);
9234 * 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)
9235 * @param {String} className
9236 * @return {Roo.Element} this
9238 addClassOnClick : function(className){
9240 this.on("mousedown", function(){
9241 Roo.fly(dom, '_internal').addClass(className);
9242 var d = Roo.get(document);
9243 var fn = function(){
9244 Roo.fly(dom, '_internal').removeClass(className);
9245 d.removeListener("mouseup", fn);
9247 d.on("mouseup", fn);
9253 * Stops the specified event from bubbling and optionally prevents the default action
9254 * @param {String} eventName
9255 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9256 * @return {Roo.Element} this
9258 swallowEvent : function(eventName, preventDefault){
9259 var fn = function(e){
9260 e.stopPropagation();
9265 if(eventName instanceof Array){
9266 for(var i = 0, len = eventName.length; i < len; i++){
9267 this.on(eventName[i], fn);
9271 this.on(eventName, fn);
9278 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9281 * Sizes this element to its parent element's dimensions performing
9282 * neccessary box adjustments.
9283 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9284 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9285 * @return {Roo.Element} this
9287 fitToParent : function(monitorResize, targetParent) {
9288 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9289 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9290 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9293 var p = Roo.get(targetParent || this.dom.parentNode);
9294 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9295 if (monitorResize === true) {
9296 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9297 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9303 * Gets the next sibling, skipping text nodes
9304 * @return {HTMLElement} The next sibling or null
9306 getNextSibling : function(){
9307 var n = this.dom.nextSibling;
9308 while(n && n.nodeType != 1){
9315 * Gets the previous sibling, skipping text nodes
9316 * @return {HTMLElement} The previous sibling or null
9318 getPrevSibling : function(){
9319 var n = this.dom.previousSibling;
9320 while(n && n.nodeType != 1){
9321 n = n.previousSibling;
9328 * Appends the passed element(s) to this element
9329 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9330 * @return {Roo.Element} this
9332 appendChild: function(el){
9339 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9340 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9341 * automatically generated with the specified attributes.
9342 * @param {HTMLElement} insertBefore (optional) a child element of this element
9343 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9344 * @return {Roo.Element} The new child element
9346 createChild: function(config, insertBefore, returnDom){
9347 config = config || {tag:'div'};
9349 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9351 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9355 * Appends this element to the passed element
9356 * @param {String/HTMLElement/Element} el The new parent element
9357 * @return {Roo.Element} this
9359 appendTo: function(el){
9360 el = Roo.getDom(el);
9361 el.appendChild(this.dom);
9366 * Inserts this element before the passed element in the DOM
9367 * @param {String/HTMLElement/Element} el The element to insert before
9368 * @return {Roo.Element} this
9370 insertBefore: function(el){
9371 el = Roo.getDom(el);
9372 el.parentNode.insertBefore(this.dom, el);
9377 * Inserts this element after the passed element in the DOM
9378 * @param {String/HTMLElement/Element} el The element to insert after
9379 * @return {Roo.Element} this
9381 insertAfter: function(el){
9382 el = Roo.getDom(el);
9383 el.parentNode.insertBefore(this.dom, el.nextSibling);
9388 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9389 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9390 * @return {Roo.Element} The new child
9392 insertFirst: function(el, returnDom){
9394 if(typeof el == 'object' && !el.nodeType){ // dh config
9395 return this.createChild(el, this.dom.firstChild, returnDom);
9397 el = Roo.getDom(el);
9398 this.dom.insertBefore(el, this.dom.firstChild);
9399 return !returnDom ? Roo.get(el) : el;
9404 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9405 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9406 * @param {String} where (optional) 'before' or 'after' defaults to before
9407 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9408 * @return {Roo.Element} the inserted Element
9410 insertSibling: function(el, where, returnDom){
9411 where = where ? where.toLowerCase() : 'before';
9413 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9415 if(typeof el == 'object' && !el.nodeType){ // dh config
9416 if(where == 'after' && !this.dom.nextSibling){
9417 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9419 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9423 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9424 where == 'before' ? this.dom : this.dom.nextSibling);
9433 * Creates and wraps this element with another element
9434 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9435 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9436 * @return {HTMLElement/Element} The newly created wrapper element
9438 wrap: function(config, returnDom){
9440 config = {tag: "div"};
9442 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9443 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9448 * Replaces the passed element with this element
9449 * @param {String/HTMLElement/Element} el The element to replace
9450 * @return {Roo.Element} this
9452 replace: function(el){
9454 this.insertBefore(el);
9460 * Inserts an html fragment into this element
9461 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9462 * @param {String} html The HTML fragment
9463 * @param {Boolean} returnEl True to return an Roo.Element
9464 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9466 insertHtml : function(where, html, returnEl){
9467 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9468 return returnEl ? Roo.get(el) : el;
9472 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9473 * @param {Object} o The object with the attributes
9474 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9475 * @return {Roo.Element} this
9477 set : function(o, useSet){
9479 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9481 if(attr == "style" || typeof o[attr] == "function") { continue; }
9483 el.className = o["cls"];
9486 el.setAttribute(attr, o[attr]);
9493 Roo.DomHelper.applyStyles(el, o.style);
9499 * Convenience method for constructing a KeyMap
9500 * @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:
9501 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9502 * @param {Function} fn The function to call
9503 * @param {Object} scope (optional) The scope of the function
9504 * @return {Roo.KeyMap} The KeyMap created
9506 addKeyListener : function(key, fn, scope){
9508 if(typeof key != "object" || key instanceof Array){
9524 return new Roo.KeyMap(this, config);
9528 * Creates a KeyMap for this element
9529 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9530 * @return {Roo.KeyMap} The KeyMap created
9532 addKeyMap : function(config){
9533 return new Roo.KeyMap(this, config);
9537 * Returns true if this element is scrollable.
9540 isScrollable : function(){
9542 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9546 * 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().
9547 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9548 * @param {Number} value The new scroll value
9549 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9550 * @return {Element} this
9553 scrollTo : function(side, value, animate){
9554 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9556 this.dom[prop] = value;
9558 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9559 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9565 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9566 * within this element's scrollable range.
9567 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9568 * @param {Number} distance How far to scroll the element in pixels
9569 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9570 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9571 * was scrolled as far as it could go.
9573 scroll : function(direction, distance, animate){
9574 if(!this.isScrollable()){
9578 var l = el.scrollLeft, t = el.scrollTop;
9579 var w = el.scrollWidth, h = el.scrollHeight;
9580 var cw = el.clientWidth, ch = el.clientHeight;
9581 direction = direction.toLowerCase();
9582 var scrolled = false;
9583 var a = this.preanim(arguments, 2);
9588 var v = Math.min(l + distance, w-cw);
9589 this.scrollTo("left", v, a);
9596 var v = Math.max(l - distance, 0);
9597 this.scrollTo("left", v, a);
9605 var v = Math.max(t - distance, 0);
9606 this.scrollTo("top", v, a);
9614 var v = Math.min(t + distance, h-ch);
9615 this.scrollTo("top", v, a);
9624 * Translates the passed page coordinates into left/top css values for this element
9625 * @param {Number/Array} x The page x or an array containing [x, y]
9626 * @param {Number} y The page y
9627 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9629 translatePoints : function(x, y){
9630 if(typeof x == 'object' || x instanceof Array){
9633 var p = this.getStyle('position');
9634 var o = this.getXY();
9636 var l = parseInt(this.getStyle('left'), 10);
9637 var t = parseInt(this.getStyle('top'), 10);
9640 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9643 t = (p == "relative") ? 0 : this.dom.offsetTop;
9646 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9650 * Returns the current scroll position of the element.
9651 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9653 getScroll : function(){
9654 var d = this.dom, doc = document;
9655 if(d == doc || d == doc.body){
9656 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9657 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9658 return {left: l, top: t};
9660 return {left: d.scrollLeft, top: d.scrollTop};
9665 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9666 * are convert to standard 6 digit hex color.
9667 * @param {String} attr The css attribute
9668 * @param {String} defaultValue The default value to use when a valid color isn't found
9669 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9672 getColor : function(attr, defaultValue, prefix){
9673 var v = this.getStyle(attr);
9674 if(!v || v == "transparent" || v == "inherit") {
9675 return defaultValue;
9677 var color = typeof prefix == "undefined" ? "#" : prefix;
9678 if(v.substr(0, 4) == "rgb("){
9679 var rvs = v.slice(4, v.length -1).split(",");
9680 for(var i = 0; i < 3; i++){
9681 var h = parseInt(rvs[i]).toString(16);
9688 if(v.substr(0, 1) == "#"){
9690 for(var i = 1; i < 4; i++){
9691 var c = v.charAt(i);
9694 }else if(v.length == 7){
9695 color += v.substr(1);
9699 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9703 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9704 * gradient background, rounded corners and a 4-way shadow.
9705 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9706 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9707 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9708 * @return {Roo.Element} this
9710 boxWrap : function(cls){
9711 cls = cls || 'x-box';
9712 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9713 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9718 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9719 * @param {String} namespace The namespace in which to look for the attribute
9720 * @param {String} name The attribute name
9721 * @return {String} The attribute value
9723 getAttributeNS : Roo.isIE ? function(ns, name){
9725 var type = typeof d[ns+":"+name];
9726 if(type != 'undefined' && type != 'unknown'){
9727 return d[ns+":"+name];
9730 } : function(ns, name){
9732 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9737 * Sets or Returns the value the dom attribute value
9738 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9739 * @param {String} value (optional) The value to set the attribute to
9740 * @return {String} The attribute value
9742 attr : function(name){
9743 if (arguments.length > 1) {
9744 this.dom.setAttribute(name, arguments[1]);
9745 return arguments[1];
9747 if (typeof(name) == 'object') {
9748 for(var i in name) {
9749 this.attr(i, name[i]);
9755 if (!this.dom.hasAttribute(name)) {
9758 return this.dom.getAttribute(name);
9765 var ep = El.prototype;
9768 * Appends an event handler (Shorthand for addListener)
9769 * @param {String} eventName The type of event to append
9770 * @param {Function} fn The method the event invokes
9771 * @param {Object} scope (optional) The scope (this object) of the fn
9772 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9775 ep.on = ep.addListener;
9777 ep.mon = ep.addListener;
9780 * Removes an event handler from this element (shorthand for removeListener)
9781 * @param {String} eventName the type of event to remove
9782 * @param {Function} fn the method the event invokes
9783 * @return {Roo.Element} this
9786 ep.un = ep.removeListener;
9789 * true to automatically adjust width and height settings for box-model issues (default to true)
9791 ep.autoBoxAdjust = true;
9794 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9797 El.addUnits = function(v, defaultUnit){
9798 if(v === "" || v == "auto"){
9801 if(v === undefined){
9804 if(typeof v == "number" || !El.unitPattern.test(v)){
9805 return v + (defaultUnit || 'px');
9810 // special markup used throughout Roo when box wrapping elements
9811 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>';
9813 * Visibility mode constant - Use visibility to hide element
9819 * Visibility mode constant - Use display to hide element
9825 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9826 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9827 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9839 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9840 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9841 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9842 * @return {Element} The Element object
9845 El.get = function(el){
9847 if(!el){ return null; }
9848 if(typeof el == "string"){ // element id
9849 if(!(elm = document.getElementById(el))){
9852 if(ex = El.cache[el]){
9855 ex = El.cache[el] = new El(elm);
9858 }else if(el.tagName){ // dom element
9862 if(ex = El.cache[id]){
9865 ex = El.cache[id] = new El(el);
9868 }else if(el instanceof El){
9870 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9871 // catch case where it hasn't been appended
9872 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9875 }else if(el.isComposite){
9877 }else if(el instanceof Array){
9878 return El.select(el);
9879 }else if(el == document){
9880 // create a bogus element object representing the document object
9882 var f = function(){};
9883 f.prototype = El.prototype;
9885 docEl.dom = document;
9893 El.uncache = function(el){
9894 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9896 delete El.cache[a[i].id || a[i]];
9902 // Garbage collection - uncache elements/purge listeners on orphaned elements
9903 // so we don't hold a reference and cause the browser to retain them
9904 El.garbageCollect = function(){
9905 if(!Roo.enableGarbageCollector){
9906 clearInterval(El.collectorThread);
9909 for(var eid in El.cache){
9910 var el = El.cache[eid], d = el.dom;
9911 // -------------------------------------------------------
9912 // Determining what is garbage:
9913 // -------------------------------------------------------
9915 // dom node is null, definitely garbage
9916 // -------------------------------------------------------
9918 // no parentNode == direct orphan, definitely garbage
9919 // -------------------------------------------------------
9920 // !d.offsetParent && !document.getElementById(eid)
9921 // display none elements have no offsetParent so we will
9922 // also try to look it up by it's id. However, check
9923 // offsetParent first so we don't do unneeded lookups.
9924 // This enables collection of elements that are not orphans
9925 // directly, but somewhere up the line they have an orphan
9927 // -------------------------------------------------------
9928 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9929 delete El.cache[eid];
9930 if(d && Roo.enableListenerCollection){
9936 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9940 El.Flyweight = function(dom){
9943 El.Flyweight.prototype = El.prototype;
9945 El._flyweights = {};
9947 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9948 * the dom node can be overwritten by other code.
9949 * @param {String/HTMLElement} el The dom node or id
9950 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9951 * prevent conflicts (e.g. internally Roo uses "_internal")
9953 * @return {Element} The shared Element object
9955 El.fly = function(el, named){
9956 named = named || '_global';
9957 el = Roo.getDom(el);
9961 if(!El._flyweights[named]){
9962 El._flyweights[named] = new El.Flyweight();
9964 El._flyweights[named].dom = el;
9965 return El._flyweights[named];
9969 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9970 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9971 * Shorthand of {@link Roo.Element#get}
9972 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9973 * @return {Element} The Element object
9979 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9980 * the dom node can be overwritten by other code.
9981 * Shorthand of {@link Roo.Element#fly}
9982 * @param {String/HTMLElement} el The dom node or id
9983 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9984 * prevent conflicts (e.g. internally Roo uses "_internal")
9986 * @return {Element} The shared Element object
9992 // speedy lookup for elements never to box adjust
9993 var noBoxAdjust = Roo.isStrict ? {
9996 input:1, select:1, textarea:1
9998 if(Roo.isIE || Roo.isGecko){
9999 noBoxAdjust['button'] = 1;
10003 Roo.EventManager.on(window, 'unload', function(){
10005 delete El._flyweights;
10013 Roo.Element.selectorFunction = Roo.DomQuery.select;
10016 Roo.Element.select = function(selector, unique, root){
10018 if(typeof selector == "string"){
10019 els = Roo.Element.selectorFunction(selector, root);
10020 }else if(selector.length !== undefined){
10023 throw "Invalid selector";
10025 if(unique === true){
10026 return new Roo.CompositeElement(els);
10028 return new Roo.CompositeElementLite(els);
10032 * Selects elements based on the passed CSS selector to enable working on them as 1.
10033 * @param {String/Array} selector The CSS selector or an array of elements
10034 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
10035 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
10036 * @return {CompositeElementLite/CompositeElement}
10040 Roo.select = Roo.Element.select;
10057 * Ext JS Library 1.1.1
10058 * Copyright(c) 2006-2007, Ext JS, LLC.
10060 * Originally Released Under LGPL - original licence link has changed is not relivant.
10063 * <script type="text/javascript">
10068 //Notifies Element that fx methods are available
10069 Roo.enableFx = true;
10073 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
10074 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
10075 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
10076 * Element effects to work.</p><br/>
10078 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
10079 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
10080 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
10081 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
10082 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
10083 * expected results and should be done with care.</p><br/>
10085 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
10086 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
10089 ----- -----------------------------
10090 tl The top left corner
10091 t The center of the top edge
10092 tr The top right corner
10093 l The center of the left edge
10094 r The center of the right edge
10095 bl The bottom left corner
10096 b The center of the bottom edge
10097 br The bottom right corner
10099 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
10100 * below are common options that can be passed to any Fx method.</b>
10101 * @cfg {Function} callback A function called when the effect is finished
10102 * @cfg {Object} scope The scope of the effect function
10103 * @cfg {String} easing A valid Easing value for the effect
10104 * @cfg {String} afterCls A css class to apply after the effect
10105 * @cfg {Number} duration The length of time (in seconds) that the effect should last
10106 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
10107 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
10108 * effects that end with the element being visually hidden, ignored otherwise)
10109 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
10110 * a function which returns such a specification that will be applied to the Element after the effect finishes
10111 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
10112 * @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
10113 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10117 * Slides the element into view. An anchor point can be optionally passed to set the point of
10118 * origin for the slide effect. This function automatically handles wrapping the element with
10119 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10122 // default: slide the element in from the top
10125 // custom: slide the element in from the right with a 2-second duration
10126 el.slideIn('r', { duration: 2 });
10128 // common config options shown with default values
10134 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10135 * @param {Object} options (optional) Object literal with any of the Fx config options
10136 * @return {Roo.Element} The Element
10138 slideIn : function(anchor, o){
10139 var el = this.getFxEl();
10142 el.queueFx(o, function(){
10144 anchor = anchor || "t";
10146 // fix display to visibility
10149 // restore values after effect
10150 var r = this.getFxRestore();
10151 var b = this.getBox();
10152 // fixed size for slide
10156 var wrap = this.fxWrap(r.pos, o, "hidden");
10158 var st = this.dom.style;
10159 st.visibility = "visible";
10160 st.position = "absolute";
10162 // clear out temp styles after slide and unwrap
10163 var after = function(){
10164 el.fxUnwrap(wrap, r.pos, o);
10165 st.width = r.width;
10166 st.height = r.height;
10169 // time to calc the positions
10170 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10172 switch(anchor.toLowerCase()){
10174 wrap.setSize(b.width, 0);
10175 st.left = st.bottom = "0";
10179 wrap.setSize(0, b.height);
10180 st.right = st.top = "0";
10184 wrap.setSize(0, b.height);
10185 wrap.setX(b.right);
10186 st.left = st.top = "0";
10187 a = {width: bw, points: pt};
10190 wrap.setSize(b.width, 0);
10191 wrap.setY(b.bottom);
10192 st.left = st.top = "0";
10193 a = {height: bh, points: pt};
10196 wrap.setSize(0, 0);
10197 st.right = st.bottom = "0";
10198 a = {width: bw, height: bh};
10201 wrap.setSize(0, 0);
10202 wrap.setY(b.y+b.height);
10203 st.right = st.top = "0";
10204 a = {width: bw, height: bh, points: pt};
10207 wrap.setSize(0, 0);
10208 wrap.setXY([b.right, b.bottom]);
10209 st.left = st.top = "0";
10210 a = {width: bw, height: bh, points: pt};
10213 wrap.setSize(0, 0);
10214 wrap.setX(b.x+b.width);
10215 st.left = st.bottom = "0";
10216 a = {width: bw, height: bh, points: pt};
10219 this.dom.style.visibility = "visible";
10222 arguments.callee.anim = wrap.fxanim(a,
10232 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10233 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10234 * 'hidden') but block elements will still take up space in the document. The element must be removed
10235 * from the DOM using the 'remove' config option if desired. This function automatically handles
10236 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10239 // default: slide the element out to the top
10242 // custom: slide the element out to the right with a 2-second duration
10243 el.slideOut('r', { duration: 2 });
10245 // common config options shown with default values
10253 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10254 * @param {Object} options (optional) Object literal with any of the Fx config options
10255 * @return {Roo.Element} The Element
10257 slideOut : function(anchor, o){
10258 var el = this.getFxEl();
10261 el.queueFx(o, function(){
10263 anchor = anchor || "t";
10265 // restore values after effect
10266 var r = this.getFxRestore();
10268 var b = this.getBox();
10269 // fixed size for slide
10273 var wrap = this.fxWrap(r.pos, o, "visible");
10275 var st = this.dom.style;
10276 st.visibility = "visible";
10277 st.position = "absolute";
10281 var after = function(){
10283 el.setDisplayed(false);
10288 el.fxUnwrap(wrap, r.pos, o);
10290 st.width = r.width;
10291 st.height = r.height;
10296 var a, zero = {to: 0};
10297 switch(anchor.toLowerCase()){
10299 st.left = st.bottom = "0";
10300 a = {height: zero};
10303 st.right = st.top = "0";
10307 st.left = st.top = "0";
10308 a = {width: zero, points: {to:[b.right, b.y]}};
10311 st.left = st.top = "0";
10312 a = {height: zero, points: {to:[b.x, b.bottom]}};
10315 st.right = st.bottom = "0";
10316 a = {width: zero, height: zero};
10319 st.right = st.top = "0";
10320 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10323 st.left = st.top = "0";
10324 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10327 st.left = st.bottom = "0";
10328 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10332 arguments.callee.anim = wrap.fxanim(a,
10342 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10343 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10344 * The element must be removed from the DOM using the 'remove' config option if desired.
10350 // common config options shown with default values
10358 * @param {Object} options (optional) Object literal with any of the Fx config options
10359 * @return {Roo.Element} The Element
10361 puff : function(o){
10362 var el = this.getFxEl();
10365 el.queueFx(o, function(){
10366 this.clearOpacity();
10369 // restore values after effect
10370 var r = this.getFxRestore();
10371 var st = this.dom.style;
10373 var after = function(){
10375 el.setDisplayed(false);
10382 el.setPositioning(r.pos);
10383 st.width = r.width;
10384 st.height = r.height;
10389 var width = this.getWidth();
10390 var height = this.getHeight();
10392 arguments.callee.anim = this.fxanim({
10393 width : {to: this.adjustWidth(width * 2)},
10394 height : {to: this.adjustHeight(height * 2)},
10395 points : {by: [-(width * .5), -(height * .5)]},
10397 fontSize: {to:200, unit: "%"}
10408 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10409 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10410 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10416 // all config options shown with default values
10424 * @param {Object} options (optional) Object literal with any of the Fx config options
10425 * @return {Roo.Element} The Element
10427 switchOff : function(o){
10428 var el = this.getFxEl();
10431 el.queueFx(o, function(){
10432 this.clearOpacity();
10435 // restore values after effect
10436 var r = this.getFxRestore();
10437 var st = this.dom.style;
10439 var after = function(){
10441 el.setDisplayed(false);
10447 el.setPositioning(r.pos);
10448 st.width = r.width;
10449 st.height = r.height;
10454 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10455 this.clearOpacity();
10459 points:{by:[0, this.getHeight() * .5]}
10460 }, o, 'motion', 0.3, 'easeIn', after);
10461 }).defer(100, this);
10468 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10469 * changed using the "attr" config option) and then fading back to the original color. If no original
10470 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10473 // default: highlight background to yellow
10476 // custom: highlight foreground text to blue for 2 seconds
10477 el.highlight("0000ff", { attr: 'color', duration: 2 });
10479 // common config options shown with default values
10480 el.highlight("ffff9c", {
10481 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10482 endColor: (current color) or "ffffff",
10487 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10488 * @param {Object} options (optional) Object literal with any of the Fx config options
10489 * @return {Roo.Element} The Element
10491 highlight : function(color, o){
10492 var el = this.getFxEl();
10495 el.queueFx(o, function(){
10496 color = color || "ffff9c";
10497 attr = o.attr || "backgroundColor";
10499 this.clearOpacity();
10502 var origColor = this.getColor(attr);
10503 var restoreColor = this.dom.style[attr];
10504 endColor = (o.endColor || origColor) || "ffffff";
10506 var after = function(){
10507 el.dom.style[attr] = restoreColor;
10512 a[attr] = {from: color, to: endColor};
10513 arguments.callee.anim = this.fxanim(a,
10523 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10526 // default: a single light blue ripple
10529 // custom: 3 red ripples lasting 3 seconds total
10530 el.frame("ff0000", 3, { duration: 3 });
10532 // common config options shown with default values
10533 el.frame("C3DAF9", 1, {
10534 duration: 1 //duration of entire animation (not each individual ripple)
10535 // Note: Easing is not configurable and will be ignored if included
10538 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10539 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10540 * @param {Object} options (optional) Object literal with any of the Fx config options
10541 * @return {Roo.Element} The Element
10543 frame : function(color, count, o){
10544 var el = this.getFxEl();
10547 el.queueFx(o, function(){
10548 color = color || "#C3DAF9";
10549 if(color.length == 6){
10550 color = "#" + color;
10552 count = count || 1;
10553 duration = o.duration || 1;
10556 var b = this.getBox();
10557 var animFn = function(){
10558 var proxy = this.createProxy({
10561 visbility:"hidden",
10562 position:"absolute",
10563 "z-index":"35000", // yee haw
10564 border:"0px solid " + color
10567 var scale = Roo.isBorderBox ? 2 : 1;
10569 top:{from:b.y, to:b.y - 20},
10570 left:{from:b.x, to:b.x - 20},
10571 borderWidth:{from:0, to:10},
10572 opacity:{from:1, to:0},
10573 height:{from:b.height, to:(b.height + (20*scale))},
10574 width:{from:b.width, to:(b.width + (20*scale))}
10575 }, duration, function(){
10579 animFn.defer((duration/2)*1000, this);
10590 * Creates a pause before any subsequent queued effects begin. If there are
10591 * no effects queued after the pause it will have no effect.
10596 * @param {Number} seconds The length of time to pause (in seconds)
10597 * @return {Roo.Element} The Element
10599 pause : function(seconds){
10600 var el = this.getFxEl();
10603 el.queueFx(o, function(){
10604 setTimeout(function(){
10606 }, seconds * 1000);
10612 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10613 * using the "endOpacity" config option.
10616 // default: fade in from opacity 0 to 100%
10619 // custom: fade in from opacity 0 to 75% over 2 seconds
10620 el.fadeIn({ endOpacity: .75, duration: 2});
10622 // common config options shown with default values
10624 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10629 * @param {Object} options (optional) Object literal with any of the Fx config options
10630 * @return {Roo.Element} The Element
10632 fadeIn : function(o){
10633 var el = this.getFxEl();
10635 el.queueFx(o, function(){
10636 this.setOpacity(0);
10638 this.dom.style.visibility = 'visible';
10639 var to = o.endOpacity || 1;
10640 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10641 o, null, .5, "easeOut", function(){
10643 this.clearOpacity();
10652 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10653 * using the "endOpacity" config option.
10656 // default: fade out from the element's current opacity to 0
10659 // custom: fade out from the element's current opacity to 25% over 2 seconds
10660 el.fadeOut({ endOpacity: .25, duration: 2});
10662 // common config options shown with default values
10664 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10671 * @param {Object} options (optional) Object literal with any of the Fx config options
10672 * @return {Roo.Element} The Element
10674 fadeOut : function(o){
10675 var el = this.getFxEl();
10677 el.queueFx(o, function(){
10678 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10679 o, null, .5, "easeOut", function(){
10680 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10681 this.dom.style.display = "none";
10683 this.dom.style.visibility = "hidden";
10685 this.clearOpacity();
10693 * Animates the transition of an element's dimensions from a starting height/width
10694 * to an ending height/width.
10697 // change height and width to 100x100 pixels
10698 el.scale(100, 100);
10700 // common config options shown with default values. The height and width will default to
10701 // the element's existing values if passed as null.
10704 [element's height], {
10709 * @param {Number} width The new width (pass undefined to keep the original width)
10710 * @param {Number} height The new height (pass undefined to keep the original height)
10711 * @param {Object} options (optional) Object literal with any of the Fx config options
10712 * @return {Roo.Element} The Element
10714 scale : function(w, h, o){
10715 this.shift(Roo.apply({}, o, {
10723 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10724 * Any of these properties not specified in the config object will not be changed. This effect
10725 * requires that at least one new dimension, position or opacity setting must be passed in on
10726 * the config object in order for the function to have any effect.
10729 // slide the element horizontally to x position 200 while changing the height and opacity
10730 el.shift({ x: 200, height: 50, opacity: .8 });
10732 // common config options shown with default values.
10734 width: [element's width],
10735 height: [element's height],
10736 x: [element's x position],
10737 y: [element's y position],
10738 opacity: [element's opacity],
10743 * @param {Object} options Object literal with any of the Fx config options
10744 * @return {Roo.Element} The Element
10746 shift : function(o){
10747 var el = this.getFxEl();
10749 el.queueFx(o, function(){
10750 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10751 if(w !== undefined){
10752 a.width = {to: this.adjustWidth(w)};
10754 if(h !== undefined){
10755 a.height = {to: this.adjustHeight(h)};
10757 if(x !== undefined || y !== undefined){
10759 x !== undefined ? x : this.getX(),
10760 y !== undefined ? y : this.getY()
10763 if(op !== undefined){
10764 a.opacity = {to: op};
10766 if(o.xy !== undefined){
10767 a.points = {to: o.xy};
10769 arguments.callee.anim = this.fxanim(a,
10770 o, 'motion', .35, "easeOut", function(){
10778 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10779 * ending point of the effect.
10782 // default: slide the element downward while fading out
10785 // custom: slide the element out to the right with a 2-second duration
10786 el.ghost('r', { duration: 2 });
10788 // common config options shown with default values
10796 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10797 * @param {Object} options (optional) Object literal with any of the Fx config options
10798 * @return {Roo.Element} The Element
10800 ghost : function(anchor, o){
10801 var el = this.getFxEl();
10804 el.queueFx(o, function(){
10805 anchor = anchor || "b";
10807 // restore values after effect
10808 var r = this.getFxRestore();
10809 var w = this.getWidth(),
10810 h = this.getHeight();
10812 var st = this.dom.style;
10814 var after = function(){
10816 el.setDisplayed(false);
10822 el.setPositioning(r.pos);
10823 st.width = r.width;
10824 st.height = r.height;
10829 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10830 switch(anchor.toLowerCase()){
10857 arguments.callee.anim = this.fxanim(a,
10867 * Ensures that all effects queued after syncFx is called on the element are
10868 * run concurrently. This is the opposite of {@link #sequenceFx}.
10869 * @return {Roo.Element} The Element
10871 syncFx : function(){
10872 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10881 * Ensures that all effects queued after sequenceFx is called on the element are
10882 * run in sequence. This is the opposite of {@link #syncFx}.
10883 * @return {Roo.Element} The Element
10885 sequenceFx : function(){
10886 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10888 concurrent : false,
10895 nextFx : function(){
10896 var ef = this.fxQueue[0];
10903 * Returns true if the element has any effects actively running or queued, else returns false.
10904 * @return {Boolean} True if element has active effects, else false
10906 hasActiveFx : function(){
10907 return this.fxQueue && this.fxQueue[0];
10911 * Stops any running effects and clears the element's internal effects queue if it contains
10912 * any additional effects that haven't started yet.
10913 * @return {Roo.Element} The Element
10915 stopFx : function(){
10916 if(this.hasActiveFx()){
10917 var cur = this.fxQueue[0];
10918 if(cur && cur.anim && cur.anim.isAnimated()){
10919 this.fxQueue = [cur]; // clear out others
10920 cur.anim.stop(true);
10927 beforeFx : function(o){
10928 if(this.hasActiveFx() && !o.concurrent){
10939 * Returns true if the element is currently blocking so that no other effect can be queued
10940 * until this effect is finished, else returns false if blocking is not set. This is commonly
10941 * used to ensure that an effect initiated by a user action runs to completion prior to the
10942 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10943 * @return {Boolean} True if blocking, else false
10945 hasFxBlock : function(){
10946 var q = this.fxQueue;
10947 return q && q[0] && q[0].block;
10951 queueFx : function(o, fn){
10955 if(!this.hasFxBlock()){
10956 Roo.applyIf(o, this.fxDefaults);
10958 var run = this.beforeFx(o);
10959 fn.block = o.block;
10960 this.fxQueue.push(fn);
10972 fxWrap : function(pos, o, vis){
10974 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10977 wrapXY = this.getXY();
10979 var div = document.createElement("div");
10980 div.style.visibility = vis;
10981 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10982 wrap.setPositioning(pos);
10983 if(wrap.getStyle("position") == "static"){
10984 wrap.position("relative");
10986 this.clearPositioning('auto');
10988 wrap.dom.appendChild(this.dom);
10990 wrap.setXY(wrapXY);
10997 fxUnwrap : function(wrap, pos, o){
10998 this.clearPositioning();
10999 this.setPositioning(pos);
11001 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
11007 getFxRestore : function(){
11008 var st = this.dom.style;
11009 return {pos: this.getPositioning(), width: st.width, height : st.height};
11013 afterFx : function(o){
11015 this.applyStyles(o.afterStyle);
11018 this.addClass(o.afterCls);
11020 if(o.remove === true){
11023 Roo.callback(o.callback, o.scope, [this]);
11025 this.fxQueue.shift();
11031 getFxEl : function(){ // support for composite element fx
11032 return Roo.get(this.dom);
11036 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
11037 animType = animType || 'run';
11039 var anim = Roo.lib.Anim[animType](
11041 (opt.duration || defaultDur) || .35,
11042 (opt.easing || defaultEase) || 'easeOut',
11044 Roo.callback(cb, this);
11053 // backwords compat
11054 Roo.Fx.resize = Roo.Fx.scale;
11056 //When included, Roo.Fx is automatically applied to Element so that all basic
11057 //effects are available directly via the Element API
11058 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
11060 * Ext JS Library 1.1.1
11061 * Copyright(c) 2006-2007, Ext JS, LLC.
11063 * Originally Released Under LGPL - original licence link has changed is not relivant.
11066 * <script type="text/javascript">
11071 * @class Roo.CompositeElement
11072 * Standard composite class. Creates a Roo.Element for every element in the collection.
11074 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11075 * actions will be performed on all the elements in this collection.</b>
11077 * All methods return <i>this</i> and can be chained.
11079 var els = Roo.select("#some-el div.some-class", true);
11080 // or select directly from an existing element
11081 var el = Roo.get('some-el');
11082 el.select('div.some-class', true);
11084 els.setWidth(100); // all elements become 100 width
11085 els.hide(true); // all elements fade out and hide
11087 els.setWidth(100).hide(true);
11090 Roo.CompositeElement = function(els){
11091 this.elements = [];
11092 this.addElements(els);
11094 Roo.CompositeElement.prototype = {
11096 addElements : function(els){
11100 if(typeof els == "string"){
11101 els = Roo.Element.selectorFunction(els);
11103 var yels = this.elements;
11104 var index = yels.length-1;
11105 for(var i = 0, len = els.length; i < len; i++) {
11106 yels[++index] = Roo.get(els[i]);
11112 * Clears this composite and adds the elements returned by the passed selector.
11113 * @param {String/Array} els A string CSS selector, an array of elements or an element
11114 * @return {CompositeElement} this
11116 fill : function(els){
11117 this.elements = [];
11123 * Filters this composite to only elements that match the passed selector.
11124 * @param {String} selector A string CSS selector
11125 * @param {Boolean} inverse return inverse filter (not matches)
11126 * @return {CompositeElement} this
11128 filter : function(selector, inverse){
11130 inverse = inverse || false;
11131 this.each(function(el){
11132 var match = inverse ? !el.is(selector) : el.is(selector);
11134 els[els.length] = el.dom;
11141 invoke : function(fn, args){
11142 var els = this.elements;
11143 for(var i = 0, len = els.length; i < len; i++) {
11144 Roo.Element.prototype[fn].apply(els[i], args);
11149 * Adds elements to this composite.
11150 * @param {String/Array} els A string CSS selector, an array of elements or an element
11151 * @return {CompositeElement} this
11153 add : function(els){
11154 if(typeof els == "string"){
11155 this.addElements(Roo.Element.selectorFunction(els));
11156 }else if(els.length !== undefined){
11157 this.addElements(els);
11159 this.addElements([els]);
11164 * Calls the passed function passing (el, this, index) for each element in this composite.
11165 * @param {Function} fn The function to call
11166 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11167 * @return {CompositeElement} this
11169 each : function(fn, scope){
11170 var els = this.elements;
11171 for(var i = 0, len = els.length; i < len; i++){
11172 if(fn.call(scope || els[i], els[i], this, i) === false) {
11180 * Returns the Element object at the specified index
11181 * @param {Number} index
11182 * @return {Roo.Element}
11184 item : function(index){
11185 return this.elements[index] || null;
11189 * Returns the first Element
11190 * @return {Roo.Element}
11192 first : function(){
11193 return this.item(0);
11197 * Returns the last Element
11198 * @return {Roo.Element}
11201 return this.item(this.elements.length-1);
11205 * Returns the number of elements in this composite
11208 getCount : function(){
11209 return this.elements.length;
11213 * Returns true if this composite contains the passed element
11216 contains : function(el){
11217 return this.indexOf(el) !== -1;
11221 * Returns true if this composite contains the passed element
11224 indexOf : function(el){
11225 return this.elements.indexOf(Roo.get(el));
11230 * Removes the specified element(s).
11231 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11232 * or an array of any of those.
11233 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11234 * @return {CompositeElement} this
11236 removeElement : function(el, removeDom){
11237 if(el instanceof Array){
11238 for(var i = 0, len = el.length; i < len; i++){
11239 this.removeElement(el[i]);
11243 var index = typeof el == 'number' ? el : this.indexOf(el);
11246 var d = this.elements[index];
11250 d.parentNode.removeChild(d);
11253 this.elements.splice(index, 1);
11259 * Replaces the specified element with the passed element.
11260 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11262 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11263 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11264 * @return {CompositeElement} this
11266 replaceElement : function(el, replacement, domReplace){
11267 var index = typeof el == 'number' ? el : this.indexOf(el);
11270 this.elements[index].replaceWith(replacement);
11272 this.elements.splice(index, 1, Roo.get(replacement))
11279 * Removes all elements.
11281 clear : function(){
11282 this.elements = [];
11286 Roo.CompositeElement.createCall = function(proto, fnName){
11287 if(!proto[fnName]){
11288 proto[fnName] = function(){
11289 return this.invoke(fnName, arguments);
11293 for(var fnName in Roo.Element.prototype){
11294 if(typeof Roo.Element.prototype[fnName] == "function"){
11295 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11301 * Ext JS Library 1.1.1
11302 * Copyright(c) 2006-2007, Ext JS, LLC.
11304 * Originally Released Under LGPL - original licence link has changed is not relivant.
11307 * <script type="text/javascript">
11311 * @class Roo.CompositeElementLite
11312 * @extends Roo.CompositeElement
11313 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11315 var els = Roo.select("#some-el div.some-class");
11316 // or select directly from an existing element
11317 var el = Roo.get('some-el');
11318 el.select('div.some-class');
11320 els.setWidth(100); // all elements become 100 width
11321 els.hide(true); // all elements fade out and hide
11323 els.setWidth(100).hide(true);
11324 </code></pre><br><br>
11325 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11326 * actions will be performed on all the elements in this collection.</b>
11328 Roo.CompositeElementLite = function(els){
11329 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11330 this.el = new Roo.Element.Flyweight();
11332 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11333 addElements : function(els){
11335 if(els instanceof Array){
11336 this.elements = this.elements.concat(els);
11338 var yels = this.elements;
11339 var index = yels.length-1;
11340 for(var i = 0, len = els.length; i < len; i++) {
11341 yels[++index] = els[i];
11347 invoke : function(fn, args){
11348 var els = this.elements;
11350 for(var i = 0, len = els.length; i < len; i++) {
11352 Roo.Element.prototype[fn].apply(el, args);
11357 * Returns a flyweight Element of the dom element object at the specified index
11358 * @param {Number} index
11359 * @return {Roo.Element}
11361 item : function(index){
11362 if(!this.elements[index]){
11365 this.el.dom = this.elements[index];
11369 // fixes scope with flyweight
11370 addListener : function(eventName, handler, scope, opt){
11371 var els = this.elements;
11372 for(var i = 0, len = els.length; i < len; i++) {
11373 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11379 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11380 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11381 * a reference to the dom node, use el.dom.</b>
11382 * @param {Function} fn The function to call
11383 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11384 * @return {CompositeElement} this
11386 each : function(fn, scope){
11387 var els = this.elements;
11389 for(var i = 0, len = els.length; i < len; i++){
11391 if(fn.call(scope || el, el, this, i) === false){
11398 indexOf : function(el){
11399 return this.elements.indexOf(Roo.getDom(el));
11402 replaceElement : function(el, replacement, domReplace){
11403 var index = typeof el == 'number' ? el : this.indexOf(el);
11405 replacement = Roo.getDom(replacement);
11407 var d = this.elements[index];
11408 d.parentNode.insertBefore(replacement, d);
11409 d.parentNode.removeChild(d);
11411 this.elements.splice(index, 1, replacement);
11416 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11420 * Ext JS Library 1.1.1
11421 * Copyright(c) 2006-2007, Ext JS, LLC.
11423 * Originally Released Under LGPL - original licence link has changed is not relivant.
11426 * <script type="text/javascript">
11432 * @class Roo.data.Connection
11433 * @extends Roo.util.Observable
11434 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11435 * either to a configured URL, or to a URL specified at request time.<br><br>
11437 * Requests made by this class are asynchronous, and will return immediately. No data from
11438 * the server will be available to the statement immediately following the {@link #request} call.
11439 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11441 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11442 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11443 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11444 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11445 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11446 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11447 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11448 * standard DOM methods.
11450 * @param {Object} config a configuration object.
11452 Roo.data.Connection = function(config){
11453 Roo.apply(this, config);
11456 * @event beforerequest
11457 * Fires before a network request is made to retrieve a data object.
11458 * @param {Connection} conn This Connection object.
11459 * @param {Object} options The options config object passed to the {@link #request} method.
11461 "beforerequest" : true,
11463 * @event requestcomplete
11464 * Fires if the request was successfully completed.
11465 * @param {Connection} conn This Connection object.
11466 * @param {Object} response The XHR object containing the response data.
11467 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11468 * @param {Object} options The options config object passed to the {@link #request} method.
11470 "requestcomplete" : true,
11472 * @event requestexception
11473 * Fires if an error HTTP status was returned from the server.
11474 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11475 * @param {Connection} conn This Connection object.
11476 * @param {Object} response The XHR object containing the response data.
11477 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11478 * @param {Object} options The options config object passed to the {@link #request} method.
11480 "requestexception" : true
11482 Roo.data.Connection.superclass.constructor.call(this);
11485 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11487 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11490 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11491 * extra parameters to each request made by this object. (defaults to undefined)
11494 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11495 * to each request made by this object. (defaults to undefined)
11498 * @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)
11501 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11505 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11511 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11514 disableCaching: true,
11517 * Sends an HTTP request to a remote server.
11518 * @param {Object} options An object which may contain the following properties:<ul>
11519 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11520 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11521 * request, a url encoded string or a function to call to get either.</li>
11522 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11523 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11524 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11525 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11526 * <li>options {Object} The parameter to the request call.</li>
11527 * <li>success {Boolean} True if the request succeeded.</li>
11528 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11530 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11531 * The callback is passed the following parameters:<ul>
11532 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11533 * <li>options {Object} The parameter to the request call.</li>
11535 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11536 * The callback is passed the following parameters:<ul>
11537 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11538 * <li>options {Object} The parameter to the request call.</li>
11540 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11541 * for the callback function. Defaults to the browser window.</li>
11542 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11543 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11544 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11545 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11546 * params for the post data. Any params will be appended to the URL.</li>
11547 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11549 * @return {Number} transactionId
11551 request : function(o){
11552 if(this.fireEvent("beforerequest", this, o) !== false){
11555 if(typeof p == "function"){
11556 p = p.call(o.scope||window, o);
11558 if(typeof p == "object"){
11559 p = Roo.urlEncode(o.params);
11561 if(this.extraParams){
11562 var extras = Roo.urlEncode(this.extraParams);
11563 p = p ? (p + '&' + extras) : extras;
11566 var url = o.url || this.url;
11567 if(typeof url == 'function'){
11568 url = url.call(o.scope||window, o);
11572 var form = Roo.getDom(o.form);
11573 url = url || form.action;
11575 var enctype = form.getAttribute("enctype");
11576 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11577 return this.doFormUpload(o, p, url);
11579 var f = Roo.lib.Ajax.serializeForm(form);
11580 p = p ? (p + '&' + f) : f;
11583 var hs = o.headers;
11584 if(this.defaultHeaders){
11585 hs = Roo.apply(hs || {}, this.defaultHeaders);
11592 success: this.handleResponse,
11593 failure: this.handleFailure,
11595 argument: {options: o},
11596 timeout : o.timeout || this.timeout
11599 var method = o.method||this.method||(p ? "POST" : "GET");
11601 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11602 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11605 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11609 }else if(this.autoAbort !== false){
11613 if((method == 'GET' && p) || o.xmlData){
11614 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11617 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11618 return this.transId;
11620 Roo.callback(o.callback, o.scope, [o, null, null]);
11626 * Determine whether this object has a request outstanding.
11627 * @param {Number} transactionId (Optional) defaults to the last transaction
11628 * @return {Boolean} True if there is an outstanding request.
11630 isLoading : function(transId){
11632 return Roo.lib.Ajax.isCallInProgress(transId);
11634 return this.transId ? true : false;
11639 * Aborts any outstanding request.
11640 * @param {Number} transactionId (Optional) defaults to the last transaction
11642 abort : function(transId){
11643 if(transId || this.isLoading()){
11644 Roo.lib.Ajax.abort(transId || this.transId);
11649 handleResponse : function(response){
11650 this.transId = false;
11651 var options = response.argument.options;
11652 response.argument = options ? options.argument : null;
11653 this.fireEvent("requestcomplete", this, response, options);
11654 Roo.callback(options.success, options.scope, [response, options]);
11655 Roo.callback(options.callback, options.scope, [options, true, response]);
11659 handleFailure : function(response, e){
11660 this.transId = false;
11661 var options = response.argument.options;
11662 response.argument = options ? options.argument : null;
11663 this.fireEvent("requestexception", this, response, options, e);
11664 Roo.callback(options.failure, options.scope, [response, options]);
11665 Roo.callback(options.callback, options.scope, [options, false, response]);
11669 doFormUpload : function(o, ps, url){
11671 var frame = document.createElement('iframe');
11674 frame.className = 'x-hidden';
11676 frame.src = Roo.SSL_SECURE_URL;
11678 document.body.appendChild(frame);
11681 document.frames[id].name = id;
11684 var form = Roo.getDom(o.form);
11686 form.method = 'POST';
11687 form.enctype = form.encoding = 'multipart/form-data';
11693 if(ps){ // add dynamic params
11695 ps = Roo.urlDecode(ps, false);
11697 if(ps.hasOwnProperty(k)){
11698 hd = document.createElement('input');
11699 hd.type = 'hidden';
11702 form.appendChild(hd);
11709 var r = { // bogus response object
11714 r.argument = o ? o.argument : null;
11719 doc = frame.contentWindow.document;
11721 doc = (frame.contentDocument || window.frames[id].document);
11723 if(doc && doc.body){
11724 r.responseText = doc.body.innerHTML;
11726 if(doc && doc.XMLDocument){
11727 r.responseXML = doc.XMLDocument;
11729 r.responseXML = doc;
11736 Roo.EventManager.removeListener(frame, 'load', cb, this);
11738 this.fireEvent("requestcomplete", this, r, o);
11739 Roo.callback(o.success, o.scope, [r, o]);
11740 Roo.callback(o.callback, o.scope, [o, true, r]);
11742 setTimeout(function(){document.body.removeChild(frame);}, 100);
11745 Roo.EventManager.on(frame, 'load', cb, this);
11748 if(hiddens){ // remove dynamic params
11749 for(var i = 0, len = hiddens.length; i < len; i++){
11750 form.removeChild(hiddens[i]);
11757 * Ext JS Library 1.1.1
11758 * Copyright(c) 2006-2007, Ext JS, LLC.
11760 * Originally Released Under LGPL - original licence link has changed is not relivant.
11763 * <script type="text/javascript">
11767 * Global Ajax request class.
11770 * @extends Roo.data.Connection
11773 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11774 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11775 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11776 * @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)
11777 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11778 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11779 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11781 Roo.Ajax = new Roo.data.Connection({
11790 * Serialize the passed form into a url encoded string
11792 * @param {String/HTMLElement} form
11795 serializeForm : function(form){
11796 return Roo.lib.Ajax.serializeForm(form);
11800 * Ext JS Library 1.1.1
11801 * Copyright(c) 2006-2007, Ext JS, LLC.
11803 * Originally Released Under LGPL - original licence link has changed is not relivant.
11806 * <script type="text/javascript">
11811 * @class Roo.UpdateManager
11812 * @extends Roo.util.Observable
11813 * Provides AJAX-style update for Element object.<br><br>
11816 * // Get it from a Roo.Element object
11817 * var el = Roo.get("foo");
11818 * var mgr = el.getUpdateManager();
11819 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11821 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11823 * // or directly (returns the same UpdateManager instance)
11824 * var mgr = new Roo.UpdateManager("myElementId");
11825 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11826 * mgr.on("update", myFcnNeedsToKnow);
11828 // short handed call directly from the element object
11829 Roo.get("foo").load({
11833 text: "Loading Foo..."
11837 * Create new UpdateManager directly.
11838 * @param {String/HTMLElement/Roo.Element} el The element to update
11839 * @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).
11841 Roo.UpdateManager = function(el, forceNew){
11843 if(!forceNew && el.updateManager){
11844 return el.updateManager;
11847 * The Element object
11848 * @type Roo.Element
11852 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11855 this.defaultUrl = null;
11859 * @event beforeupdate
11860 * Fired before an update is made, return false from your handler and the update is cancelled.
11861 * @param {Roo.Element} el
11862 * @param {String/Object/Function} url
11863 * @param {String/Object} params
11865 "beforeupdate": true,
11868 * Fired after successful update is made.
11869 * @param {Roo.Element} el
11870 * @param {Object} oResponseObject The response Object
11875 * Fired on update failure.
11876 * @param {Roo.Element} el
11877 * @param {Object} oResponseObject The response Object
11881 var d = Roo.UpdateManager.defaults;
11883 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11886 this.sslBlankUrl = d.sslBlankUrl;
11888 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11891 this.disableCaching = d.disableCaching;
11893 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11896 this.indicatorText = d.indicatorText;
11898 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11901 this.showLoadIndicator = d.showLoadIndicator;
11903 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11906 this.timeout = d.timeout;
11909 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11912 this.loadScripts = d.loadScripts;
11915 * Transaction object of current executing transaction
11917 this.transaction = null;
11922 this.autoRefreshProcId = null;
11924 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11927 this.refreshDelegate = this.refresh.createDelegate(this);
11929 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11932 this.updateDelegate = this.update.createDelegate(this);
11934 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11937 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11941 this.successDelegate = this.processSuccess.createDelegate(this);
11945 this.failureDelegate = this.processFailure.createDelegate(this);
11947 if(!this.renderer){
11949 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11951 this.renderer = new Roo.UpdateManager.BasicRenderer();
11954 Roo.UpdateManager.superclass.constructor.call(this);
11957 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11959 * Get the Element this UpdateManager is bound to
11960 * @return {Roo.Element} The element
11962 getEl : function(){
11966 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11967 * @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:
11970 url: "your-url.php",<br/>
11971 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11972 callback: yourFunction,<br/>
11973 scope: yourObject, //(optional scope) <br/>
11974 discardUrl: false, <br/>
11975 nocache: false,<br/>
11976 text: "Loading...",<br/>
11978 scripts: false<br/>
11981 * The only required property is url. The optional properties nocache, text and scripts
11982 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11983 * @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}
11984 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11985 * @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.
11987 update : function(url, params, callback, discardUrl){
11988 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11989 var method = this.method,
11991 if(typeof url == "object"){ // must be config object
11994 params = params || cfg.params;
11995 callback = callback || cfg.callback;
11996 discardUrl = discardUrl || cfg.discardUrl;
11997 if(callback && cfg.scope){
11998 callback = callback.createDelegate(cfg.scope);
12000 if(typeof cfg.method != "undefined"){method = cfg.method;};
12001 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
12002 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
12003 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
12004 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
12006 this.showLoading();
12008 this.defaultUrl = url;
12010 if(typeof url == "function"){
12011 url = url.call(this);
12014 method = method || (params ? "POST" : "GET");
12015 if(method == "GET"){
12016 url = this.prepareUrl(url);
12019 var o = Roo.apply(cfg ||{}, {
12022 success: this.successDelegate,
12023 failure: this.failureDelegate,
12024 callback: undefined,
12025 timeout: (this.timeout*1000),
12026 argument: {"url": url, "form": null, "callback": callback, "params": params}
12028 Roo.log("updated manager called with timeout of " + o.timeout);
12029 this.transaction = Roo.Ajax.request(o);
12034 * 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.
12035 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
12036 * @param {String/HTMLElement} form The form Id or form element
12037 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
12038 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
12039 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
12041 formUpdate : function(form, url, reset, callback){
12042 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
12043 if(typeof url == "function"){
12044 url = url.call(this);
12046 form = Roo.getDom(form);
12047 this.transaction = Roo.Ajax.request({
12050 success: this.successDelegate,
12051 failure: this.failureDelegate,
12052 timeout: (this.timeout*1000),
12053 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
12055 this.showLoading.defer(1, this);
12060 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
12061 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12063 refresh : function(callback){
12064 if(this.defaultUrl == null){
12067 this.update(this.defaultUrl, null, callback, true);
12071 * Set this element to auto refresh.
12072 * @param {Number} interval How often to update (in seconds).
12073 * @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)
12074 * @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}
12075 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
12076 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
12078 startAutoRefresh : function(interval, url, params, callback, refreshNow){
12080 this.update(url || this.defaultUrl, params, callback, true);
12082 if(this.autoRefreshProcId){
12083 clearInterval(this.autoRefreshProcId);
12085 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
12089 * Stop auto refresh on this element.
12091 stopAutoRefresh : function(){
12092 if(this.autoRefreshProcId){
12093 clearInterval(this.autoRefreshProcId);
12094 delete this.autoRefreshProcId;
12098 isAutoRefreshing : function(){
12099 return this.autoRefreshProcId ? true : false;
12102 * Called to update the element to "Loading" state. Override to perform custom action.
12104 showLoading : function(){
12105 if(this.showLoadIndicator){
12106 this.el.update(this.indicatorText);
12111 * Adds unique parameter to query string if disableCaching = true
12114 prepareUrl : function(url){
12115 if(this.disableCaching){
12116 var append = "_dc=" + (new Date().getTime());
12117 if(url.indexOf("?") !== -1){
12118 url += "&" + append;
12120 url += "?" + append;
12129 processSuccess : function(response){
12130 this.transaction = null;
12131 if(response.argument.form && response.argument.reset){
12132 try{ // put in try/catch since some older FF releases had problems with this
12133 response.argument.form.reset();
12136 if(this.loadScripts){
12137 this.renderer.render(this.el, response, this,
12138 this.updateComplete.createDelegate(this, [response]));
12140 this.renderer.render(this.el, response, this);
12141 this.updateComplete(response);
12145 updateComplete : function(response){
12146 this.fireEvent("update", this.el, response);
12147 if(typeof response.argument.callback == "function"){
12148 response.argument.callback(this.el, true, response);
12155 processFailure : function(response){
12156 this.transaction = null;
12157 this.fireEvent("failure", this.el, response);
12158 if(typeof response.argument.callback == "function"){
12159 response.argument.callback(this.el, false, response);
12164 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12165 * @param {Object} renderer The object implementing the render() method
12167 setRenderer : function(renderer){
12168 this.renderer = renderer;
12171 getRenderer : function(){
12172 return this.renderer;
12176 * Set the defaultUrl used for updates
12177 * @param {String/Function} defaultUrl The url or a function to call to get the url
12179 setDefaultUrl : function(defaultUrl){
12180 this.defaultUrl = defaultUrl;
12184 * Aborts the executing transaction
12186 abort : function(){
12187 if(this.transaction){
12188 Roo.Ajax.abort(this.transaction);
12193 * Returns true if an update is in progress
12194 * @return {Boolean}
12196 isUpdating : function(){
12197 if(this.transaction){
12198 return Roo.Ajax.isLoading(this.transaction);
12205 * @class Roo.UpdateManager.defaults
12206 * @static (not really - but it helps the doc tool)
12207 * The defaults collection enables customizing the default properties of UpdateManager
12209 Roo.UpdateManager.defaults = {
12211 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12217 * True to process scripts by default (Defaults to false).
12220 loadScripts : false,
12223 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12226 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12228 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12231 disableCaching : false,
12233 * Whether to show indicatorText when loading (Defaults to true).
12236 showLoadIndicator : true,
12238 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12241 indicatorText : '<div class="loading-indicator">Loading...</div>'
12245 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12247 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12248 * @param {String/HTMLElement/Roo.Element} el The element to update
12249 * @param {String} url The url
12250 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12251 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12254 * @member Roo.UpdateManager
12256 Roo.UpdateManager.updateElement = function(el, url, params, options){
12257 var um = Roo.get(el, true).getUpdateManager();
12258 Roo.apply(um, options);
12259 um.update(url, params, options ? options.callback : null);
12261 // alias for backwards compat
12262 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12264 * @class Roo.UpdateManager.BasicRenderer
12265 * Default Content renderer. Updates the elements innerHTML with the responseText.
12267 Roo.UpdateManager.BasicRenderer = function(){};
12269 Roo.UpdateManager.BasicRenderer.prototype = {
12271 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12272 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12273 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12274 * @param {Roo.Element} el The element being rendered
12275 * @param {Object} response The YUI Connect response object
12276 * @param {UpdateManager} updateManager The calling update manager
12277 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12279 render : function(el, response, updateManager, callback){
12280 el.update(response.responseText, updateManager.loadScripts, callback);
12286 * (c)) Alan Knowles
12292 * @class Roo.DomTemplate
12293 * @extends Roo.Template
12294 * An effort at a dom based template engine..
12296 * Similar to XTemplate, except it uses dom parsing to create the template..
12298 * Supported features:
12303 {a_variable} - output encoded.
12304 {a_variable.format:("Y-m-d")} - call a method on the variable
12305 {a_variable:raw} - unencoded output
12306 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12307 {a_variable:this.method_on_template(...)} - call a method on the template object.
12312 <div roo-for="a_variable or condition.."></div>
12313 <div roo-if="a_variable or condition"></div>
12314 <div roo-exec="some javascript"></div>
12315 <div roo-name="named_template"></div>
12320 Roo.DomTemplate = function()
12322 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12329 Roo.extend(Roo.DomTemplate, Roo.Template, {
12331 * id counter for sub templates.
12335 * flag to indicate if dom parser is inside a pre,
12336 * it will strip whitespace if not.
12341 * The various sub templates
12349 * basic tag replacing syntax
12352 * // you can fake an object call by doing this
12356 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12357 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12359 iterChild : function (node, method) {
12361 var oldPre = this.inPre;
12362 if (node.tagName == 'PRE') {
12365 for( var i = 0; i < node.childNodes.length; i++) {
12366 method.call(this, node.childNodes[i]);
12368 this.inPre = oldPre;
12374 * compile the template
12376 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12379 compile: function()
12383 // covert the html into DOM...
12387 doc = document.implementation.createHTMLDocument("");
12388 doc.documentElement.innerHTML = this.html ;
12389 div = doc.documentElement;
12391 // old IE... - nasty -- it causes all sorts of issues.. with
12392 // images getting pulled from server..
12393 div = document.createElement('div');
12394 div.innerHTML = this.html;
12396 //doc.documentElement.innerHTML = htmlBody
12402 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12404 var tpls = this.tpls;
12406 // create a top level template from the snippet..
12408 //Roo.log(div.innerHTML);
12415 body : div.innerHTML,
12428 Roo.each(tpls, function(tp){
12429 this.compileTpl(tp);
12430 this.tpls[tp.id] = tp;
12433 this.master = tpls[0];
12439 compileNode : function(node, istop) {
12444 // skip anything not a tag..
12445 if (node.nodeType != 1) {
12446 if (node.nodeType == 3 && !this.inPre) {
12447 // reduce white space..
12448 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12471 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12472 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12473 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12474 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12480 // just itterate children..
12481 this.iterChild(node,this.compileNode);
12484 tpl.uid = this.id++;
12485 tpl.value = node.getAttribute('roo-' + tpl.attr);
12486 node.removeAttribute('roo-'+ tpl.attr);
12487 if (tpl.attr != 'name') {
12488 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12489 node.parentNode.replaceChild(placeholder, node);
12492 var placeholder = document.createElement('span');
12493 placeholder.className = 'roo-tpl-' + tpl.value;
12494 node.parentNode.replaceChild(placeholder, node);
12497 // parent now sees '{domtplXXXX}
12498 this.iterChild(node,this.compileNode);
12500 // we should now have node body...
12501 var div = document.createElement('div');
12502 div.appendChild(node);
12504 // this has the unfortunate side effect of converting tagged attributes
12505 // eg. href="{...}" into %7C...%7D
12506 // this has been fixed by searching for those combo's although it's a bit hacky..
12509 tpl.body = div.innerHTML;
12516 switch (tpl.value) {
12517 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12518 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12519 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12524 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12528 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12532 tpl.id = tpl.value; // replace non characters???
12538 this.tpls.push(tpl);
12548 * Compile a segment of the template into a 'sub-template'
12554 compileTpl : function(tpl)
12556 var fm = Roo.util.Format;
12557 var useF = this.disableFormats !== true;
12559 var sep = Roo.isGecko ? "+\n" : ",\n";
12561 var undef = function(str) {
12562 Roo.debug && Roo.log("Property not found :" + str);
12566 //Roo.log(tpl.body);
12570 var fn = function(m, lbrace, name, format, args)
12573 //Roo.log(arguments);
12574 args = args ? args.replace(/\\'/g,"'") : args;
12575 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12576 if (typeof(format) == 'undefined') {
12577 format = 'htmlEncode';
12579 if (format == 'raw' ) {
12583 if(name.substr(0, 6) == 'domtpl'){
12584 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12587 // build an array of options to determine if value is undefined..
12589 // basically get 'xxxx.yyyy' then do
12590 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12591 // (function () { Roo.log("Property not found"); return ''; })() :
12596 Roo.each(name.split('.'), function(st) {
12597 lookfor += (lookfor.length ? '.': '') + st;
12598 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12601 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12604 if(format && useF){
12606 args = args ? ',' + args : "";
12608 if(format.substr(0, 5) != "this."){
12609 format = "fm." + format + '(';
12611 format = 'this.call("'+ format.substr(5) + '", ';
12615 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12618 if (args && args.length) {
12619 // called with xxyx.yuu:(test,test)
12621 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12623 // raw.. - :raw modifier..
12624 return "'"+ sep + udef_st + name + ")"+sep+"'";
12628 // branched to use + in gecko and [].join() in others
12630 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12631 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12634 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12635 body.push(tpl.body.replace(/(\r\n|\n)/g,
12636 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12637 body.push("'].join('');};};");
12638 body = body.join('');
12641 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12643 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12650 * same as applyTemplate, except it's done to one of the subTemplates
12651 * when using named templates, you can do:
12653 * var str = pl.applySubTemplate('your-name', values);
12656 * @param {Number} id of the template
12657 * @param {Object} values to apply to template
12658 * @param {Object} parent (normaly the instance of this object)
12660 applySubTemplate : function(id, values, parent)
12664 var t = this.tpls[id];
12668 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12669 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12673 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12680 if(t.execCall && t.execCall.call(this, values, parent)){
12684 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12690 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12691 parent = t.target ? values : parent;
12692 if(t.forCall && vs instanceof Array){
12694 for(var i = 0, len = vs.length; i < len; i++){
12696 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12698 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12700 //Roo.log(t.compiled);
12704 return buf.join('');
12707 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12712 return t.compiled.call(this, vs, parent);
12714 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12716 //Roo.log(t.compiled);
12724 applyTemplate : function(values){
12725 return this.master.compiled.call(this, values, {});
12726 //var s = this.subs;
12729 apply : function(){
12730 return this.applyTemplate.apply(this, arguments);
12735 Roo.DomTemplate.from = function(el){
12736 el = Roo.getDom(el);
12737 return new Roo.Domtemplate(el.value || el.innerHTML);
12740 * Ext JS Library 1.1.1
12741 * Copyright(c) 2006-2007, Ext JS, LLC.
12743 * Originally Released Under LGPL - original licence link has changed is not relivant.
12746 * <script type="text/javascript">
12750 * @class Roo.util.DelayedTask
12751 * Provides a convenient method of performing setTimeout where a new
12752 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12753 * You can use this class to buffer
12754 * the keypress events for a certain number of milliseconds, and perform only if they stop
12755 * for that amount of time.
12756 * @constructor The parameters to this constructor serve as defaults and are not required.
12757 * @param {Function} fn (optional) The default function to timeout
12758 * @param {Object} scope (optional) The default scope of that timeout
12759 * @param {Array} args (optional) The default Array of arguments
12761 Roo.util.DelayedTask = function(fn, scope, args){
12762 var id = null, d, t;
12764 var call = function(){
12765 var now = new Date().getTime();
12769 fn.apply(scope, args || []);
12773 * Cancels any pending timeout and queues a new one
12774 * @param {Number} delay The milliseconds to delay
12775 * @param {Function} newFn (optional) Overrides function passed to constructor
12776 * @param {Object} newScope (optional) Overrides scope passed to constructor
12777 * @param {Array} newArgs (optional) Overrides args passed to constructor
12779 this.delay = function(delay, newFn, newScope, newArgs){
12780 if(id && delay != d){
12784 t = new Date().getTime();
12786 scope = newScope || scope;
12787 args = newArgs || args;
12789 id = setInterval(call, d);
12794 * Cancel the last queued timeout
12796 this.cancel = function(){
12804 * Ext JS Library 1.1.1
12805 * Copyright(c) 2006-2007, Ext JS, LLC.
12807 * Originally Released Under LGPL - original licence link has changed is not relivant.
12810 * <script type="text/javascript">
12814 Roo.util.TaskRunner = function(interval){
12815 interval = interval || 10;
12816 var tasks = [], removeQueue = [];
12818 var running = false;
12820 var stopThread = function(){
12826 var startThread = function(){
12829 id = setInterval(runTasks, interval);
12833 var removeTask = function(task){
12834 removeQueue.push(task);
12840 var runTasks = function(){
12841 if(removeQueue.length > 0){
12842 for(var i = 0, len = removeQueue.length; i < len; i++){
12843 tasks.remove(removeQueue[i]);
12846 if(tasks.length < 1){
12851 var now = new Date().getTime();
12852 for(var i = 0, len = tasks.length; i < len; ++i){
12854 var itime = now - t.taskRunTime;
12855 if(t.interval <= itime){
12856 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12857 t.taskRunTime = now;
12858 if(rt === false || t.taskRunCount === t.repeat){
12863 if(t.duration && t.duration <= (now - t.taskStartTime)){
12870 * Queues a new task.
12871 * @param {Object} task
12873 this.start = function(task){
12875 task.taskStartTime = new Date().getTime();
12876 task.taskRunTime = 0;
12877 task.taskRunCount = 0;
12882 this.stop = function(task){
12887 this.stopAll = function(){
12889 for(var i = 0, len = tasks.length; i < len; i++){
12890 if(tasks[i].onStop){
12899 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12901 * Ext JS Library 1.1.1
12902 * Copyright(c) 2006-2007, Ext JS, LLC.
12904 * Originally Released Under LGPL - original licence link has changed is not relivant.
12907 * <script type="text/javascript">
12912 * @class Roo.util.MixedCollection
12913 * @extends Roo.util.Observable
12914 * A Collection class that maintains both numeric indexes and keys and exposes events.
12916 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12917 * collection (defaults to false)
12918 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12919 * and return the key value for that item. This is used when available to look up the key on items that
12920 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12921 * equivalent to providing an implementation for the {@link #getKey} method.
12923 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12931 * Fires when the collection is cleared.
12936 * Fires when an item is added to the collection.
12937 * @param {Number} index The index at which the item was added.
12938 * @param {Object} o The item added.
12939 * @param {String} key The key associated with the added item.
12944 * Fires when an item is replaced in the collection.
12945 * @param {String} key he key associated with the new added.
12946 * @param {Object} old The item being replaced.
12947 * @param {Object} new The new item.
12952 * Fires when an item is removed from the collection.
12953 * @param {Object} o The item being removed.
12954 * @param {String} key (optional) The key associated with the removed item.
12959 this.allowFunctions = allowFunctions === true;
12961 this.getKey = keyFn;
12963 Roo.util.MixedCollection.superclass.constructor.call(this);
12966 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12967 allowFunctions : false,
12970 * Adds an item to the collection.
12971 * @param {String} key The key to associate with the item
12972 * @param {Object} o The item to add.
12973 * @return {Object} The item added.
12975 add : function(key, o){
12976 if(arguments.length == 1){
12978 key = this.getKey(o);
12980 if(typeof key == "undefined" || key === null){
12982 this.items.push(o);
12983 this.keys.push(null);
12985 var old = this.map[key];
12987 return this.replace(key, o);
12990 this.items.push(o);
12992 this.keys.push(key);
12994 this.fireEvent("add", this.length-1, o, key);
12999 * MixedCollection has a generic way to fetch keys if you implement getKey.
13002 var mc = new Roo.util.MixedCollection();
13003 mc.add(someEl.dom.id, someEl);
13004 mc.add(otherEl.dom.id, otherEl);
13008 var mc = new Roo.util.MixedCollection();
13009 mc.getKey = function(el){
13015 // or via the constructor
13016 var mc = new Roo.util.MixedCollection(false, function(el){
13022 * @param o {Object} The item for which to find the key.
13023 * @return {Object} The key for the passed item.
13025 getKey : function(o){
13030 * Replaces an item in the collection.
13031 * @param {String} key The key associated with the item to replace, or the item to replace.
13032 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
13033 * @return {Object} The new item.
13035 replace : function(key, o){
13036 if(arguments.length == 1){
13038 key = this.getKey(o);
13040 var old = this.item(key);
13041 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
13042 return this.add(key, o);
13044 var index = this.indexOfKey(key);
13045 this.items[index] = o;
13047 this.fireEvent("replace", key, old, o);
13052 * Adds all elements of an Array or an Object to the collection.
13053 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
13054 * an Array of values, each of which are added to the collection.
13056 addAll : function(objs){
13057 if(arguments.length > 1 || objs instanceof Array){
13058 var args = arguments.length > 1 ? arguments : objs;
13059 for(var i = 0, len = args.length; i < len; i++){
13063 for(var key in objs){
13064 if(this.allowFunctions || typeof objs[key] != "function"){
13065 this.add(key, objs[key]);
13072 * Executes the specified function once for every item in the collection, passing each
13073 * item as the first and only parameter. returning false from the function will stop the iteration.
13074 * @param {Function} fn The function to execute for each item.
13075 * @param {Object} scope (optional) The scope in which to execute the function.
13077 each : function(fn, scope){
13078 var items = [].concat(this.items); // each safe for removal
13079 for(var i = 0, len = items.length; i < len; i++){
13080 if(fn.call(scope || items[i], items[i], i, len) === false){
13087 * Executes the specified function once for every key in the collection, passing each
13088 * key, and its associated item as the first two parameters.
13089 * @param {Function} fn The function to execute for each item.
13090 * @param {Object} scope (optional) The scope in which to execute the function.
13092 eachKey : function(fn, scope){
13093 for(var i = 0, len = this.keys.length; i < len; i++){
13094 fn.call(scope || window, this.keys[i], this.items[i], i, len);
13099 * Returns the first item in the collection which elicits a true return value from the
13100 * passed selection function.
13101 * @param {Function} fn The selection function to execute for each item.
13102 * @param {Object} scope (optional) The scope in which to execute the function.
13103 * @return {Object} The first item in the collection which returned true from the selection function.
13105 find : function(fn, scope){
13106 for(var i = 0, len = this.items.length; i < len; i++){
13107 if(fn.call(scope || window, this.items[i], this.keys[i])){
13108 return this.items[i];
13115 * Inserts an item at the specified index in the collection.
13116 * @param {Number} index The index to insert the item at.
13117 * @param {String} key The key to associate with the new item, or the item itself.
13118 * @param {Object} o (optional) If the second parameter was a key, the new item.
13119 * @return {Object} The item inserted.
13121 insert : function(index, key, o){
13122 if(arguments.length == 2){
13124 key = this.getKey(o);
13126 if(index >= this.length){
13127 return this.add(key, o);
13130 this.items.splice(index, 0, o);
13131 if(typeof key != "undefined" && key != null){
13134 this.keys.splice(index, 0, key);
13135 this.fireEvent("add", index, o, key);
13140 * Removed an item from the collection.
13141 * @param {Object} o The item to remove.
13142 * @return {Object} The item removed.
13144 remove : function(o){
13145 return this.removeAt(this.indexOf(o));
13149 * Remove an item from a specified index in the collection.
13150 * @param {Number} index The index within the collection of the item to remove.
13152 removeAt : function(index){
13153 if(index < this.length && index >= 0){
13155 var o = this.items[index];
13156 this.items.splice(index, 1);
13157 var key = this.keys[index];
13158 if(typeof key != "undefined"){
13159 delete this.map[key];
13161 this.keys.splice(index, 1);
13162 this.fireEvent("remove", o, key);
13167 * Removed an item associated with the passed key fom the collection.
13168 * @param {String} key The key of the item to remove.
13170 removeKey : function(key){
13171 return this.removeAt(this.indexOfKey(key));
13175 * Returns the number of items in the collection.
13176 * @return {Number} the number of items in the collection.
13178 getCount : function(){
13179 return this.length;
13183 * Returns index within the collection of the passed Object.
13184 * @param {Object} o The item to find the index of.
13185 * @return {Number} index of the item.
13187 indexOf : function(o){
13188 if(!this.items.indexOf){
13189 for(var i = 0, len = this.items.length; i < len; i++){
13190 if(this.items[i] == o) {
13196 return this.items.indexOf(o);
13201 * Returns index within the collection of the passed key.
13202 * @param {String} key The key to find the index of.
13203 * @return {Number} index of the key.
13205 indexOfKey : function(key){
13206 if(!this.keys.indexOf){
13207 for(var i = 0, len = this.keys.length; i < len; i++){
13208 if(this.keys[i] == key) {
13214 return this.keys.indexOf(key);
13219 * Returns the item associated with the passed key OR index. Key has priority over index.
13220 * @param {String/Number} key The key or index of the item.
13221 * @return {Object} The item associated with the passed key.
13223 item : function(key){
13224 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13225 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13229 * Returns the item at the specified index.
13230 * @param {Number} index The index of the item.
13233 itemAt : function(index){
13234 return this.items[index];
13238 * Returns the item associated with the passed key.
13239 * @param {String/Number} key The key of the item.
13240 * @return {Object} The item associated with the passed key.
13242 key : function(key){
13243 return this.map[key];
13247 * Returns true if the collection contains the passed Object as an item.
13248 * @param {Object} o The Object to look for in the collection.
13249 * @return {Boolean} True if the collection contains the Object as an item.
13251 contains : function(o){
13252 return this.indexOf(o) != -1;
13256 * Returns true if the collection contains the passed Object as a key.
13257 * @param {String} key The key to look for in the collection.
13258 * @return {Boolean} True if the collection contains the Object as a key.
13260 containsKey : function(key){
13261 return typeof this.map[key] != "undefined";
13265 * Removes all items from the collection.
13267 clear : function(){
13272 this.fireEvent("clear");
13276 * Returns the first item in the collection.
13277 * @return {Object} the first item in the collection..
13279 first : function(){
13280 return this.items[0];
13284 * Returns the last item in the collection.
13285 * @return {Object} the last item in the collection..
13288 return this.items[this.length-1];
13291 _sort : function(property, dir, fn){
13292 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13293 fn = fn || function(a, b){
13296 var c = [], k = this.keys, items = this.items;
13297 for(var i = 0, len = items.length; i < len; i++){
13298 c[c.length] = {key: k[i], value: items[i], index: i};
13300 c.sort(function(a, b){
13301 var v = fn(a[property], b[property]) * dsc;
13303 v = (a.index < b.index ? -1 : 1);
13307 for(var i = 0, len = c.length; i < len; i++){
13308 items[i] = c[i].value;
13311 this.fireEvent("sort", this);
13315 * Sorts this collection with the passed comparison function
13316 * @param {String} direction (optional) "ASC" or "DESC"
13317 * @param {Function} fn (optional) comparison function
13319 sort : function(dir, fn){
13320 this._sort("value", dir, fn);
13324 * Sorts this collection by keys
13325 * @param {String} direction (optional) "ASC" or "DESC"
13326 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13328 keySort : function(dir, fn){
13329 this._sort("key", dir, fn || function(a, b){
13330 return String(a).toUpperCase()-String(b).toUpperCase();
13335 * Returns a range of items in this collection
13336 * @param {Number} startIndex (optional) defaults to 0
13337 * @param {Number} endIndex (optional) default to the last item
13338 * @return {Array} An array of items
13340 getRange : function(start, end){
13341 var items = this.items;
13342 if(items.length < 1){
13345 start = start || 0;
13346 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13349 for(var i = start; i <= end; i++) {
13350 r[r.length] = items[i];
13353 for(var i = start; i >= end; i--) {
13354 r[r.length] = items[i];
13361 * Filter the <i>objects</i> in this collection by a specific property.
13362 * Returns a new collection that has been filtered.
13363 * @param {String} property A property on your objects
13364 * @param {String/RegExp} value Either string that the property values
13365 * should start with or a RegExp to test against the property
13366 * @return {MixedCollection} The new filtered collection
13368 filter : function(property, value){
13369 if(!value.exec){ // not a regex
13370 value = String(value);
13371 if(value.length == 0){
13372 return this.clone();
13374 value = new RegExp("^" + Roo.escapeRe(value), "i");
13376 return this.filterBy(function(o){
13377 return o && value.test(o[property]);
13382 * Filter by a function. * Returns a new collection that has been filtered.
13383 * The passed function will be called with each
13384 * object in the collection. If the function returns true, the value is included
13385 * otherwise it is filtered.
13386 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13387 * @param {Object} scope (optional) The scope of the function (defaults to this)
13388 * @return {MixedCollection} The new filtered collection
13390 filterBy : function(fn, scope){
13391 var r = new Roo.util.MixedCollection();
13392 r.getKey = this.getKey;
13393 var k = this.keys, it = this.items;
13394 for(var i = 0, len = it.length; i < len; i++){
13395 if(fn.call(scope||this, it[i], k[i])){
13396 r.add(k[i], it[i]);
13403 * Creates a duplicate of this collection
13404 * @return {MixedCollection}
13406 clone : function(){
13407 var r = new Roo.util.MixedCollection();
13408 var k = this.keys, it = this.items;
13409 for(var i = 0, len = it.length; i < len; i++){
13410 r.add(k[i], it[i]);
13412 r.getKey = this.getKey;
13417 * Returns the item associated with the passed key or index.
13419 * @param {String/Number} key The key or index of the item.
13420 * @return {Object} The item associated with the passed key.
13422 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13424 * Ext JS Library 1.1.1
13425 * Copyright(c) 2006-2007, Ext JS, LLC.
13427 * Originally Released Under LGPL - original licence link has changed is not relivant.
13430 * <script type="text/javascript">
13433 * @class Roo.util.JSON
13434 * Modified version of Douglas Crockford"s json.js that doesn"t
13435 * mess with the Object prototype
13436 * http://www.json.org/js.html
13439 Roo.util.JSON = new (function(){
13440 var useHasOwn = {}.hasOwnProperty ? true : false;
13442 // crashes Safari in some instances
13443 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13445 var pad = function(n) {
13446 return n < 10 ? "0" + n : n;
13459 var encodeString = function(s){
13460 if (/["\\\x00-\x1f]/.test(s)) {
13461 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13466 c = b.charCodeAt();
13468 Math.floor(c / 16).toString(16) +
13469 (c % 16).toString(16);
13472 return '"' + s + '"';
13475 var encodeArray = function(o){
13476 var a = ["["], b, i, l = o.length, v;
13477 for (i = 0; i < l; i += 1) {
13479 switch (typeof v) {
13488 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13496 var encodeDate = function(o){
13497 return '"' + o.getFullYear() + "-" +
13498 pad(o.getMonth() + 1) + "-" +
13499 pad(o.getDate()) + "T" +
13500 pad(o.getHours()) + ":" +
13501 pad(o.getMinutes()) + ":" +
13502 pad(o.getSeconds()) + '"';
13506 * Encodes an Object, Array or other value
13507 * @param {Mixed} o The variable to encode
13508 * @return {String} The JSON string
13510 this.encode = function(o)
13512 // should this be extended to fully wrap stringify..
13514 if(typeof o == "undefined" || o === null){
13516 }else if(o instanceof Array){
13517 return encodeArray(o);
13518 }else if(o instanceof Date){
13519 return encodeDate(o);
13520 }else if(typeof o == "string"){
13521 return encodeString(o);
13522 }else if(typeof o == "number"){
13523 return isFinite(o) ? String(o) : "null";
13524 }else if(typeof o == "boolean"){
13527 var a = ["{"], b, i, v;
13529 if(!useHasOwn || o.hasOwnProperty(i)) {
13531 switch (typeof v) {
13540 a.push(this.encode(i), ":",
13541 v === null ? "null" : this.encode(v));
13552 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13553 * @param {String} json The JSON string
13554 * @return {Object} The resulting object
13556 this.decode = function(json){
13558 return /** eval:var:json */ eval("(" + json + ')');
13562 * Shorthand for {@link Roo.util.JSON#encode}
13563 * @member Roo encode
13565 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13567 * Shorthand for {@link Roo.util.JSON#decode}
13568 * @member Roo decode
13570 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13573 * Ext JS Library 1.1.1
13574 * Copyright(c) 2006-2007, Ext JS, LLC.
13576 * Originally Released Under LGPL - original licence link has changed is not relivant.
13579 * <script type="text/javascript">
13583 * @class Roo.util.Format
13584 * Reusable data formatting functions
13587 Roo.util.Format = function(){
13588 var trimRe = /^\s+|\s+$/g;
13591 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13592 * @param {String} value The string to truncate
13593 * @param {Number} length The maximum length to allow before truncating
13594 * @return {String} The converted text
13596 ellipsis : function(value, len){
13597 if(value && value.length > len){
13598 return value.substr(0, len-3)+"...";
13604 * Checks a reference and converts it to empty string if it is undefined
13605 * @param {Mixed} value Reference to check
13606 * @return {Mixed} Empty string if converted, otherwise the original value
13608 undef : function(value){
13609 return typeof value != "undefined" ? value : "";
13613 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13614 * @param {String} value The string to encode
13615 * @return {String} The encoded text
13617 htmlEncode : function(value){
13618 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13622 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13623 * @param {String} value The string to decode
13624 * @return {String} The decoded text
13626 htmlDecode : function(value){
13627 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13631 * Trims any whitespace from either side of a string
13632 * @param {String} value The text to trim
13633 * @return {String} The trimmed text
13635 trim : function(value){
13636 return String(value).replace(trimRe, "");
13640 * Returns a substring from within an original string
13641 * @param {String} value The original text
13642 * @param {Number} start The start index of the substring
13643 * @param {Number} length The length of the substring
13644 * @return {String} The substring
13646 substr : function(value, start, length){
13647 return String(value).substr(start, length);
13651 * Converts a string to all lower case letters
13652 * @param {String} value The text to convert
13653 * @return {String} The converted text
13655 lowercase : function(value){
13656 return String(value).toLowerCase();
13660 * Converts a string to all upper case letters
13661 * @param {String} value The text to convert
13662 * @return {String} The converted text
13664 uppercase : function(value){
13665 return String(value).toUpperCase();
13669 * Converts the first character only of a string to upper case
13670 * @param {String} value The text to convert
13671 * @return {String} The converted text
13673 capitalize : function(value){
13674 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13678 call : function(value, fn){
13679 if(arguments.length > 2){
13680 var args = Array.prototype.slice.call(arguments, 2);
13681 args.unshift(value);
13683 return /** eval:var:value */ eval(fn).apply(window, args);
13685 /** eval:var:value */
13686 return /** eval:var:value */ eval(fn).call(window, value);
13692 * safer version of Math.toFixed..??/
13693 * @param {Number/String} value The numeric value to format
13694 * @param {Number/String} value Decimal places
13695 * @return {String} The formatted currency string
13697 toFixed : function(v, n)
13699 // why not use to fixed - precision is buggered???
13701 return Math.round(v-0);
13703 var fact = Math.pow(10,n+1);
13704 v = (Math.round((v-0)*fact))/fact;
13705 var z = (''+fact).substring(2);
13706 if (v == Math.floor(v)) {
13707 return Math.floor(v) + '.' + z;
13710 // now just padd decimals..
13711 var ps = String(v).split('.');
13712 var fd = (ps[1] + z);
13713 var r = fd.substring(0,n);
13714 var rm = fd.substring(n);
13716 return ps[0] + '.' + r;
13718 r*=1; // turn it into a number;
13720 if (String(r).length != n) {
13723 r = String(r).substring(1); // chop the end off.
13726 return ps[0] + '.' + r;
13731 * Format a number as US currency
13732 * @param {Number/String} value The numeric value to format
13733 * @return {String} The formatted currency string
13735 usMoney : function(v){
13736 return '$' + Roo.util.Format.number(v);
13741 * eventually this should probably emulate php's number_format
13742 * @param {Number/String} value The numeric value to format
13743 * @param {Number} decimals number of decimal places
13744 * @return {String} The formatted currency string
13746 number : function(v,decimals)
13748 // multiply and round.
13749 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13750 var mul = Math.pow(10, decimals);
13751 var zero = String(mul).substring(1);
13752 v = (Math.round((v-0)*mul))/mul;
13754 // if it's '0' number.. then
13756 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13758 var ps = v.split('.');
13762 var r = /(\d+)(\d{3})/;
13764 while (r.test(whole)) {
13765 whole = whole.replace(r, '$1' + ',' + '$2');
13771 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13772 // does not have decimals
13773 (decimals ? ('.' + zero) : '');
13776 return whole + sub ;
13780 * Parse a value into a formatted date using the specified format pattern.
13781 * @param {Mixed} value The value to format
13782 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13783 * @return {String} The formatted date string
13785 date : function(v, format){
13789 if(!(v instanceof Date)){
13790 v = new Date(Date.parse(v));
13792 return v.dateFormat(format || Roo.util.Format.defaults.date);
13796 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13797 * @param {String} format Any valid date format string
13798 * @return {Function} The date formatting function
13800 dateRenderer : function(format){
13801 return function(v){
13802 return Roo.util.Format.date(v, format);
13807 stripTagsRE : /<\/?[^>]+>/gi,
13810 * Strips all HTML tags
13811 * @param {Mixed} value The text from which to strip tags
13812 * @return {String} The stripped text
13814 stripTags : function(v){
13815 return !v ? v : String(v).replace(this.stripTagsRE, "");
13819 Roo.util.Format.defaults = {
13823 * Ext JS Library 1.1.1
13824 * Copyright(c) 2006-2007, Ext JS, LLC.
13826 * Originally Released Under LGPL - original licence link has changed is not relivant.
13829 * <script type="text/javascript">
13836 * @class Roo.MasterTemplate
13837 * @extends Roo.Template
13838 * Provides a template that can have child templates. The syntax is:
13840 var t = new Roo.MasterTemplate(
13841 '<select name="{name}">',
13842 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13845 t.add('options', {value: 'foo', text: 'bar'});
13846 // or you can add multiple child elements in one shot
13847 t.addAll('options', [
13848 {value: 'foo', text: 'bar'},
13849 {value: 'foo2', text: 'bar2'},
13850 {value: 'foo3', text: 'bar3'}
13852 // then append, applying the master template values
13853 t.append('my-form', {name: 'my-select'});
13855 * A name attribute for the child template is not required if you have only one child
13856 * template or you want to refer to them by index.
13858 Roo.MasterTemplate = function(){
13859 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13860 this.originalHtml = this.html;
13862 var m, re = this.subTemplateRe;
13865 while(m = re.exec(this.html)){
13866 var name = m[1], content = m[2];
13871 tpl : new Roo.Template(content)
13874 st[name] = st[subIndex];
13876 st[subIndex].tpl.compile();
13877 st[subIndex].tpl.call = this.call.createDelegate(this);
13880 this.subCount = subIndex;
13883 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13885 * The regular expression used to match sub templates
13889 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13892 * Applies the passed values to a child template.
13893 * @param {String/Number} name (optional) The name or index of the child template
13894 * @param {Array/Object} values The values to be applied to the template
13895 * @return {MasterTemplate} this
13897 add : function(name, values){
13898 if(arguments.length == 1){
13899 values = arguments[0];
13902 var s = this.subs[name];
13903 s.buffer[s.buffer.length] = s.tpl.apply(values);
13908 * Applies all the passed values to a child template.
13909 * @param {String/Number} name (optional) The name or index of the child template
13910 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13911 * @param {Boolean} reset (optional) True to reset the template first
13912 * @return {MasterTemplate} this
13914 fill : function(name, values, reset){
13916 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13924 for(var i = 0, len = values.length; i < len; i++){
13925 this.add(name, values[i]);
13931 * Resets the template for reuse
13932 * @return {MasterTemplate} this
13934 reset : function(){
13936 for(var i = 0; i < this.subCount; i++){
13942 applyTemplate : function(values){
13944 var replaceIndex = -1;
13945 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13946 return s[++replaceIndex].buffer.join("");
13948 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13951 apply : function(){
13952 return this.applyTemplate.apply(this, arguments);
13955 compile : function(){return this;}
13959 * Alias for fill().
13962 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13964 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13965 * var tpl = Roo.MasterTemplate.from('element-id');
13966 * @param {String/HTMLElement} el
13967 * @param {Object} config
13970 Roo.MasterTemplate.from = function(el, config){
13971 el = Roo.getDom(el);
13972 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13975 * Ext JS Library 1.1.1
13976 * Copyright(c) 2006-2007, Ext JS, LLC.
13978 * Originally Released Under LGPL - original licence link has changed is not relivant.
13981 * <script type="text/javascript">
13986 * @class Roo.util.CSS
13987 * Utility class for manipulating CSS rules
13990 Roo.util.CSS = function(){
13992 var doc = document;
13994 var camelRe = /(-[a-z])/gi;
13995 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13999 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
14000 * tag and appended to the HEAD of the document.
14001 * @param {String|Object} cssText The text containing the css rules
14002 * @param {String} id An id to add to the stylesheet for later removal
14003 * @return {StyleSheet}
14005 createStyleSheet : function(cssText, id){
14007 var head = doc.getElementsByTagName("head")[0];
14008 var nrules = doc.createElement("style");
14009 nrules.setAttribute("type", "text/css");
14011 nrules.setAttribute("id", id);
14013 if (typeof(cssText) != 'string') {
14014 // support object maps..
14015 // not sure if this a good idea..
14016 // perhaps it should be merged with the general css handling
14017 // and handle js style props.
14018 var cssTextNew = [];
14019 for(var n in cssText) {
14021 for(var k in cssText[n]) {
14022 citems.push( k + ' : ' +cssText[n][k] + ';' );
14024 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
14027 cssText = cssTextNew.join("\n");
14033 head.appendChild(nrules);
14034 ss = nrules.styleSheet;
14035 ss.cssText = cssText;
14038 nrules.appendChild(doc.createTextNode(cssText));
14040 nrules.cssText = cssText;
14042 head.appendChild(nrules);
14043 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
14045 this.cacheStyleSheet(ss);
14050 * Removes a style or link tag by id
14051 * @param {String} id The id of the tag
14053 removeStyleSheet : function(id){
14054 var existing = doc.getElementById(id);
14056 existing.parentNode.removeChild(existing);
14061 * Dynamically swaps an existing stylesheet reference for a new one
14062 * @param {String} id The id of an existing link tag to remove
14063 * @param {String} url The href of the new stylesheet to include
14065 swapStyleSheet : function(id, url){
14066 this.removeStyleSheet(id);
14067 var ss = doc.createElement("link");
14068 ss.setAttribute("rel", "stylesheet");
14069 ss.setAttribute("type", "text/css");
14070 ss.setAttribute("id", id);
14071 ss.setAttribute("href", url);
14072 doc.getElementsByTagName("head")[0].appendChild(ss);
14076 * Refresh the rule cache if you have dynamically added stylesheets
14077 * @return {Object} An object (hash) of rules indexed by selector
14079 refreshCache : function(){
14080 return this.getRules(true);
14084 cacheStyleSheet : function(stylesheet){
14088 try{// try catch for cross domain access issue
14089 var ssRules = stylesheet.cssRules || stylesheet.rules;
14090 for(var j = ssRules.length-1; j >= 0; --j){
14091 rules[ssRules[j].selectorText] = ssRules[j];
14097 * Gets all css rules for the document
14098 * @param {Boolean} refreshCache true to refresh the internal cache
14099 * @return {Object} An object (hash) of rules indexed by selector
14101 getRules : function(refreshCache){
14102 if(rules == null || refreshCache){
14104 var ds = doc.styleSheets;
14105 for(var i =0, len = ds.length; i < len; i++){
14107 this.cacheStyleSheet(ds[i]);
14115 * Gets an an individual CSS rule by selector(s)
14116 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
14117 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
14118 * @return {CSSRule} The CSS rule or null if one is not found
14120 getRule : function(selector, refreshCache){
14121 var rs = this.getRules(refreshCache);
14122 if(!(selector instanceof Array)){
14123 return rs[selector];
14125 for(var i = 0; i < selector.length; i++){
14126 if(rs[selector[i]]){
14127 return rs[selector[i]];
14135 * Updates a rule property
14136 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14137 * @param {String} property The css property
14138 * @param {String} value The new value for the property
14139 * @return {Boolean} true If a rule was found and updated
14141 updateRule : function(selector, property, value){
14142 if(!(selector instanceof Array)){
14143 var rule = this.getRule(selector);
14145 rule.style[property.replace(camelRe, camelFn)] = value;
14149 for(var i = 0; i < selector.length; i++){
14150 if(this.updateRule(selector[i], property, value)){
14160 * Ext JS Library 1.1.1
14161 * Copyright(c) 2006-2007, Ext JS, LLC.
14163 * Originally Released Under LGPL - original licence link has changed is not relivant.
14166 * <script type="text/javascript">
14172 * @class Roo.util.ClickRepeater
14173 * @extends Roo.util.Observable
14175 * A wrapper class which can be applied to any element. Fires a "click" event while the
14176 * mouse is pressed. The interval between firings may be specified in the config but
14177 * defaults to 10 milliseconds.
14179 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14181 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14182 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14183 * Similar to an autorepeat key delay.
14184 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14185 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14186 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14187 * "interval" and "delay" are ignored. "immediate" is honored.
14188 * @cfg {Boolean} preventDefault True to prevent the default click event
14189 * @cfg {Boolean} stopDefault True to stop the default click event
14192 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14193 * 2007-02-02 jvs Renamed to ClickRepeater
14194 * 2007-02-03 jvs Modifications for FF Mac and Safari
14197 * @param {String/HTMLElement/Element} el The element to listen on
14198 * @param {Object} config
14200 Roo.util.ClickRepeater = function(el, config)
14202 this.el = Roo.get(el);
14203 this.el.unselectable();
14205 Roo.apply(this, config);
14210 * Fires when the mouse button is depressed.
14211 * @param {Roo.util.ClickRepeater} this
14213 "mousedown" : true,
14216 * Fires on a specified interval during the time the element is pressed.
14217 * @param {Roo.util.ClickRepeater} this
14222 * Fires when the mouse key is released.
14223 * @param {Roo.util.ClickRepeater} this
14228 this.el.on("mousedown", this.handleMouseDown, this);
14229 if(this.preventDefault || this.stopDefault){
14230 this.el.on("click", function(e){
14231 if(this.preventDefault){
14232 e.preventDefault();
14234 if(this.stopDefault){
14240 // allow inline handler
14242 this.on("click", this.handler, this.scope || this);
14245 Roo.util.ClickRepeater.superclass.constructor.call(this);
14248 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14251 preventDefault : true,
14252 stopDefault : false,
14256 handleMouseDown : function(){
14257 clearTimeout(this.timer);
14259 if(this.pressClass){
14260 this.el.addClass(this.pressClass);
14262 this.mousedownTime = new Date();
14264 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14265 this.el.on("mouseout", this.handleMouseOut, this);
14267 this.fireEvent("mousedown", this);
14268 this.fireEvent("click", this);
14270 this.timer = this.click.defer(this.delay || this.interval, this);
14274 click : function(){
14275 this.fireEvent("click", this);
14276 this.timer = this.click.defer(this.getInterval(), this);
14280 getInterval: function(){
14281 if(!this.accelerate){
14282 return this.interval;
14284 var pressTime = this.mousedownTime.getElapsed();
14285 if(pressTime < 500){
14287 }else if(pressTime < 1700){
14289 }else if(pressTime < 2600){
14291 }else if(pressTime < 3500){
14293 }else if(pressTime < 4400){
14295 }else if(pressTime < 5300){
14297 }else if(pressTime < 6200){
14305 handleMouseOut : function(){
14306 clearTimeout(this.timer);
14307 if(this.pressClass){
14308 this.el.removeClass(this.pressClass);
14310 this.el.on("mouseover", this.handleMouseReturn, this);
14314 handleMouseReturn : function(){
14315 this.el.un("mouseover", this.handleMouseReturn);
14316 if(this.pressClass){
14317 this.el.addClass(this.pressClass);
14323 handleMouseUp : function(){
14324 clearTimeout(this.timer);
14325 this.el.un("mouseover", this.handleMouseReturn);
14326 this.el.un("mouseout", this.handleMouseOut);
14327 Roo.get(document).un("mouseup", this.handleMouseUp);
14328 this.el.removeClass(this.pressClass);
14329 this.fireEvent("mouseup", this);
14333 * Ext JS Library 1.1.1
14334 * Copyright(c) 2006-2007, Ext JS, LLC.
14336 * Originally Released Under LGPL - original licence link has changed is not relivant.
14339 * <script type="text/javascript">
14344 * @class Roo.KeyNav
14345 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14346 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14347 * way to implement custom navigation schemes for any UI component.</p>
14348 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14349 * pageUp, pageDown, del, home, end. Usage:</p>
14351 var nav = new Roo.KeyNav("my-element", {
14352 "left" : function(e){
14353 this.moveLeft(e.ctrlKey);
14355 "right" : function(e){
14356 this.moveRight(e.ctrlKey);
14358 "enter" : function(e){
14365 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14366 * @param {Object} config The config
14368 Roo.KeyNav = function(el, config){
14369 this.el = Roo.get(el);
14370 Roo.apply(this, config);
14371 if(!this.disabled){
14372 this.disabled = true;
14377 Roo.KeyNav.prototype = {
14379 * @cfg {Boolean} disabled
14380 * True to disable this KeyNav instance (defaults to false)
14384 * @cfg {String} defaultEventAction
14385 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14386 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14387 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14389 defaultEventAction: "stopEvent",
14391 * @cfg {Boolean} forceKeyDown
14392 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14393 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14394 * handle keydown instead of keypress.
14396 forceKeyDown : false,
14399 prepareEvent : function(e){
14400 var k = e.getKey();
14401 var h = this.keyToHandler[k];
14402 //if(h && this[h]){
14403 // e.stopPropagation();
14405 if(Roo.isSafari && h && k >= 37 && k <= 40){
14411 relay : function(e){
14412 var k = e.getKey();
14413 var h = this.keyToHandler[k];
14415 if(this.doRelay(e, this[h], h) !== true){
14416 e[this.defaultEventAction]();
14422 doRelay : function(e, h, hname){
14423 return h.call(this.scope || this, e);
14426 // possible handlers
14440 // quick lookup hash
14457 * Enable this KeyNav
14459 enable: function(){
14461 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14462 // the EventObject will normalize Safari automatically
14463 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14464 this.el.on("keydown", this.relay, this);
14466 this.el.on("keydown", this.prepareEvent, this);
14467 this.el.on("keypress", this.relay, this);
14469 this.disabled = false;
14474 * Disable this KeyNav
14476 disable: function(){
14477 if(!this.disabled){
14478 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14479 this.el.un("keydown", this.relay);
14481 this.el.un("keydown", this.prepareEvent);
14482 this.el.un("keypress", this.relay);
14484 this.disabled = true;
14489 * Ext JS Library 1.1.1
14490 * Copyright(c) 2006-2007, Ext JS, LLC.
14492 * Originally Released Under LGPL - original licence link has changed is not relivant.
14495 * <script type="text/javascript">
14500 * @class Roo.KeyMap
14501 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14502 * The constructor accepts the same config object as defined by {@link #addBinding}.
14503 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14504 * combination it will call the function with this signature (if the match is a multi-key
14505 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14506 * A KeyMap can also handle a string representation of keys.<br />
14509 // map one key by key code
14510 var map = new Roo.KeyMap("my-element", {
14511 key: 13, // or Roo.EventObject.ENTER
14516 // map multiple keys to one action by string
14517 var map = new Roo.KeyMap("my-element", {
14523 // map multiple keys to multiple actions by strings and array of codes
14524 var map = new Roo.KeyMap("my-element", [
14527 fn: function(){ alert("Return was pressed"); }
14530 fn: function(){ alert('a, b or c was pressed'); }
14535 fn: function(){ alert('Control + shift + tab was pressed.'); }
14539 * <b>Note: A KeyMap starts enabled</b>
14541 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14542 * @param {Object} config The config (see {@link #addBinding})
14543 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14545 Roo.KeyMap = function(el, config, eventName){
14546 this.el = Roo.get(el);
14547 this.eventName = eventName || "keydown";
14548 this.bindings = [];
14550 this.addBinding(config);
14555 Roo.KeyMap.prototype = {
14557 * True to stop the event from bubbling and prevent the default browser action if the
14558 * key was handled by the KeyMap (defaults to false)
14564 * Add a new binding to this KeyMap. The following config object properties are supported:
14566 Property Type Description
14567 ---------- --------------- ----------------------------------------------------------------------
14568 key String/Array A single keycode or an array of keycodes to handle
14569 shift Boolean True to handle key only when shift is pressed (defaults to false)
14570 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14571 alt Boolean True to handle key only when alt is pressed (defaults to false)
14572 fn Function The function to call when KeyMap finds the expected key combination
14573 scope Object The scope of the callback function
14579 var map = new Roo.KeyMap(document, {
14580 key: Roo.EventObject.ENTER,
14585 //Add a new binding to the existing KeyMap later
14593 * @param {Object/Array} config A single KeyMap config or an array of configs
14595 addBinding : function(config){
14596 if(config instanceof Array){
14597 for(var i = 0, len = config.length; i < len; i++){
14598 this.addBinding(config[i]);
14602 var keyCode = config.key,
14603 shift = config.shift,
14604 ctrl = config.ctrl,
14607 scope = config.scope;
14608 if(typeof keyCode == "string"){
14610 var keyString = keyCode.toUpperCase();
14611 for(var j = 0, len = keyString.length; j < len; j++){
14612 ks.push(keyString.charCodeAt(j));
14616 var keyArray = keyCode instanceof Array;
14617 var handler = function(e){
14618 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14619 var k = e.getKey();
14621 for(var i = 0, len = keyCode.length; i < len; i++){
14622 if(keyCode[i] == k){
14623 if(this.stopEvent){
14626 fn.call(scope || window, k, e);
14632 if(this.stopEvent){
14635 fn.call(scope || window, k, e);
14640 this.bindings.push(handler);
14644 * Shorthand for adding a single key listener
14645 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14646 * following options:
14647 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14648 * @param {Function} fn The function to call
14649 * @param {Object} scope (optional) The scope of the function
14651 on : function(key, fn, scope){
14652 var keyCode, shift, ctrl, alt;
14653 if(typeof key == "object" && !(key instanceof Array)){
14672 handleKeyDown : function(e){
14673 if(this.enabled){ //just in case
14674 var b = this.bindings;
14675 for(var i = 0, len = b.length; i < len; i++){
14676 b[i].call(this, e);
14682 * Returns true if this KeyMap is enabled
14683 * @return {Boolean}
14685 isEnabled : function(){
14686 return this.enabled;
14690 * Enables this KeyMap
14692 enable: function(){
14694 this.el.on(this.eventName, this.handleKeyDown, this);
14695 this.enabled = true;
14700 * Disable this KeyMap
14702 disable: function(){
14704 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14705 this.enabled = false;
14710 * Ext JS Library 1.1.1
14711 * Copyright(c) 2006-2007, Ext JS, LLC.
14713 * Originally Released Under LGPL - original licence link has changed is not relivant.
14716 * <script type="text/javascript">
14721 * @class Roo.util.TextMetrics
14722 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14723 * wide, in pixels, a given block of text will be.
14726 Roo.util.TextMetrics = function(){
14730 * Measures the size of the specified text
14731 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14732 * that can affect the size of the rendered text
14733 * @param {String} text The text to measure
14734 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14735 * in order to accurately measure the text height
14736 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14738 measure : function(el, text, fixedWidth){
14740 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14743 shared.setFixedWidth(fixedWidth || 'auto');
14744 return shared.getSize(text);
14748 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14749 * the overhead of multiple calls to initialize the style properties on each measurement.
14750 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14751 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14752 * in order to accurately measure the text height
14753 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14755 createInstance : function(el, fixedWidth){
14756 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14763 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14764 var ml = new Roo.Element(document.createElement('div'));
14765 document.body.appendChild(ml.dom);
14766 ml.position('absolute');
14767 ml.setLeftTop(-1000, -1000);
14771 ml.setWidth(fixedWidth);
14776 * Returns the size of the specified text based on the internal element's style and width properties
14777 * @memberOf Roo.util.TextMetrics.Instance#
14778 * @param {String} text The text to measure
14779 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14781 getSize : function(text){
14783 var s = ml.getSize();
14789 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14790 * that can affect the size of the rendered text
14791 * @memberOf Roo.util.TextMetrics.Instance#
14792 * @param {String/HTMLElement} el The element, dom node or id
14794 bind : function(el){
14796 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14801 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14802 * to set a fixed width in order to accurately measure the text height.
14803 * @memberOf Roo.util.TextMetrics.Instance#
14804 * @param {Number} width The width to set on the element
14806 setFixedWidth : function(width){
14807 ml.setWidth(width);
14811 * Returns the measured width of the specified text
14812 * @memberOf Roo.util.TextMetrics.Instance#
14813 * @param {String} text The text to measure
14814 * @return {Number} width The width in pixels
14816 getWidth : function(text){
14817 ml.dom.style.width = 'auto';
14818 return this.getSize(text).width;
14822 * Returns the measured height of the specified text. For multiline text, be sure to call
14823 * {@link #setFixedWidth} if necessary.
14824 * @memberOf Roo.util.TextMetrics.Instance#
14825 * @param {String} text The text to measure
14826 * @return {Number} height The height in pixels
14828 getHeight : function(text){
14829 return this.getSize(text).height;
14833 instance.bind(bindTo);
14838 // backwards compat
14839 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14841 * Ext JS Library 1.1.1
14842 * Copyright(c) 2006-2007, Ext JS, LLC.
14844 * Originally Released Under LGPL - original licence link has changed is not relivant.
14847 * <script type="text/javascript">
14851 * @class Roo.state.Provider
14852 * Abstract base class for state provider implementations. This class provides methods
14853 * for encoding and decoding <b>typed</b> variables including dates and defines the
14854 * Provider interface.
14856 Roo.state.Provider = function(){
14858 * @event statechange
14859 * Fires when a state change occurs.
14860 * @param {Provider} this This state provider
14861 * @param {String} key The state key which was changed
14862 * @param {String} value The encoded value for the state
14865 "statechange": true
14868 Roo.state.Provider.superclass.constructor.call(this);
14870 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14872 * Returns the current value for a key
14873 * @param {String} name The key name
14874 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14875 * @return {Mixed} The state data
14877 get : function(name, defaultValue){
14878 return typeof this.state[name] == "undefined" ?
14879 defaultValue : this.state[name];
14883 * Clears a value from the state
14884 * @param {String} name The key name
14886 clear : function(name){
14887 delete this.state[name];
14888 this.fireEvent("statechange", this, name, null);
14892 * Sets the value for a key
14893 * @param {String} name The key name
14894 * @param {Mixed} value The value to set
14896 set : function(name, value){
14897 this.state[name] = value;
14898 this.fireEvent("statechange", this, name, value);
14902 * Decodes a string previously encoded with {@link #encodeValue}.
14903 * @param {String} value The value to decode
14904 * @return {Mixed} The decoded value
14906 decodeValue : function(cookie){
14907 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14908 var matches = re.exec(unescape(cookie));
14909 if(!matches || !matches[1]) {
14910 return; // non state cookie
14912 var type = matches[1];
14913 var v = matches[2];
14916 return parseFloat(v);
14918 return new Date(Date.parse(v));
14923 var values = v.split("^");
14924 for(var i = 0, len = values.length; i < len; i++){
14925 all.push(this.decodeValue(values[i]));
14930 var values = v.split("^");
14931 for(var i = 0, len = values.length; i < len; i++){
14932 var kv = values[i].split("=");
14933 all[kv[0]] = this.decodeValue(kv[1]);
14942 * Encodes a value including type information. Decode with {@link #decodeValue}.
14943 * @param {Mixed} value The value to encode
14944 * @return {String} The encoded value
14946 encodeValue : function(v){
14948 if(typeof v == "number"){
14950 }else if(typeof v == "boolean"){
14951 enc = "b:" + (v ? "1" : "0");
14952 }else if(v instanceof Date){
14953 enc = "d:" + v.toGMTString();
14954 }else if(v instanceof Array){
14956 for(var i = 0, len = v.length; i < len; i++){
14957 flat += this.encodeValue(v[i]);
14963 }else if(typeof v == "object"){
14966 if(typeof v[key] != "function"){
14967 flat += key + "=" + this.encodeValue(v[key]) + "^";
14970 enc = "o:" + flat.substring(0, flat.length-1);
14974 return escape(enc);
14980 * Ext JS Library 1.1.1
14981 * Copyright(c) 2006-2007, Ext JS, LLC.
14983 * Originally Released Under LGPL - original licence link has changed is not relivant.
14986 * <script type="text/javascript">
14989 * @class Roo.state.Manager
14990 * This is the global state manager. By default all components that are "state aware" check this class
14991 * for state information if you don't pass them a custom state provider. In order for this class
14992 * to be useful, it must be initialized with a provider when your application initializes.
14994 // in your initialization function
14996 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14998 // supposed you have a {@link Roo.BorderLayout}
14999 var layout = new Roo.BorderLayout(...);
15000 layout.restoreState();
15001 // or a {Roo.BasicDialog}
15002 var dialog = new Roo.BasicDialog(...);
15003 dialog.restoreState();
15007 Roo.state.Manager = function(){
15008 var provider = new Roo.state.Provider();
15012 * Configures the default state provider for your application
15013 * @param {Provider} stateProvider The state provider to set
15015 setProvider : function(stateProvider){
15016 provider = stateProvider;
15020 * Returns the current value for a key
15021 * @param {String} name The key name
15022 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
15023 * @return {Mixed} The state data
15025 get : function(key, defaultValue){
15026 return provider.get(key, defaultValue);
15030 * Sets the value for a key
15031 * @param {String} name The key name
15032 * @param {Mixed} value The state data
15034 set : function(key, value){
15035 provider.set(key, value);
15039 * Clears a value from the state
15040 * @param {String} name The key name
15042 clear : function(key){
15043 provider.clear(key);
15047 * Gets the currently configured state provider
15048 * @return {Provider} The state provider
15050 getProvider : function(){
15057 * Ext JS Library 1.1.1
15058 * Copyright(c) 2006-2007, Ext JS, LLC.
15060 * Originally Released Under LGPL - original licence link has changed is not relivant.
15063 * <script type="text/javascript">
15066 * @class Roo.state.CookieProvider
15067 * @extends Roo.state.Provider
15068 * The default Provider implementation which saves state via cookies.
15071 var cp = new Roo.state.CookieProvider({
15073 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
15074 domain: "roojs.com"
15076 Roo.state.Manager.setProvider(cp);
15078 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
15079 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
15080 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
15081 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
15082 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
15083 * domain the page is running on including the 'www' like 'www.roojs.com')
15084 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
15086 * Create a new CookieProvider
15087 * @param {Object} config The configuration object
15089 Roo.state.CookieProvider = function(config){
15090 Roo.state.CookieProvider.superclass.constructor.call(this);
15092 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
15093 this.domain = null;
15094 this.secure = false;
15095 Roo.apply(this, config);
15096 this.state = this.readCookies();
15099 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
15101 set : function(name, value){
15102 if(typeof value == "undefined" || value === null){
15106 this.setCookie(name, value);
15107 Roo.state.CookieProvider.superclass.set.call(this, name, value);
15111 clear : function(name){
15112 this.clearCookie(name);
15113 Roo.state.CookieProvider.superclass.clear.call(this, name);
15117 readCookies : function(){
15119 var c = document.cookie + ";";
15120 var re = /\s?(.*?)=(.*?);/g;
15122 while((matches = re.exec(c)) != null){
15123 var name = matches[1];
15124 var value = matches[2];
15125 if(name && name.substring(0,3) == "ys-"){
15126 cookies[name.substr(3)] = this.decodeValue(value);
15133 setCookie : function(name, value){
15134 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15135 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15136 ((this.path == null) ? "" : ("; path=" + this.path)) +
15137 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15138 ((this.secure == true) ? "; secure" : "");
15142 clearCookie : function(name){
15143 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15144 ((this.path == null) ? "" : ("; path=" + this.path)) +
15145 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15146 ((this.secure == true) ? "; secure" : "");
15150 * Ext JS Library 1.1.1
15151 * Copyright(c) 2006-2007, Ext JS, LLC.
15153 * Originally Released Under LGPL - original licence link has changed is not relivant.
15156 * <script type="text/javascript">
15161 * @class Roo.ComponentMgr
15162 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15165 Roo.ComponentMgr = function(){
15166 var all = new Roo.util.MixedCollection();
15170 * Registers a component.
15171 * @param {Roo.Component} c The component
15173 register : function(c){
15178 * Unregisters a component.
15179 * @param {Roo.Component} c The component
15181 unregister : function(c){
15186 * Returns a component by id
15187 * @param {String} id The component id
15189 get : function(id){
15190 return all.get(id);
15194 * Registers a function that will be called when a specified component is added to ComponentMgr
15195 * @param {String} id The component id
15196 * @param {Funtction} fn The callback function
15197 * @param {Object} scope The scope of the callback
15199 onAvailable : function(id, fn, scope){
15200 all.on("add", function(index, o){
15202 fn.call(scope || o, o);
15203 all.un("add", fn, scope);
15210 * Ext JS Library 1.1.1
15211 * Copyright(c) 2006-2007, Ext JS, LLC.
15213 * Originally Released Under LGPL - original licence link has changed is not relivant.
15216 * <script type="text/javascript">
15220 * @class Roo.Component
15221 * @extends Roo.util.Observable
15222 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15223 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15224 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15225 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15226 * All visual components (widgets) that require rendering into a layout should subclass Component.
15228 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15229 * 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
15230 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15232 Roo.Component = function(config){
15233 config = config || {};
15234 if(config.tagName || config.dom || typeof config == "string"){ // element object
15235 config = {el: config, id: config.id || config};
15237 this.initialConfig = config;
15239 Roo.apply(this, config);
15243 * Fires after the component is disabled.
15244 * @param {Roo.Component} this
15249 * Fires after the component is enabled.
15250 * @param {Roo.Component} this
15254 * @event beforeshow
15255 * Fires before the component is shown. Return false to stop the show.
15256 * @param {Roo.Component} this
15261 * Fires after the component is shown.
15262 * @param {Roo.Component} this
15266 * @event beforehide
15267 * Fires before the component is hidden. Return false to stop the hide.
15268 * @param {Roo.Component} this
15273 * Fires after the component is hidden.
15274 * @param {Roo.Component} this
15278 * @event beforerender
15279 * Fires before the component is rendered. Return false to stop the render.
15280 * @param {Roo.Component} this
15282 beforerender : true,
15285 * Fires after the component is rendered.
15286 * @param {Roo.Component} this
15290 * @event beforedestroy
15291 * Fires before the component is destroyed. Return false to stop the destroy.
15292 * @param {Roo.Component} this
15294 beforedestroy : true,
15297 * Fires after the component is destroyed.
15298 * @param {Roo.Component} this
15303 this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
15305 Roo.ComponentMgr.register(this);
15306 Roo.Component.superclass.constructor.call(this);
15307 this.initComponent();
15308 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15309 this.render(this.renderTo);
15310 delete this.renderTo;
15315 Roo.Component.AUTO_ID = 1000;
15317 Roo.extend(Roo.Component, Roo.util.Observable, {
15319 * @scope Roo.Component.prototype
15321 * true if this component is hidden. Read-only.
15326 * true if this component is disabled. Read-only.
15331 * true if this component has been rendered. Read-only.
15335 /** @cfg {String} disableClass
15336 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15338 disabledClass : "x-item-disabled",
15339 /** @cfg {Boolean} allowDomMove
15340 * Whether the component can move the Dom node when rendering (defaults to true).
15342 allowDomMove : true,
15343 /** @cfg {String} hideMode (display|visibility)
15344 * How this component should hidden. Supported values are
15345 * "visibility" (css visibility), "offsets" (negative offset position) and
15346 * "display" (css display) - defaults to "display".
15348 hideMode: 'display',
15351 ctype : "Roo.Component",
15354 * @cfg {String} actionMode
15355 * which property holds the element that used for hide() / show() / disable() / enable()
15361 getActionEl : function(){
15362 return this[this.actionMode];
15365 initComponent : Roo.emptyFn,
15367 * If this is a lazy rendering component, render it to its container element.
15368 * @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.
15370 render : function(container, position){
15371 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15372 if(!container && this.el){
15373 this.el = Roo.get(this.el);
15374 container = this.el.dom.parentNode;
15375 this.allowDomMove = false;
15377 this.container = Roo.get(container);
15378 this.rendered = true;
15379 if(position !== undefined){
15380 if(typeof position == 'number'){
15381 position = this.container.dom.childNodes[position];
15383 position = Roo.getDom(position);
15386 this.onRender(this.container, position || null);
15388 this.el.addClass(this.cls);
15392 this.el.applyStyles(this.style);
15395 this.fireEvent("render", this);
15396 this.afterRender(this.container);
15408 // default function is not really useful
15409 onRender : function(ct, position){
15411 this.el = Roo.get(this.el);
15412 if(this.allowDomMove !== false){
15413 ct.dom.insertBefore(this.el.dom, position);
15419 getAutoCreate : function(){
15420 var cfg = typeof this.autoCreate == "object" ?
15421 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15422 if(this.id && !cfg.id){
15429 afterRender : Roo.emptyFn,
15432 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15433 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15435 destroy : function(){
15436 if(this.fireEvent("beforedestroy", this) !== false){
15437 this.purgeListeners();
15438 this.beforeDestroy();
15440 this.el.removeAllListeners();
15442 if(this.actionMode == "container"){
15443 this.container.remove();
15447 Roo.ComponentMgr.unregister(this);
15448 this.fireEvent("destroy", this);
15453 beforeDestroy : function(){
15458 onDestroy : function(){
15463 * Returns the underlying {@link Roo.Element}.
15464 * @return {Roo.Element} The element
15466 getEl : function(){
15471 * Returns the id of this component.
15474 getId : function(){
15479 * Try to focus this component.
15480 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15481 * @return {Roo.Component} this
15483 focus : function(selectText){
15486 if(selectText === true){
15487 this.el.dom.select();
15502 * Disable this component.
15503 * @return {Roo.Component} this
15505 disable : function(){
15509 this.disabled = true;
15510 this.fireEvent("disable", this);
15515 onDisable : function(){
15516 this.getActionEl().addClass(this.disabledClass);
15517 this.el.dom.disabled = true;
15521 * Enable this component.
15522 * @return {Roo.Component} this
15524 enable : function(){
15528 this.disabled = false;
15529 this.fireEvent("enable", this);
15534 onEnable : function(){
15535 this.getActionEl().removeClass(this.disabledClass);
15536 this.el.dom.disabled = false;
15540 * Convenience function for setting disabled/enabled by boolean.
15541 * @param {Boolean} disabled
15543 setDisabled : function(disabled){
15544 this[disabled ? "disable" : "enable"]();
15548 * Show this component.
15549 * @return {Roo.Component} this
15552 if(this.fireEvent("beforeshow", this) !== false){
15553 this.hidden = false;
15557 this.fireEvent("show", this);
15563 onShow : function(){
15564 var ae = this.getActionEl();
15565 if(this.hideMode == 'visibility'){
15566 ae.dom.style.visibility = "visible";
15567 }else if(this.hideMode == 'offsets'){
15568 ae.removeClass('x-hidden');
15570 ae.dom.style.display = "";
15575 * Hide this component.
15576 * @return {Roo.Component} this
15579 if(this.fireEvent("beforehide", this) !== false){
15580 this.hidden = true;
15584 this.fireEvent("hide", this);
15590 onHide : function(){
15591 var ae = this.getActionEl();
15592 if(this.hideMode == 'visibility'){
15593 ae.dom.style.visibility = "hidden";
15594 }else if(this.hideMode == 'offsets'){
15595 ae.addClass('x-hidden');
15597 ae.dom.style.display = "none";
15602 * Convenience function to hide or show this component by boolean.
15603 * @param {Boolean} visible True to show, false to hide
15604 * @return {Roo.Component} this
15606 setVisible: function(visible){
15616 * Returns true if this component is visible.
15618 isVisible : function(){
15619 return this.getActionEl().isVisible();
15622 cloneConfig : function(overrides){
15623 overrides = overrides || {};
15624 var id = overrides.id || Roo.id();
15625 var cfg = Roo.applyIf(overrides, this.initialConfig);
15626 cfg.id = id; // prevent dup id
15627 return new this.constructor(cfg);
15631 * Ext JS Library 1.1.1
15632 * Copyright(c) 2006-2007, Ext JS, LLC.
15634 * Originally Released Under LGPL - original licence link has changed is not relivant.
15637 * <script type="text/javascript">
15641 * @class Roo.BoxComponent
15642 * @extends Roo.Component
15643 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15644 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15645 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15646 * layout containers.
15648 * @param {Roo.Element/String/Object} config The configuration options.
15650 Roo.BoxComponent = function(config){
15651 Roo.Component.call(this, config);
15655 * Fires after the component is resized.
15656 * @param {Roo.Component} this
15657 * @param {Number} adjWidth The box-adjusted width that was set
15658 * @param {Number} adjHeight The box-adjusted height that was set
15659 * @param {Number} rawWidth The width that was originally specified
15660 * @param {Number} rawHeight The height that was originally specified
15665 * Fires after the component is moved.
15666 * @param {Roo.Component} this
15667 * @param {Number} x The new x position
15668 * @param {Number} y The new y position
15674 Roo.extend(Roo.BoxComponent, Roo.Component, {
15675 // private, set in afterRender to signify that the component has been rendered
15677 // private, used to defer height settings to subclasses
15678 deferHeight: false,
15679 /** @cfg {Number} width
15680 * width (optional) size of component
15682 /** @cfg {Number} height
15683 * height (optional) size of component
15687 * Sets the width and height of the component. This method fires the resize event. This method can accept
15688 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15689 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15690 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15691 * @return {Roo.BoxComponent} this
15693 setSize : function(w, h){
15694 // support for standard size objects
15695 if(typeof w == 'object'){
15700 if(!this.boxReady){
15706 // prevent recalcs when not needed
15707 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15710 this.lastSize = {width: w, height: h};
15712 var adj = this.adjustSize(w, h);
15713 var aw = adj.width, ah = adj.height;
15714 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15715 var rz = this.getResizeEl();
15716 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15717 rz.setSize(aw, ah);
15718 }else if(!this.deferHeight && ah !== undefined){
15720 }else if(aw !== undefined){
15723 this.onResize(aw, ah, w, h);
15724 this.fireEvent('resize', this, aw, ah, w, h);
15730 * Gets the current size of the component's underlying element.
15731 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15733 getSize : function(){
15734 return this.el.getSize();
15738 * Gets the current XY position of the component's underlying element.
15739 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15740 * @return {Array} The XY position of the element (e.g., [100, 200])
15742 getPosition : function(local){
15743 if(local === true){
15744 return [this.el.getLeft(true), this.el.getTop(true)];
15746 return this.xy || this.el.getXY();
15750 * Gets the current box measurements of the component's underlying element.
15751 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15752 * @returns {Object} box An object in the format {x, y, width, height}
15754 getBox : function(local){
15755 var s = this.el.getSize();
15757 s.x = this.el.getLeft(true);
15758 s.y = this.el.getTop(true);
15760 var xy = this.xy || this.el.getXY();
15768 * Sets the current box measurements of the component's underlying element.
15769 * @param {Object} box An object in the format {x, y, width, height}
15770 * @returns {Roo.BoxComponent} this
15772 updateBox : function(box){
15773 this.setSize(box.width, box.height);
15774 this.setPagePosition(box.x, box.y);
15779 getResizeEl : function(){
15780 return this.resizeEl || this.el;
15784 getPositionEl : function(){
15785 return this.positionEl || this.el;
15789 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15790 * This method fires the move event.
15791 * @param {Number} left The new left
15792 * @param {Number} top The new top
15793 * @returns {Roo.BoxComponent} this
15795 setPosition : function(x, y){
15798 if(!this.boxReady){
15801 var adj = this.adjustPosition(x, y);
15802 var ax = adj.x, ay = adj.y;
15804 var el = this.getPositionEl();
15805 if(ax !== undefined || ay !== undefined){
15806 if(ax !== undefined && ay !== undefined){
15807 el.setLeftTop(ax, ay);
15808 }else if(ax !== undefined){
15810 }else if(ay !== undefined){
15813 this.onPosition(ax, ay);
15814 this.fireEvent('move', this, ax, ay);
15820 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15821 * This method fires the move event.
15822 * @param {Number} x The new x position
15823 * @param {Number} y The new y position
15824 * @returns {Roo.BoxComponent} this
15826 setPagePosition : function(x, y){
15829 if(!this.boxReady){
15832 if(x === undefined || y === undefined){ // cannot translate undefined points
15835 var p = this.el.translatePoints(x, y);
15836 this.setPosition(p.left, p.top);
15841 onRender : function(ct, position){
15842 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15844 this.resizeEl = Roo.get(this.resizeEl);
15846 if(this.positionEl){
15847 this.positionEl = Roo.get(this.positionEl);
15852 afterRender : function(){
15853 Roo.BoxComponent.superclass.afterRender.call(this);
15854 this.boxReady = true;
15855 this.setSize(this.width, this.height);
15856 if(this.x || this.y){
15857 this.setPosition(this.x, this.y);
15859 if(this.pageX || this.pageY){
15860 this.setPagePosition(this.pageX, this.pageY);
15865 * Force the component's size to recalculate based on the underlying element's current height and width.
15866 * @returns {Roo.BoxComponent} this
15868 syncSize : function(){
15869 delete this.lastSize;
15870 this.setSize(this.el.getWidth(), this.el.getHeight());
15875 * Called after the component is resized, this method is empty by default but can be implemented by any
15876 * subclass that needs to perform custom logic after a resize occurs.
15877 * @param {Number} adjWidth The box-adjusted width that was set
15878 * @param {Number} adjHeight The box-adjusted height that was set
15879 * @param {Number} rawWidth The width that was originally specified
15880 * @param {Number} rawHeight The height that was originally specified
15882 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15887 * Called after the component is moved, this method is empty by default but can be implemented by any
15888 * subclass that needs to perform custom logic after a move occurs.
15889 * @param {Number} x The new x position
15890 * @param {Number} y The new y position
15892 onPosition : function(x, y){
15897 adjustSize : function(w, h){
15898 if(this.autoWidth){
15901 if(this.autoHeight){
15904 return {width : w, height: h};
15908 adjustPosition : function(x, y){
15909 return {x : x, y: y};
15912 * Original code for Roojs - LGPL
15913 * <script type="text/javascript">
15917 * @class Roo.XComponent
15918 * A delayed Element creator...
15919 * Or a way to group chunks of interface together.
15920 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15921 * used in conjunction with XComponent.build() it will create an instance of each element,
15922 * then call addxtype() to build the User interface.
15924 * Mypart.xyx = new Roo.XComponent({
15926 parent : 'Mypart.xyz', // empty == document.element.!!
15930 disabled : function() {}
15932 tree : function() { // return an tree of xtype declared components
15936 xtype : 'NestedLayoutPanel',
15943 * It can be used to build a big heiracy, with parent etc.
15944 * or you can just use this to render a single compoent to a dom element
15945 * MYPART.render(Roo.Element | String(id) | dom_element )
15952 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15953 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15955 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15957 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15958 * - if mulitple topModules exist, the last one is defined as the top module.
15962 * When the top level or multiple modules are to embedded into a existing HTML page,
15963 * the parent element can container '#id' of the element where the module will be drawn.
15967 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15968 * it relies more on a include mechanism, where sub modules are included into an outer page.
15969 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15971 * Bootstrap Roo Included elements
15973 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15974 * hence confusing the component builder as it thinks there are multiple top level elements.
15978 * @extends Roo.util.Observable
15980 * @param cfg {Object} configuration of component
15983 Roo.XComponent = function(cfg) {
15984 Roo.apply(this, cfg);
15988 * Fires when this the componnt is built
15989 * @param {Roo.XComponent} c the component
15994 this.region = this.region || 'center'; // default..
15995 Roo.XComponent.register(this);
15996 this.modules = false;
15997 this.el = false; // where the layout goes..
16001 Roo.extend(Roo.XComponent, Roo.util.Observable, {
16004 * The created element (with Roo.factory())
16005 * @type {Roo.Layout}
16011 * for BC - use el in new code
16012 * @type {Roo.Layout}
16018 * for BC - use el in new code
16019 * @type {Roo.Layout}
16024 * @cfg {Function|boolean} disabled
16025 * If this module is disabled by some rule, return true from the funtion
16030 * @cfg {String} parent
16031 * Name of parent element which it get xtype added to..
16036 * @cfg {String} order
16037 * Used to set the order in which elements are created (usefull for multiple tabs)
16042 * @cfg {String} name
16043 * String to display while loading.
16047 * @cfg {String} region
16048 * Region to render component to (defaults to center)
16053 * @cfg {Array} items
16054 * A single item array - the first element is the root of the tree..
16055 * It's done this way to stay compatible with the Xtype system...
16061 * The method that retuns the tree of parts that make up this compoennt
16068 * render element to dom or tree
16069 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
16072 render : function(el)
16076 var hp = this.parent ? 1 : 0;
16077 Roo.debug && Roo.log(this);
16079 var tree = this._tree ? this._tree() : this.tree();
16082 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
16083 // if parent is a '#.....' string, then let's use that..
16084 var ename = this.parent.substr(1);
16085 this.parent = false;
16086 Roo.debug && Roo.log(ename);
16088 case 'bootstrap-body':
16089 if (typeof(tree.el) != 'undefined' && tree.el == document.body) {
16090 // this is the BorderLayout standard?
16091 this.parent = { el : true };
16094 if (["Nest", "Content", "Grid", "Tree"].indexOf(tree.xtype) > -1) {
16095 // need to insert stuff...
16097 el : new Roo.bootstrap.layout.Border({
16098 el : document.body,
16104 tabPosition: 'top',
16105 //resizeTabs: true,
16106 alwaysShowTabs: true,
16116 if (typeof(Roo.bootstrap.Body) != 'undefined' ) {
16117 this.parent = { el : new Roo.bootstrap.Body() };
16118 Roo.debug && Roo.log("setting el to doc body");
16121 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
16125 this.parent = { el : true};
16128 el = Roo.get(ename);
16129 if (typeof(Roo.bootstrap) != 'undefined' && tree['|xns'] == 'Roo.bootstrap') {
16130 this.parent = { el : true};
16137 if (!el && !this.parent) {
16138 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
16143 Roo.debug && Roo.log("EL:");
16144 Roo.debug && Roo.log(el);
16145 Roo.debug && Roo.log("this.parent.el:");
16146 Roo.debug && Roo.log(this.parent.el);
16149 // altertive root elements ??? - we need a better way to indicate these.
16150 var is_alt = Roo.XComponent.is_alt ||
16151 (typeof(tree.el) != 'undefined' && tree.el == document.body) ||
16152 (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
16153 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
16157 if (!this.parent && is_alt) {
16158 //el = Roo.get(document.body);
16159 this.parent = { el : true };
16164 if (!this.parent) {
16166 Roo.debug && Roo.log("no parent - creating one");
16168 el = el ? Roo.get(el) : false;
16170 if (typeof(Roo.BorderLayout) == 'undefined' ) {
16173 el : new Roo.bootstrap.layout.Border({
16174 el: el || document.body,
16180 tabPosition: 'top',
16181 //resizeTabs: true,
16182 alwaysShowTabs: false,
16185 overflow: 'visible'
16191 // it's a top level one..
16193 el : new Roo.BorderLayout(el || document.body, {
16198 tabPosition: 'top',
16199 //resizeTabs: true,
16200 alwaysShowTabs: el && hp? false : true,
16201 hideTabs: el || !hp ? true : false,
16209 if (!this.parent.el) {
16210 // probably an old style ctor, which has been disabled.
16214 // The 'tree' method is '_tree now'
16216 tree.region = tree.region || this.region;
16217 var is_body = false;
16218 if (this.parent.el === true) {
16219 // bootstrap... - body..
16223 this.parent.el = Roo.factory(tree);
16227 this.el = this.parent.el.addxtype(tree, undefined, is_body);
16228 this.fireEvent('built', this);
16230 this.panel = this.el;
16231 this.layout = this.panel.layout;
16232 this.parentLayout = this.parent.layout || false;
16238 Roo.apply(Roo.XComponent, {
16240 * @property hideProgress
16241 * true to disable the building progress bar.. usefull on single page renders.
16244 hideProgress : false,
16246 * @property buildCompleted
16247 * True when the builder has completed building the interface.
16250 buildCompleted : false,
16253 * @property topModule
16254 * the upper most module - uses document.element as it's constructor.
16261 * @property modules
16262 * array of modules to be created by registration system.
16263 * @type {Array} of Roo.XComponent
16268 * @property elmodules
16269 * array of modules to be created by which use #ID
16270 * @type {Array} of Roo.XComponent
16277 * Is an alternative Root - normally used by bootstrap or other systems,
16278 * where the top element in the tree can wrap 'body'
16279 * @type {boolean} (default false)
16284 * @property build_from_html
16285 * Build elements from html - used by bootstrap HTML stuff
16286 * - this is cleared after build is completed
16287 * @type {boolean} (default false)
16290 build_from_html : false,
16292 * Register components to be built later.
16294 * This solves the following issues
16295 * - Building is not done on page load, but after an authentication process has occured.
16296 * - Interface elements are registered on page load
16297 * - Parent Interface elements may not be loaded before child, so this handles that..
16304 module : 'Pman.Tab.projectMgr',
16306 parent : 'Pman.layout',
16307 disabled : false, // or use a function..
16310 * * @param {Object} details about module
16312 register : function(obj) {
16314 Roo.XComponent.event.fireEvent('register', obj);
16315 switch(typeof(obj.disabled) ) {
16321 if ( obj.disabled() ) {
16327 if (obj.disabled) {
16333 this.modules.push(obj);
16337 * convert a string to an object..
16338 * eg. 'AAA.BBB' -> finds AAA.BBB
16342 toObject : function(str)
16344 if (!str || typeof(str) == 'object') {
16347 if (str.substring(0,1) == '#') {
16351 var ar = str.split('.');
16356 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16358 throw "Module not found : " + str;
16362 throw "Module not found : " + str;
16364 Roo.each(ar, function(e) {
16365 if (typeof(o[e]) == 'undefined') {
16366 throw "Module not found : " + str;
16377 * move modules into their correct place in the tree..
16380 preBuild : function ()
16383 Roo.each(this.modules , function (obj)
16385 Roo.XComponent.event.fireEvent('beforebuild', obj);
16387 var opar = obj.parent;
16389 obj.parent = this.toObject(opar);
16391 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16396 Roo.debug && Roo.log("GOT top level module");
16397 Roo.debug && Roo.log(obj);
16398 obj.modules = new Roo.util.MixedCollection(false,
16399 function(o) { return o.order + '' }
16401 this.topModule = obj;
16404 // parent is a string (usually a dom element name..)
16405 if (typeof(obj.parent) == 'string') {
16406 this.elmodules.push(obj);
16409 if (obj.parent.constructor != Roo.XComponent) {
16410 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16412 if (!obj.parent.modules) {
16413 obj.parent.modules = new Roo.util.MixedCollection(false,
16414 function(o) { return o.order + '' }
16417 if (obj.parent.disabled) {
16418 obj.disabled = true;
16420 obj.parent.modules.add(obj);
16425 * make a list of modules to build.
16426 * @return {Array} list of modules.
16429 buildOrder : function()
16432 var cmp = function(a,b) {
16433 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16435 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16436 throw "No top level modules to build";
16439 // make a flat list in order of modules to build.
16440 var mods = this.topModule ? [ this.topModule ] : [];
16443 // elmodules (is a list of DOM based modules )
16444 Roo.each(this.elmodules, function(e) {
16446 if (!this.topModule &&
16447 typeof(e.parent) == 'string' &&
16448 e.parent.substring(0,1) == '#' &&
16449 Roo.get(e.parent.substr(1))
16452 _this.topModule = e;
16458 // add modules to their parents..
16459 var addMod = function(m) {
16460 Roo.debug && Roo.log("build Order: add: " + m.name);
16463 if (m.modules && !m.disabled) {
16464 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16465 m.modules.keySort('ASC', cmp );
16466 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16468 m.modules.each(addMod);
16470 Roo.debug && Roo.log("build Order: no child modules");
16472 // not sure if this is used any more..
16474 m.finalize.name = m.name + " (clean up) ";
16475 mods.push(m.finalize);
16479 if (this.topModule && this.topModule.modules) {
16480 this.topModule.modules.keySort('ASC', cmp );
16481 this.topModule.modules.each(addMod);
16487 * Build the registered modules.
16488 * @param {Object} parent element.
16489 * @param {Function} optional method to call after module has been added.
16493 build : function(opts)
16496 if (typeof(opts) != 'undefined') {
16497 Roo.apply(this,opts);
16501 var mods = this.buildOrder();
16503 //this.allmods = mods;
16504 //Roo.debug && Roo.log(mods);
16506 if (!mods.length) { // should not happen
16507 throw "NO modules!!!";
16511 var msg = "Building Interface...";
16512 // flash it up as modal - so we store the mask!?
16513 if (!this.hideProgress && Roo.MessageBox) {
16514 Roo.MessageBox.show({ title: 'loading' });
16515 Roo.MessageBox.show({
16516 title: "Please wait...",
16525 var total = mods.length;
16528 var progressRun = function() {
16529 if (!mods.length) {
16530 Roo.debug && Roo.log('hide?');
16531 if (!this.hideProgress && Roo.MessageBox) {
16532 Roo.MessageBox.hide();
16534 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16536 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16542 var m = mods.shift();
16545 Roo.debug && Roo.log(m);
16546 // not sure if this is supported any more.. - modules that are are just function
16547 if (typeof(m) == 'function') {
16549 return progressRun.defer(10, _this);
16553 msg = "Building Interface " + (total - mods.length) +
16555 (m.name ? (' - ' + m.name) : '');
16556 Roo.debug && Roo.log(msg);
16557 if (!_this.hideProgress && Roo.MessageBox) {
16558 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16562 // is the module disabled?
16563 var disabled = (typeof(m.disabled) == 'function') ?
16564 m.disabled.call(m.module.disabled) : m.disabled;
16568 return progressRun(); // we do not update the display!
16576 // it's 10 on top level, and 1 on others??? why...
16577 return progressRun.defer(10, _this);
16580 progressRun.defer(1, _this);
16594 * wrapper for event.on - aliased later..
16595 * Typically use to register a event handler for register:
16597 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16606 Roo.XComponent.event = new Roo.util.Observable({
16610 * Fires when an Component is registered,
16611 * set the disable property on the Component to stop registration.
16612 * @param {Roo.XComponent} c the component being registerd.
16617 * @event beforebuild
16618 * Fires before each Component is built
16619 * can be used to apply permissions.
16620 * @param {Roo.XComponent} c the component being registerd.
16623 'beforebuild' : true,
16625 * @event buildcomplete
16626 * Fires on the top level element when all elements have been built
16627 * @param {Roo.XComponent} the top level component.
16629 'buildcomplete' : true
16634 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);
16637 * marked - a markdown parser
16638 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
16639 * https://github.com/chjj/marked
16645 * Roo.Markdown - is a very crude wrapper around marked..
16649 * alert( Roo.Markdown.toHtml("Markdown *rocks*.") );
16651 * Note: move the sample code to the bottom of this
16652 * file before uncommenting it.
16657 Roo.Markdown.toHtml = function(text) {
16659 var c = new Roo.Markdown.marked.setOptions({
16660 renderer: new Roo.Markdown.marked.Renderer(),
16671 text = text.replace(/\\\n/g,' ');
16672 return Roo.Markdown.marked(text);
16677 // Wraps all "globals" so that the only thing
16678 // exposed is makeHtml().
16683 * Block-Level Grammar
16688 code: /^( {4}[^\n]+\n*)+/,
16690 hr: /^( *[-*_]){3,} *(?:\n+|$)/,
16691 heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
16693 lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
16694 blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
16695 list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
16696 html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
16697 def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
16699 paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
16703 block.bullet = /(?:[*+-]|\d+\.)/;
16704 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
16705 block.item = replace(block.item, 'gm')
16706 (/bull/g, block.bullet)
16709 block.list = replace(block.list)
16710 (/bull/g, block.bullet)
16711 ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
16712 ('def', '\\n+(?=' + block.def.source + ')')
16715 block.blockquote = replace(block.blockquote)
16719 block._tag = '(?!(?:'
16720 + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
16721 + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
16722 + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
16724 block.html = replace(block.html)
16725 ('comment', /<!--[\s\S]*?-->/)
16726 ('closed', /<(tag)[\s\S]+?<\/\1>/)
16727 ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
16728 (/tag/g, block._tag)
16731 block.paragraph = replace(block.paragraph)
16733 ('heading', block.heading)
16734 ('lheading', block.lheading)
16735 ('blockquote', block.blockquote)
16736 ('tag', '<' + block._tag)
16741 * Normal Block Grammar
16744 block.normal = merge({}, block);
16747 * GFM Block Grammar
16750 block.gfm = merge({}, block.normal, {
16751 fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
16753 heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
16756 block.gfm.paragraph = replace(block.paragraph)
16758 + block.gfm.fences.source.replace('\\1', '\\2') + '|'
16759 + block.list.source.replace('\\1', '\\3') + '|')
16763 * GFM + Tables Block Grammar
16766 block.tables = merge({}, block.gfm, {
16767 nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
16768 table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
16775 function Lexer(options) {
16777 this.tokens.links = {};
16778 this.options = options || marked.defaults;
16779 this.rules = block.normal;
16781 if (this.options.gfm) {
16782 if (this.options.tables) {
16783 this.rules = block.tables;
16785 this.rules = block.gfm;
16791 * Expose Block Rules
16794 Lexer.rules = block;
16797 * Static Lex Method
16800 Lexer.lex = function(src, options) {
16801 var lexer = new Lexer(options);
16802 return lexer.lex(src);
16809 Lexer.prototype.lex = function(src) {
16811 .replace(/\r\n|\r/g, '\n')
16812 .replace(/\t/g, ' ')
16813 .replace(/\u00a0/g, ' ')
16814 .replace(/\u2424/g, '\n');
16816 return this.token(src, true);
16823 Lexer.prototype.token = function(src, top, bq) {
16824 var src = src.replace(/^ +$/gm, '')
16837 if (cap = this.rules.newline.exec(src)) {
16838 src = src.substring(cap[0].length);
16839 if (cap[0].length > 1) {
16847 if (cap = this.rules.code.exec(src)) {
16848 src = src.substring(cap[0].length);
16849 cap = cap[0].replace(/^ {4}/gm, '');
16852 text: !this.options.pedantic
16853 ? cap.replace(/\n+$/, '')
16860 if (cap = this.rules.fences.exec(src)) {
16861 src = src.substring(cap[0].length);
16871 if (cap = this.rules.heading.exec(src)) {
16872 src = src.substring(cap[0].length);
16875 depth: cap[1].length,
16881 // table no leading pipe (gfm)
16882 if (top && (cap = this.rules.nptable.exec(src))) {
16883 src = src.substring(cap[0].length);
16887 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
16888 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
16889 cells: cap[3].replace(/\n$/, '').split('\n')
16892 for (i = 0; i < item.align.length; i++) {
16893 if (/^ *-+: *$/.test(item.align[i])) {
16894 item.align[i] = 'right';
16895 } else if (/^ *:-+: *$/.test(item.align[i])) {
16896 item.align[i] = 'center';
16897 } else if (/^ *:-+ *$/.test(item.align[i])) {
16898 item.align[i] = 'left';
16900 item.align[i] = null;
16904 for (i = 0; i < item.cells.length; i++) {
16905 item.cells[i] = item.cells[i].split(/ *\| */);
16908 this.tokens.push(item);
16914 if (cap = this.rules.lheading.exec(src)) {
16915 src = src.substring(cap[0].length);
16918 depth: cap[2] === '=' ? 1 : 2,
16925 if (cap = this.rules.hr.exec(src)) {
16926 src = src.substring(cap[0].length);
16934 if (cap = this.rules.blockquote.exec(src)) {
16935 src = src.substring(cap[0].length);
16938 type: 'blockquote_start'
16941 cap = cap[0].replace(/^ *> ?/gm, '');
16943 // Pass `top` to keep the current
16944 // "toplevel" state. This is exactly
16945 // how markdown.pl works.
16946 this.token(cap, top, true);
16949 type: 'blockquote_end'
16956 if (cap = this.rules.list.exec(src)) {
16957 src = src.substring(cap[0].length);
16961 type: 'list_start',
16962 ordered: bull.length > 1
16965 // Get each top-level item.
16966 cap = cap[0].match(this.rules.item);
16972 for (; i < l; i++) {
16975 // Remove the list item's bullet
16976 // so it is seen as the next token.
16977 space = item.length;
16978 item = item.replace(/^ *([*+-]|\d+\.) +/, '');
16980 // Outdent whatever the
16981 // list item contains. Hacky.
16982 if (~item.indexOf('\n ')) {
16983 space -= item.length;
16984 item = !this.options.pedantic
16985 ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
16986 : item.replace(/^ {1,4}/gm, '');
16989 // Determine whether the next list item belongs here.
16990 // Backpedal if it does not belong in this list.
16991 if (this.options.smartLists && i !== l - 1) {
16992 b = block.bullet.exec(cap[i + 1])[0];
16993 if (bull !== b && !(bull.length > 1 && b.length > 1)) {
16994 src = cap.slice(i + 1).join('\n') + src;
16999 // Determine whether item is loose or not.
17000 // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
17001 // for discount behavior.
17002 loose = next || /\n\n(?!\s*$)/.test(item);
17004 next = item.charAt(item.length - 1) === '\n';
17005 if (!loose) { loose = next; }
17010 ? 'loose_item_start'
17011 : 'list_item_start'
17015 this.token(item, false, bq);
17018 type: 'list_item_end'
17030 if (cap = this.rules.html.exec(src)) {
17031 src = src.substring(cap[0].length);
17033 type: this.options.sanitize
17036 pre: !this.options.sanitizer
17037 && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
17044 if ((!bq && top) && (cap = this.rules.def.exec(src))) {
17045 src = src.substring(cap[0].length);
17046 this.tokens.links[cap[1].toLowerCase()] = {
17054 if (top && (cap = this.rules.table.exec(src))) {
17055 src = src.substring(cap[0].length);
17059 header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
17060 align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
17061 cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
17064 for (i = 0; i < item.align.length; i++) {
17065 if (/^ *-+: *$/.test(item.align[i])) {
17066 item.align[i] = 'right';
17067 } else if (/^ *:-+: *$/.test(item.align[i])) {
17068 item.align[i] = 'center';
17069 } else if (/^ *:-+ *$/.test(item.align[i])) {
17070 item.align[i] = 'left';
17072 item.align[i] = null;
17076 for (i = 0; i < item.cells.length; i++) {
17077 item.cells[i] = item.cells[i]
17078 .replace(/^ *\| *| *\| *$/g, '')
17082 this.tokens.push(item);
17087 // top-level paragraph
17088 if (top && (cap = this.rules.paragraph.exec(src))) {
17089 src = src.substring(cap[0].length);
17092 text: cap[1].charAt(cap[1].length - 1) === '\n'
17093 ? cap[1].slice(0, -1)
17100 if (cap = this.rules.text.exec(src)) {
17101 // Top-level should never reach here.
17102 src = src.substring(cap[0].length);
17112 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17116 return this.tokens;
17120 * Inline-Level Grammar
17124 escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
17125 autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
17127 tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
17128 link: /^!?\[(inside)\]\(href\)/,
17129 reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
17130 nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
17131 strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
17132 em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
17133 code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
17134 br: /^ {2,}\n(?!\s*$)/,
17136 text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
17139 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
17140 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
17142 inline.link = replace(inline.link)
17143 ('inside', inline._inside)
17144 ('href', inline._href)
17147 inline.reflink = replace(inline.reflink)
17148 ('inside', inline._inside)
17152 * Normal Inline Grammar
17155 inline.normal = merge({}, inline);
17158 * Pedantic Inline Grammar
17161 inline.pedantic = merge({}, inline.normal, {
17162 strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
17163 em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
17167 * GFM Inline Grammar
17170 inline.gfm = merge({}, inline.normal, {
17171 escape: replace(inline.escape)('])', '~|])')(),
17172 url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
17173 del: /^~~(?=\S)([\s\S]*?\S)~~/,
17174 text: replace(inline.text)
17176 ('|', '|https?://|')
17181 * GFM + Line Breaks Inline Grammar
17184 inline.breaks = merge({}, inline.gfm, {
17185 br: replace(inline.br)('{2,}', '*')(),
17186 text: replace(inline.gfm.text)('{2,}', '*')()
17190 * Inline Lexer & Compiler
17193 function InlineLexer(links, options) {
17194 this.options = options || marked.defaults;
17195 this.links = links;
17196 this.rules = inline.normal;
17197 this.renderer = this.options.renderer || new Renderer;
17198 this.renderer.options = this.options;
17202 Error('Tokens array requires a `links` property.');
17205 if (this.options.gfm) {
17206 if (this.options.breaks) {
17207 this.rules = inline.breaks;
17209 this.rules = inline.gfm;
17211 } else if (this.options.pedantic) {
17212 this.rules = inline.pedantic;
17217 * Expose Inline Rules
17220 InlineLexer.rules = inline;
17223 * Static Lexing/Compiling Method
17226 InlineLexer.output = function(src, links, options) {
17227 var inline = new InlineLexer(links, options);
17228 return inline.output(src);
17235 InlineLexer.prototype.output = function(src) {
17244 if (cap = this.rules.escape.exec(src)) {
17245 src = src.substring(cap[0].length);
17251 if (cap = this.rules.autolink.exec(src)) {
17252 src = src.substring(cap[0].length);
17253 if (cap[2] === '@') {
17254 text = cap[1].charAt(6) === ':'
17255 ? this.mangle(cap[1].substring(7))
17256 : this.mangle(cap[1]);
17257 href = this.mangle('mailto:') + text;
17259 text = escape(cap[1]);
17262 out += this.renderer.link(href, null, text);
17267 if (!this.inLink && (cap = this.rules.url.exec(src))) {
17268 src = src.substring(cap[0].length);
17269 text = escape(cap[1]);
17271 out += this.renderer.link(href, null, text);
17276 if (cap = this.rules.tag.exec(src)) {
17277 if (!this.inLink && /^<a /i.test(cap[0])) {
17278 this.inLink = true;
17279 } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
17280 this.inLink = false;
17282 src = src.substring(cap[0].length);
17283 out += this.options.sanitize
17284 ? this.options.sanitizer
17285 ? this.options.sanitizer(cap[0])
17292 if (cap = this.rules.link.exec(src)) {
17293 src = src.substring(cap[0].length);
17294 this.inLink = true;
17295 out += this.outputLink(cap, {
17299 this.inLink = false;
17304 if ((cap = this.rules.reflink.exec(src))
17305 || (cap = this.rules.nolink.exec(src))) {
17306 src = src.substring(cap[0].length);
17307 link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
17308 link = this.links[link.toLowerCase()];
17309 if (!link || !link.href) {
17310 out += cap[0].charAt(0);
17311 src = cap[0].substring(1) + src;
17314 this.inLink = true;
17315 out += this.outputLink(cap, link);
17316 this.inLink = false;
17321 if (cap = this.rules.strong.exec(src)) {
17322 src = src.substring(cap[0].length);
17323 out += this.renderer.strong(this.output(cap[2] || cap[1]));
17328 if (cap = this.rules.em.exec(src)) {
17329 src = src.substring(cap[0].length);
17330 out += this.renderer.em(this.output(cap[2] || cap[1]));
17335 if (cap = this.rules.code.exec(src)) {
17336 src = src.substring(cap[0].length);
17337 out += this.renderer.codespan(escape(cap[2], true));
17342 if (cap = this.rules.br.exec(src)) {
17343 src = src.substring(cap[0].length);
17344 out += this.renderer.br();
17349 if (cap = this.rules.del.exec(src)) {
17350 src = src.substring(cap[0].length);
17351 out += this.renderer.del(this.output(cap[1]));
17356 if (cap = this.rules.text.exec(src)) {
17357 src = src.substring(cap[0].length);
17358 out += this.renderer.text(escape(this.smartypants(cap[0])));
17364 Error('Infinite loop on byte: ' + src.charCodeAt(0));
17375 InlineLexer.prototype.outputLink = function(cap, link) {
17376 var href = escape(link.href)
17377 , title = link.title ? escape(link.title) : null;
17379 return cap[0].charAt(0) !== '!'
17380 ? this.renderer.link(href, title, this.output(cap[1]))
17381 : this.renderer.image(href, title, escape(cap[1]));
17385 * Smartypants Transformations
17388 InlineLexer.prototype.smartypants = function(text) {
17389 if (!this.options.smartypants) { return text; }
17392 .replace(/---/g, '\u2014')
17394 .replace(/--/g, '\u2013')
17396 .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
17397 // closing singles & apostrophes
17398 .replace(/'/g, '\u2019')
17400 .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
17402 .replace(/"/g, '\u201d')
17404 .replace(/\.{3}/g, '\u2026');
17411 InlineLexer.prototype.mangle = function(text) {
17412 if (!this.options.mangle) { return text; }
17418 for (; i < l; i++) {
17419 ch = text.charCodeAt(i);
17420 if (Math.random() > 0.5) {
17421 ch = 'x' + ch.toString(16);
17423 out += '&#' + ch + ';';
17433 function Renderer(options) {
17434 this.options = options || {};
17437 Renderer.prototype.code = function(code, lang, escaped) {
17438 if (this.options.highlight) {
17439 var out = this.options.highlight(code, lang);
17440 if (out != null && out !== code) {
17445 // hack!!! - it's already escapeD?
17450 return '<pre><code>'
17451 + (escaped ? code : escape(code, true))
17452 + '\n</code></pre>';
17455 return '<pre><code class="'
17456 + this.options.langPrefix
17457 + escape(lang, true)
17459 + (escaped ? code : escape(code, true))
17460 + '\n</code></pre>\n';
17463 Renderer.prototype.blockquote = function(quote) {
17464 return '<blockquote>\n' + quote + '</blockquote>\n';
17467 Renderer.prototype.html = function(html) {
17471 Renderer.prototype.heading = function(text, level, raw) {
17475 + this.options.headerPrefix
17476 + raw.toLowerCase().replace(/[^\w]+/g, '-')
17484 Renderer.prototype.hr = function() {
17485 return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
17488 Renderer.prototype.list = function(body, ordered) {
17489 var type = ordered ? 'ol' : 'ul';
17490 return '<' + type + '>\n' + body + '</' + type + '>\n';
17493 Renderer.prototype.listitem = function(text) {
17494 return '<li>' + text + '</li>\n';
17497 Renderer.prototype.paragraph = function(text) {
17498 return '<p>' + text + '</p>\n';
17501 Renderer.prototype.table = function(header, body) {
17502 return '<table class="table table-striped">\n'
17512 Renderer.prototype.tablerow = function(content) {
17513 return '<tr>\n' + content + '</tr>\n';
17516 Renderer.prototype.tablecell = function(content, flags) {
17517 var type = flags.header ? 'th' : 'td';
17518 var tag = flags.align
17519 ? '<' + type + ' style="text-align:' + flags.align + '">'
17520 : '<' + type + '>';
17521 return tag + content + '</' + type + '>\n';
17524 // span level renderer
17525 Renderer.prototype.strong = function(text) {
17526 return '<strong>' + text + '</strong>';
17529 Renderer.prototype.em = function(text) {
17530 return '<em>' + text + '</em>';
17533 Renderer.prototype.codespan = function(text) {
17534 return '<code>' + text + '</code>';
17537 Renderer.prototype.br = function() {
17538 return this.options.xhtml ? '<br/>' : '<br>';
17541 Renderer.prototype.del = function(text) {
17542 return '<del>' + text + '</del>';
17545 Renderer.prototype.link = function(href, title, text) {
17546 if (this.options.sanitize) {
17548 var prot = decodeURIComponent(unescape(href))
17549 .replace(/[^\w:]/g, '')
17554 if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
17558 var out = '<a href="' + href + '"';
17560 out += ' title="' + title + '"';
17562 out += '>' + text + '</a>';
17566 Renderer.prototype.image = function(href, title, text) {
17567 var out = '<img src="' + href + '" alt="' + text + '"';
17569 out += ' title="' + title + '"';
17571 out += this.options.xhtml ? '/>' : '>';
17575 Renderer.prototype.text = function(text) {
17580 * Parsing & Compiling
17583 function Parser(options) {
17586 this.options = options || marked.defaults;
17587 this.options.renderer = this.options.renderer || new Renderer;
17588 this.renderer = this.options.renderer;
17589 this.renderer.options = this.options;
17593 * Static Parse Method
17596 Parser.parse = function(src, options, renderer) {
17597 var parser = new Parser(options, renderer);
17598 return parser.parse(src);
17605 Parser.prototype.parse = function(src) {
17606 this.inline = new InlineLexer(src.links, this.options, this.renderer);
17607 this.tokens = src.reverse();
17610 while (this.next()) {
17621 Parser.prototype.next = function() {
17622 return this.token = this.tokens.pop();
17626 * Preview Next Token
17629 Parser.prototype.peek = function() {
17630 return this.tokens[this.tokens.length - 1] || 0;
17634 * Parse Text Tokens
17637 Parser.prototype.parseText = function() {
17638 var body = this.token.text;
17640 while (this.peek().type === 'text') {
17641 body += '\n' + this.next().text;
17644 return this.inline.output(body);
17648 * Parse Current Token
17651 Parser.prototype.tok = function() {
17652 switch (this.token.type) {
17657 return this.renderer.hr();
17660 return this.renderer.heading(
17661 this.inline.output(this.token.text),
17666 return this.renderer.code(this.token.text,
17668 this.token.escaped);
17681 for (i = 0; i < this.token.header.length; i++) {
17682 flags = { header: true, align: this.token.align[i] };
17683 cell += this.renderer.tablecell(
17684 this.inline.output(this.token.header[i]),
17685 { header: true, align: this.token.align[i] }
17688 header += this.renderer.tablerow(cell);
17690 for (i = 0; i < this.token.cells.length; i++) {
17691 row = this.token.cells[i];
17694 for (j = 0; j < row.length; j++) {
17695 cell += this.renderer.tablecell(
17696 this.inline.output(row[j]),
17697 { header: false, align: this.token.align[j] }
17701 body += this.renderer.tablerow(cell);
17703 return this.renderer.table(header, body);
17705 case 'blockquote_start': {
17708 while (this.next().type !== 'blockquote_end') {
17709 body += this.tok();
17712 return this.renderer.blockquote(body);
17714 case 'list_start': {
17716 , ordered = this.token.ordered;
17718 while (this.next().type !== 'list_end') {
17719 body += this.tok();
17722 return this.renderer.list(body, ordered);
17724 case 'list_item_start': {
17727 while (this.next().type !== 'list_item_end') {
17728 body += this.token.type === 'text'
17733 return this.renderer.listitem(body);
17735 case 'loose_item_start': {
17738 while (this.next().type !== 'list_item_end') {
17739 body += this.tok();
17742 return this.renderer.listitem(body);
17745 var html = !this.token.pre && !this.options.pedantic
17746 ? this.inline.output(this.token.text)
17748 return this.renderer.html(html);
17750 case 'paragraph': {
17751 return this.renderer.paragraph(this.inline.output(this.token.text));
17754 return this.renderer.paragraph(this.parseText());
17763 function escape(html, encode) {
17765 .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
17766 .replace(/</g, '<')
17767 .replace(/>/g, '>')
17768 .replace(/"/g, '"')
17769 .replace(/'/g, ''');
17772 function unescape(html) {
17773 // explicitly match decimal, hex, and named HTML entities
17774 return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
17775 n = n.toLowerCase();
17776 if (n === 'colon') { return ':'; }
17777 if (n.charAt(0) === '#') {
17778 return n.charAt(1) === 'x'
17779 ? String.fromCharCode(parseInt(n.substring(2), 16))
17780 : String.fromCharCode(+n.substring(1));
17786 function replace(regex, opt) {
17787 regex = regex.source;
17789 return function self(name, val) {
17790 if (!name) { return new RegExp(regex, opt); }
17791 val = val.source || val;
17792 val = val.replace(/(^|[^\[])\^/g, '$1');
17793 regex = regex.replace(name, val);
17801 function merge(obj) {
17806 for (; i < arguments.length; i++) {
17807 target = arguments[i];
17808 for (key in target) {
17809 if (Object.prototype.hasOwnProperty.call(target, key)) {
17810 obj[key] = target[key];
17823 function marked(src, opt, callback) {
17824 if (callback || typeof opt === 'function') {
17830 opt = merge({}, marked.defaults, opt || {});
17832 var highlight = opt.highlight
17838 tokens = Lexer.lex(src, opt)
17840 return callback(e);
17843 pending = tokens.length;
17845 var done = function(err) {
17847 opt.highlight = highlight;
17848 return callback(err);
17854 out = Parser.parse(tokens, opt);
17859 opt.highlight = highlight;
17863 : callback(null, out);
17866 if (!highlight || highlight.length < 3) {
17870 delete opt.highlight;
17872 if (!pending) { return done(); }
17874 for (; i < tokens.length; i++) {
17876 if (token.type !== 'code') {
17877 return --pending || done();
17879 return highlight(token.text, token.lang, function(err, code) {
17880 if (err) { return done(err); }
17881 if (code == null || code === token.text) {
17882 return --pending || done();
17885 token.escaped = true;
17886 --pending || done();
17894 if (opt) { opt = merge({}, marked.defaults, opt); }
17895 return Parser.parse(Lexer.lex(src, opt), opt);
17897 e.message += '\nPlease report this to https://github.com/chjj/marked.';
17898 if ((opt || marked.defaults).silent) {
17899 return '<p>An error occured:</p><pre>'
17900 + escape(e.message + '', true)
17912 marked.setOptions = function(opt) {
17913 merge(marked.defaults, opt);
17917 marked.defaults = {
17928 langPrefix: 'lang-',
17929 smartypants: false,
17931 renderer: new Renderer,
17939 marked.Parser = Parser;
17940 marked.parser = Parser.parse;
17942 marked.Renderer = Renderer;
17944 marked.Lexer = Lexer;
17945 marked.lexer = Lexer.lex;
17947 marked.InlineLexer = InlineLexer;
17948 marked.inlineLexer = InlineLexer.output;
17950 marked.parse = marked;
17952 Roo.Markdown.marked = marked;
17956 * Ext JS Library 1.1.1
17957 * Copyright(c) 2006-2007, Ext JS, LLC.
17959 * Originally Released Under LGPL - original licence link has changed is not relivant.
17962 * <script type="text/javascript">
17968 * These classes are derivatives of the similarly named classes in the YUI Library.
17969 * The original license:
17970 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
17971 * Code licensed under the BSD License:
17972 * http://developer.yahoo.net/yui/license.txt
17977 var Event=Roo.EventManager;
17978 var Dom=Roo.lib.Dom;
17981 * @class Roo.dd.DragDrop
17982 * @extends Roo.util.Observable
17983 * Defines the interface and base operation of items that that can be
17984 * dragged or can be drop targets. It was designed to be extended, overriding
17985 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
17986 * Up to three html elements can be associated with a DragDrop instance:
17988 * <li>linked element: the element that is passed into the constructor.
17989 * This is the element which defines the boundaries for interaction with
17990 * other DragDrop objects.</li>
17991 * <li>handle element(s): The drag operation only occurs if the element that
17992 * was clicked matches a handle element. By default this is the linked
17993 * element, but there are times that you will want only a portion of the
17994 * linked element to initiate the drag operation, and the setHandleElId()
17995 * method provides a way to define this.</li>
17996 * <li>drag element: this represents the element that would be moved along
17997 * with the cursor during a drag operation. By default, this is the linked
17998 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
17999 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
18002 * This class should not be instantiated until the onload event to ensure that
18003 * the associated elements are available.
18004 * The following would define a DragDrop obj that would interact with any
18005 * other DragDrop obj in the "group1" group:
18007 * dd = new Roo.dd.DragDrop("div1", "group1");
18009 * Since none of the event handlers have been implemented, nothing would
18010 * actually happen if you were to run the code above. Normally you would
18011 * override this class or one of the default implementations, but you can
18012 * also override the methods you want on an instance of the class...
18014 * dd.onDragDrop = function(e, id) {
18015 * alert("dd was dropped on " + id);
18019 * @param {String} id of the element that is linked to this instance
18020 * @param {String} sGroup the group of related DragDrop objects
18021 * @param {object} config an object containing configurable attributes
18022 * Valid properties for DragDrop:
18023 * padding, isTarget, maintainOffset, primaryButtonOnly
18025 Roo.dd.DragDrop = function(id, sGroup, config) {
18027 this.init(id, sGroup, config);
18032 Roo.extend(Roo.dd.DragDrop, Roo.util.Observable , {
18035 * The id of the element associated with this object. This is what we
18036 * refer to as the "linked element" because the size and position of
18037 * this element is used to determine when the drag and drop objects have
18045 * Configuration attributes passed into the constructor
18052 * The id of the element that will be dragged. By default this is same
18053 * as the linked element , but could be changed to another element. Ex:
18055 * @property dragElId
18062 * the id of the element that initiates the drag operation. By default
18063 * this is the linked element, but could be changed to be a child of this
18064 * element. This lets us do things like only starting the drag when the
18065 * header element within the linked html element is clicked.
18066 * @property handleElId
18073 * An associative array of HTML tags that will be ignored if clicked.
18074 * @property invalidHandleTypes
18075 * @type {string: string}
18077 invalidHandleTypes: null,
18080 * An associative array of ids for elements that will be ignored if clicked
18081 * @property invalidHandleIds
18082 * @type {string: string}
18084 invalidHandleIds: null,
18087 * An indexted array of css class names for elements that will be ignored
18089 * @property invalidHandleClasses
18092 invalidHandleClasses: null,
18095 * The linked element's absolute X position at the time the drag was
18097 * @property startPageX
18104 * The linked element's absolute X position at the time the drag was
18106 * @property startPageY
18113 * The group defines a logical collection of DragDrop objects that are
18114 * related. Instances only get events when interacting with other
18115 * DragDrop object in the same group. This lets us define multiple
18116 * groups using a single DragDrop subclass if we want.
18118 * @type {string: string}
18123 * Individual drag/drop instances can be locked. This will prevent
18124 * onmousedown start drag.
18132 * Lock this instance
18135 lock: function() { this.locked = true; },
18138 * Unlock this instace
18141 unlock: function() { this.locked = false; },
18144 * By default, all insances can be a drop target. This can be disabled by
18145 * setting isTarget to false.
18152 * The padding configured for this drag and drop object for calculating
18153 * the drop zone intersection with this object.
18160 * Cached reference to the linked element
18161 * @property _domRef
18167 * Internal typeof flag
18168 * @property __ygDragDrop
18171 __ygDragDrop: true,
18174 * Set to true when horizontal contraints are applied
18175 * @property constrainX
18182 * Set to true when vertical contraints are applied
18183 * @property constrainY
18190 * The left constraint
18198 * The right constraint
18206 * The up constraint
18215 * The down constraint
18223 * Maintain offsets when we resetconstraints. Set to true when you want
18224 * the position of the element relative to its parent to stay the same
18225 * when the page changes
18227 * @property maintainOffset
18230 maintainOffset: false,
18233 * Array of pixel locations the element will snap to if we specified a
18234 * horizontal graduation/interval. This array is generated automatically
18235 * when you define a tick interval.
18242 * Array of pixel locations the element will snap to if we specified a
18243 * vertical graduation/interval. This array is generated automatically
18244 * when you define a tick interval.
18251 * By default the drag and drop instance will only respond to the primary
18252 * button click (left button for a right-handed mouse). Set to true to
18253 * allow drag and drop to start with any mouse click that is propogated
18255 * @property primaryButtonOnly
18258 primaryButtonOnly: true,
18261 * The availabe property is false until the linked dom element is accessible.
18262 * @property available
18268 * By default, drags can only be initiated if the mousedown occurs in the
18269 * region the linked element is. This is done in part to work around a
18270 * bug in some browsers that mis-report the mousedown if the previous
18271 * mouseup happened outside of the window. This property is set to true
18272 * if outer handles are defined.
18274 * @property hasOuterHandles
18278 hasOuterHandles: false,
18281 * Code that executes immediately before the startDrag event
18282 * @method b4StartDrag
18285 b4StartDrag: function(x, y) { },
18288 * Abstract method called after a drag/drop object is clicked
18289 * and the drag or mousedown time thresholds have beeen met.
18290 * @method startDrag
18291 * @param {int} X click location
18292 * @param {int} Y click location
18294 startDrag: function(x, y) { /* override this */ },
18297 * Code that executes immediately before the onDrag event
18301 b4Drag: function(e) { },
18304 * Abstract method called during the onMouseMove event while dragging an
18307 * @param {Event} e the mousemove event
18309 onDrag: function(e) { /* override this */ },
18312 * Abstract method called when this element fist begins hovering over
18313 * another DragDrop obj
18314 * @method onDragEnter
18315 * @param {Event} e the mousemove event
18316 * @param {String|DragDrop[]} id In POINT mode, the element
18317 * id this is hovering over. In INTERSECT mode, an array of one or more
18318 * dragdrop items being hovered over.
18320 onDragEnter: function(e, id) { /* override this */ },
18323 * Code that executes immediately before the onDragOver event
18324 * @method b4DragOver
18327 b4DragOver: function(e) { },
18330 * Abstract method called when this element is hovering over another
18332 * @method onDragOver
18333 * @param {Event} e the mousemove event
18334 * @param {String|DragDrop[]} id In POINT mode, the element
18335 * id this is hovering over. In INTERSECT mode, an array of dd items
18336 * being hovered over.
18338 onDragOver: function(e, id) { /* override this */ },
18341 * Code that executes immediately before the onDragOut event
18342 * @method b4DragOut
18345 b4DragOut: function(e) { },
18348 * Abstract method called when we are no longer hovering over an element
18349 * @method onDragOut
18350 * @param {Event} e the mousemove event
18351 * @param {String|DragDrop[]} id In POINT mode, the element
18352 * id this was hovering over. In INTERSECT mode, an array of dd items
18353 * that the mouse is no longer over.
18355 onDragOut: function(e, id) { /* override this */ },
18358 * Code that executes immediately before the onDragDrop event
18359 * @method b4DragDrop
18362 b4DragDrop: function(e) { },
18365 * Abstract method called when this item is dropped on another DragDrop
18367 * @method onDragDrop
18368 * @param {Event} e the mouseup event
18369 * @param {String|DragDrop[]} id In POINT mode, the element
18370 * id this was dropped on. In INTERSECT mode, an array of dd items this
18373 onDragDrop: function(e, id) { /* override this */ },
18376 * Abstract method called when this item is dropped on an area with no
18378 * @method onInvalidDrop
18379 * @param {Event} e the mouseup event
18381 onInvalidDrop: function(e) { /* override this */ },
18384 * Code that executes immediately before the endDrag event
18385 * @method b4EndDrag
18388 b4EndDrag: function(e) { },
18391 * Fired when we are done dragging the object
18393 * @param {Event} e the mouseup event
18395 endDrag: function(e) { /* override this */ },
18398 * Code executed immediately before the onMouseDown event
18399 * @method b4MouseDown
18400 * @param {Event} e the mousedown event
18403 b4MouseDown: function(e) { },
18406 * Event handler that fires when a drag/drop obj gets a mousedown
18407 * @method onMouseDown
18408 * @param {Event} e the mousedown event
18410 onMouseDown: function(e) { /* override this */ },
18413 * Event handler that fires when a drag/drop obj gets a mouseup
18414 * @method onMouseUp
18415 * @param {Event} e the mouseup event
18417 onMouseUp: function(e) { /* override this */ },
18420 * Override the onAvailable method to do what is needed after the initial
18421 * position was determined.
18422 * @method onAvailable
18424 onAvailable: function () {
18428 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
18431 defaultPadding : {left:0, right:0, top:0, bottom:0},
18434 * Initializes the drag drop object's constraints to restrict movement to a certain element.
18438 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
18439 { dragElId: "existingProxyDiv" });
18440 dd.startDrag = function(){
18441 this.constrainTo("parent-id");
18444 * Or you can initalize it using the {@link Roo.Element} object:
18446 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
18447 startDrag : function(){
18448 this.constrainTo("parent-id");
18452 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
18453 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
18454 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
18455 * an object containing the sides to pad. For example: {right:10, bottom:10}
18456 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
18458 constrainTo : function(constrainTo, pad, inContent){
18459 if(typeof pad == "number"){
18460 pad = {left: pad, right:pad, top:pad, bottom:pad};
18462 pad = pad || this.defaultPadding;
18463 var b = Roo.get(this.getEl()).getBox();
18464 var ce = Roo.get(constrainTo);
18465 var s = ce.getScroll();
18466 var c, cd = ce.dom;
18467 if(cd == document.body){
18468 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
18471 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
18475 var topSpace = b.y - c.y;
18476 var leftSpace = b.x - c.x;
18478 this.resetConstraints();
18479 this.setXConstraint(leftSpace - (pad.left||0), // left
18480 c.width - leftSpace - b.width - (pad.right||0) //right
18482 this.setYConstraint(topSpace - (pad.top||0), //top
18483 c.height - topSpace - b.height - (pad.bottom||0) //bottom
18488 * Returns a reference to the linked element
18490 * @return {HTMLElement} the html element
18492 getEl: function() {
18493 if (!this._domRef) {
18494 this._domRef = Roo.getDom(this.id);
18497 return this._domRef;
18501 * Returns a reference to the actual element to drag. By default this is
18502 * the same as the html element, but it can be assigned to another
18503 * element. An example of this can be found in Roo.dd.DDProxy
18504 * @method getDragEl
18505 * @return {HTMLElement} the html element
18507 getDragEl: function() {
18508 return Roo.getDom(this.dragElId);
18512 * Sets up the DragDrop object. Must be called in the constructor of any
18513 * Roo.dd.DragDrop subclass
18515 * @param id the id of the linked element
18516 * @param {String} sGroup the group of related items
18517 * @param {object} config configuration attributes
18519 init: function(id, sGroup, config) {
18520 this.initTarget(id, sGroup, config);
18521 if (!Roo.isTouch) {
18522 Event.on(this.id, "mousedown", this.handleMouseDown, this);
18524 Event.on(this.id, "touchstart", this.handleMouseDown, this);
18525 // Event.on(this.id, "selectstart", Event.preventDefault);
18529 * Initializes Targeting functionality only... the object does not
18530 * get a mousedown handler.
18531 * @method initTarget
18532 * @param id the id of the linked element
18533 * @param {String} sGroup the group of related items
18534 * @param {object} config configuration attributes
18536 initTarget: function(id, sGroup, config) {
18538 // configuration attributes
18539 this.config = config || {};
18541 // create a local reference to the drag and drop manager
18542 this.DDM = Roo.dd.DDM;
18543 // initialize the groups array
18546 // assume that we have an element reference instead of an id if the
18547 // parameter is not a string
18548 if (typeof id !== "string") {
18555 // add to an interaction group
18556 this.addToGroup((sGroup) ? sGroup : "default");
18558 // We don't want to register this as the handle with the manager
18559 // so we just set the id rather than calling the setter.
18560 this.handleElId = id;
18562 // the linked element is the element that gets dragged by default
18563 this.setDragElId(id);
18565 // by default, clicked anchors will not start drag operations.
18566 this.invalidHandleTypes = { A: "A" };
18567 this.invalidHandleIds = {};
18568 this.invalidHandleClasses = [];
18570 this.applyConfig();
18572 this.handleOnAvailable();
18576 * Applies the configuration parameters that were passed into the constructor.
18577 * This is supposed to happen at each level through the inheritance chain. So
18578 * a DDProxy implentation will execute apply config on DDProxy, DD, and
18579 * DragDrop in order to get all of the parameters that are available in
18581 * @method applyConfig
18583 applyConfig: function() {
18585 // configurable properties:
18586 // padding, isTarget, maintainOffset, primaryButtonOnly
18587 this.padding = this.config.padding || [0, 0, 0, 0];
18588 this.isTarget = (this.config.isTarget !== false);
18589 this.maintainOffset = (this.config.maintainOffset);
18590 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
18595 * Executed when the linked element is available
18596 * @method handleOnAvailable
18599 handleOnAvailable: function() {
18600 this.available = true;
18601 this.resetConstraints();
18602 this.onAvailable();
18606 * Configures the padding for the target zone in px. Effectively expands
18607 * (or reduces) the virtual object size for targeting calculations.
18608 * Supports css-style shorthand; if only one parameter is passed, all sides
18609 * will have that padding, and if only two are passed, the top and bottom
18610 * will have the first param, the left and right the second.
18611 * @method setPadding
18612 * @param {int} iTop Top pad
18613 * @param {int} iRight Right pad
18614 * @param {int} iBot Bot pad
18615 * @param {int} iLeft Left pad
18617 setPadding: function(iTop, iRight, iBot, iLeft) {
18618 // this.padding = [iLeft, iRight, iTop, iBot];
18619 if (!iRight && 0 !== iRight) {
18620 this.padding = [iTop, iTop, iTop, iTop];
18621 } else if (!iBot && 0 !== iBot) {
18622 this.padding = [iTop, iRight, iTop, iRight];
18624 this.padding = [iTop, iRight, iBot, iLeft];
18629 * Stores the initial placement of the linked element.
18630 * @method setInitialPosition
18631 * @param {int} diffX the X offset, default 0
18632 * @param {int} diffY the Y offset, default 0
18634 setInitPosition: function(diffX, diffY) {
18635 var el = this.getEl();
18637 if (!this.DDM.verifyEl(el)) {
18641 var dx = diffX || 0;
18642 var dy = diffY || 0;
18644 var p = Dom.getXY( el );
18646 this.initPageX = p[0] - dx;
18647 this.initPageY = p[1] - dy;
18649 this.lastPageX = p[0];
18650 this.lastPageY = p[1];
18653 this.setStartPosition(p);
18657 * Sets the start position of the element. This is set when the obj
18658 * is initialized, the reset when a drag is started.
18659 * @method setStartPosition
18660 * @param pos current position (from previous lookup)
18663 setStartPosition: function(pos) {
18664 var p = pos || Dom.getXY( this.getEl() );
18665 this.deltaSetXY = null;
18667 this.startPageX = p[0];
18668 this.startPageY = p[1];
18672 * Add this instance to a group of related drag/drop objects. All
18673 * instances belong to at least one group, and can belong to as many
18674 * groups as needed.
18675 * @method addToGroup
18676 * @param sGroup {string} the name of the group
18678 addToGroup: function(sGroup) {
18679 this.groups[sGroup] = true;
18680 this.DDM.regDragDrop(this, sGroup);
18684 * Remove's this instance from the supplied interaction group
18685 * @method removeFromGroup
18686 * @param {string} sGroup The group to drop
18688 removeFromGroup: function(sGroup) {
18689 if (this.groups[sGroup]) {
18690 delete this.groups[sGroup];
18693 this.DDM.removeDDFromGroup(this, sGroup);
18697 * Allows you to specify that an element other than the linked element
18698 * will be moved with the cursor during a drag
18699 * @method setDragElId
18700 * @param id {string} the id of the element that will be used to initiate the drag
18702 setDragElId: function(id) {
18703 this.dragElId = id;
18707 * Allows you to specify a child of the linked element that should be
18708 * used to initiate the drag operation. An example of this would be if
18709 * you have a content div with text and links. Clicking anywhere in the
18710 * content area would normally start the drag operation. Use this method
18711 * to specify that an element inside of the content div is the element
18712 * that starts the drag operation.
18713 * @method setHandleElId
18714 * @param id {string} the id of the element that will be used to
18715 * initiate the drag.
18717 setHandleElId: function(id) {
18718 if (typeof id !== "string") {
18721 this.handleElId = id;
18722 this.DDM.regHandle(this.id, id);
18726 * Allows you to set an element outside of the linked element as a drag
18728 * @method setOuterHandleElId
18729 * @param id the id of the element that will be used to initiate the drag
18731 setOuterHandleElId: function(id) {
18732 if (typeof id !== "string") {
18735 Event.on(id, "mousedown",
18736 this.handleMouseDown, this);
18737 this.setHandleElId(id);
18739 this.hasOuterHandles = true;
18743 * Remove all drag and drop hooks for this element
18746 unreg: function() {
18747 Event.un(this.id, "mousedown",
18748 this.handleMouseDown);
18749 Event.un(this.id, "touchstart",
18750 this.handleMouseDown);
18751 this._domRef = null;
18752 this.DDM._remove(this);
18755 destroy : function(){
18760 * Returns true if this instance is locked, or the drag drop mgr is locked
18761 * (meaning that all drag/drop is disabled on the page.)
18763 * @return {boolean} true if this obj or all drag/drop is locked, else
18766 isLocked: function() {
18767 return (this.DDM.isLocked() || this.locked);
18771 * Fired when this object is clicked
18772 * @method handleMouseDown
18774 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
18777 handleMouseDown: function(e, oDD){
18779 if (!Roo.isTouch && this.primaryButtonOnly && e.button != 0) {
18780 //Roo.log('not touch/ button !=0');
18783 if (e.browserEvent.touches && e.browserEvent.touches.length != 1) {
18784 return; // double touch..
18788 if (this.isLocked()) {
18789 //Roo.log('locked');
18793 this.DDM.refreshCache(this.groups);
18794 // Roo.log([Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e)]);
18795 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
18796 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
18797 //Roo.log('no outer handes or not over target');
18800 // Roo.log('check validator');
18801 if (this.clickValidator(e)) {
18802 // Roo.log('validate success');
18803 // set the initial element position
18804 this.setStartPosition();
18807 this.b4MouseDown(e);
18808 this.onMouseDown(e);
18810 this.DDM.handleMouseDown(e, this);
18812 this.DDM.stopEvent(e);
18820 clickValidator: function(e) {
18821 var target = e.getTarget();
18822 return ( this.isValidHandleChild(target) &&
18823 (this.id == this.handleElId ||
18824 this.DDM.handleWasClicked(target, this.id)) );
18828 * Allows you to specify a tag name that should not start a drag operation
18829 * when clicked. This is designed to facilitate embedding links within a
18830 * drag handle that do something other than start the drag.
18831 * @method addInvalidHandleType
18832 * @param {string} tagName the type of element to exclude
18834 addInvalidHandleType: function(tagName) {
18835 var type = tagName.toUpperCase();
18836 this.invalidHandleTypes[type] = type;
18840 * Lets you to specify an element id for a child of a drag handle
18841 * that should not initiate a drag
18842 * @method addInvalidHandleId
18843 * @param {string} id the element id of the element you wish to ignore
18845 addInvalidHandleId: function(id) {
18846 if (typeof id !== "string") {
18849 this.invalidHandleIds[id] = id;
18853 * Lets you specify a css class of elements that will not initiate a drag
18854 * @method addInvalidHandleClass
18855 * @param {string} cssClass the class of the elements you wish to ignore
18857 addInvalidHandleClass: function(cssClass) {
18858 this.invalidHandleClasses.push(cssClass);
18862 * Unsets an excluded tag name set by addInvalidHandleType
18863 * @method removeInvalidHandleType
18864 * @param {string} tagName the type of element to unexclude
18866 removeInvalidHandleType: function(tagName) {
18867 var type = tagName.toUpperCase();
18868 // this.invalidHandleTypes[type] = null;
18869 delete this.invalidHandleTypes[type];
18873 * Unsets an invalid handle id
18874 * @method removeInvalidHandleId
18875 * @param {string} id the id of the element to re-enable
18877 removeInvalidHandleId: function(id) {
18878 if (typeof id !== "string") {
18881 delete this.invalidHandleIds[id];
18885 * Unsets an invalid css class
18886 * @method removeInvalidHandleClass
18887 * @param {string} cssClass the class of the element(s) you wish to
18890 removeInvalidHandleClass: function(cssClass) {
18891 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
18892 if (this.invalidHandleClasses[i] == cssClass) {
18893 delete this.invalidHandleClasses[i];
18899 * Checks the tag exclusion list to see if this click should be ignored
18900 * @method isValidHandleChild
18901 * @param {HTMLElement} node the HTMLElement to evaluate
18902 * @return {boolean} true if this is a valid tag type, false if not
18904 isValidHandleChild: function(node) {
18907 // var n = (node.nodeName == "#text") ? node.parentNode : node;
18910 nodeName = node.nodeName.toUpperCase();
18912 nodeName = node.nodeName;
18914 valid = valid && !this.invalidHandleTypes[nodeName];
18915 valid = valid && !this.invalidHandleIds[node.id];
18917 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
18918 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
18927 * Create the array of horizontal tick marks if an interval was specified
18928 * in setXConstraint().
18929 * @method setXTicks
18932 setXTicks: function(iStartX, iTickSize) {
18934 this.xTickSize = iTickSize;
18938 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
18940 this.xTicks[this.xTicks.length] = i;
18945 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
18947 this.xTicks[this.xTicks.length] = i;
18952 this.xTicks.sort(this.DDM.numericSort) ;
18956 * Create the array of vertical tick marks if an interval was specified in
18957 * setYConstraint().
18958 * @method setYTicks
18961 setYTicks: function(iStartY, iTickSize) {
18963 this.yTickSize = iTickSize;
18967 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
18969 this.yTicks[this.yTicks.length] = i;
18974 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
18976 this.yTicks[this.yTicks.length] = i;
18981 this.yTicks.sort(this.DDM.numericSort) ;
18985 * By default, the element can be dragged any place on the screen. Use
18986 * this method to limit the horizontal travel of the element. Pass in
18987 * 0,0 for the parameters if you want to lock the drag to the y axis.
18988 * @method setXConstraint
18989 * @param {int} iLeft the number of pixels the element can move to the left
18990 * @param {int} iRight the number of pixels the element can move to the
18992 * @param {int} iTickSize optional parameter for specifying that the
18994 * should move iTickSize pixels at a time.
18996 setXConstraint: function(iLeft, iRight, iTickSize) {
18997 this.leftConstraint = iLeft;
18998 this.rightConstraint = iRight;
19000 this.minX = this.initPageX - iLeft;
19001 this.maxX = this.initPageX + iRight;
19002 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
19004 this.constrainX = true;
19008 * Clears any constraints applied to this instance. Also clears ticks
19009 * since they can't exist independent of a constraint at this time.
19010 * @method clearConstraints
19012 clearConstraints: function() {
19013 this.constrainX = false;
19014 this.constrainY = false;
19019 * Clears any tick interval defined for this instance
19020 * @method clearTicks
19022 clearTicks: function() {
19023 this.xTicks = null;
19024 this.yTicks = null;
19025 this.xTickSize = 0;
19026 this.yTickSize = 0;
19030 * By default, the element can be dragged any place on the screen. Set
19031 * this to limit the vertical travel of the element. Pass in 0,0 for the
19032 * parameters if you want to lock the drag to the x axis.
19033 * @method setYConstraint
19034 * @param {int} iUp the number of pixels the element can move up
19035 * @param {int} iDown the number of pixels the element can move down
19036 * @param {int} iTickSize optional parameter for specifying that the
19037 * element should move iTickSize pixels at a time.
19039 setYConstraint: function(iUp, iDown, iTickSize) {
19040 this.topConstraint = iUp;
19041 this.bottomConstraint = iDown;
19043 this.minY = this.initPageY - iUp;
19044 this.maxY = this.initPageY + iDown;
19045 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
19047 this.constrainY = true;
19052 * resetConstraints must be called if you manually reposition a dd element.
19053 * @method resetConstraints
19054 * @param {boolean} maintainOffset
19056 resetConstraints: function() {
19059 // Maintain offsets if necessary
19060 if (this.initPageX || this.initPageX === 0) {
19061 // figure out how much this thing has moved
19062 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
19063 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
19065 this.setInitPosition(dx, dy);
19067 // This is the first time we have detected the element's position
19069 this.setInitPosition();
19072 if (this.constrainX) {
19073 this.setXConstraint( this.leftConstraint,
19074 this.rightConstraint,
19078 if (this.constrainY) {
19079 this.setYConstraint( this.topConstraint,
19080 this.bottomConstraint,
19086 * Normally the drag element is moved pixel by pixel, but we can specify
19087 * that it move a number of pixels at a time. This method resolves the
19088 * location when we have it set up like this.
19090 * @param {int} val where we want to place the object
19091 * @param {int[]} tickArray sorted array of valid points
19092 * @return {int} the closest tick
19095 getTick: function(val, tickArray) {
19098 // If tick interval is not defined, it is effectively 1 pixel,
19099 // so we return the value passed to us.
19101 } else if (tickArray[0] >= val) {
19102 // The value is lower than the first tick, so we return the first
19104 return tickArray[0];
19106 for (var i=0, len=tickArray.length; i<len; ++i) {
19108 if (tickArray[next] && tickArray[next] >= val) {
19109 var diff1 = val - tickArray[i];
19110 var diff2 = tickArray[next] - val;
19111 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
19115 // The value is larger than the last tick, so we return the last
19117 return tickArray[tickArray.length - 1];
19124 * @return {string} string representation of the dd obj
19126 toString: function() {
19127 return ("DragDrop " + this.id);
19135 * Ext JS Library 1.1.1
19136 * Copyright(c) 2006-2007, Ext JS, LLC.
19138 * Originally Released Under LGPL - original licence link has changed is not relivant.
19141 * <script type="text/javascript">
19146 * The drag and drop utility provides a framework for building drag and drop
19147 * applications. In addition to enabling drag and drop for specific elements,
19148 * the drag and drop elements are tracked by the manager class, and the
19149 * interactions between the various elements are tracked during the drag and
19150 * the implementing code is notified about these important moments.
19153 // Only load the library once. Rewriting the manager class would orphan
19154 // existing drag and drop instances.
19155 if (!Roo.dd.DragDropMgr) {
19158 * @class Roo.dd.DragDropMgr
19159 * DragDropMgr is a singleton that tracks the element interaction for
19160 * all DragDrop items in the window. Generally, you will not call
19161 * this class directly, but it does have helper methods that could
19162 * be useful in your DragDrop implementations.
19165 Roo.dd.DragDropMgr = function() {
19167 var Event = Roo.EventManager;
19172 * Two dimensional Array of registered DragDrop objects. The first
19173 * dimension is the DragDrop item group, the second the DragDrop
19176 * @type {string: string}
19183 * Array of element ids defined as drag handles. Used to determine
19184 * if the element that generated the mousedown event is actually the
19185 * handle and not the html element itself.
19186 * @property handleIds
19187 * @type {string: string}
19194 * the DragDrop object that is currently being dragged
19195 * @property dragCurrent
19203 * the DragDrop object(s) that are being hovered over
19204 * @property dragOvers
19212 * the X distance between the cursor and the object being dragged
19221 * the Y distance between the cursor and the object being dragged
19230 * Flag to determine if we should prevent the default behavior of the
19231 * events we define. By default this is true, but this can be set to
19232 * false if you need the default behavior (not recommended)
19233 * @property preventDefault
19237 preventDefault: true,
19240 * Flag to determine if we should stop the propagation of the events
19241 * we generate. This is true by default but you may want to set it to
19242 * false if the html element contains other features that require the
19244 * @property stopPropagation
19248 stopPropagation: true,
19251 * Internal flag that is set to true when drag and drop has been
19253 * @property initialized
19260 * All drag and drop can be disabled.
19268 * Called the first time an element is registered.
19274 this.initialized = true;
19278 * In point mode, drag and drop interaction is defined by the
19279 * location of the cursor during the drag/drop
19287 * In intersect mode, drag and drop interactio nis defined by the
19288 * overlap of two or more drag and drop objects.
19289 * @property INTERSECT
19296 * The current drag and drop mode. Default: POINT
19304 * Runs method on all drag and drop objects
19305 * @method _execOnAll
19309 _execOnAll: function(sMethod, args) {
19310 for (var i in this.ids) {
19311 for (var j in this.ids[i]) {
19312 var oDD = this.ids[i][j];
19313 if (! this.isTypeOfDD(oDD)) {
19316 oDD[sMethod].apply(oDD, args);
19322 * Drag and drop initialization. Sets up the global event handlers
19327 _onLoad: function() {
19331 if (!Roo.isTouch) {
19332 Event.on(document, "mouseup", this.handleMouseUp, this, true);
19333 Event.on(document, "mousemove", this.handleMouseMove, this, true);
19335 Event.on(document, "touchend", this.handleMouseUp, this, true);
19336 Event.on(document, "touchmove", this.handleMouseMove, this, true);
19338 Event.on(window, "unload", this._onUnload, this, true);
19339 Event.on(window, "resize", this._onResize, this, true);
19340 // Event.on(window, "mouseout", this._test);
19345 * Reset constraints on all drag and drop objs
19346 * @method _onResize
19350 _onResize: function(e) {
19351 this._execOnAll("resetConstraints", []);
19355 * Lock all drag and drop functionality
19359 lock: function() { this.locked = true; },
19362 * Unlock all drag and drop functionality
19366 unlock: function() { this.locked = false; },
19369 * Is drag and drop locked?
19371 * @return {boolean} True if drag and drop is locked, false otherwise.
19374 isLocked: function() { return this.locked; },
19377 * Location cache that is set for all drag drop objects when a drag is
19378 * initiated, cleared when the drag is finished.
19379 * @property locationCache
19386 * Set useCache to false if you want to force object the lookup of each
19387 * drag and drop linked element constantly during a drag.
19388 * @property useCache
19395 * The number of pixels that the mouse needs to move after the
19396 * mousedown before the drag is initiated. Default=3;
19397 * @property clickPixelThresh
19401 clickPixelThresh: 3,
19404 * The number of milliseconds after the mousedown event to initiate the
19405 * drag if we don't get a mouseup event. Default=1000
19406 * @property clickTimeThresh
19410 clickTimeThresh: 350,
19413 * Flag that indicates that either the drag pixel threshold or the
19414 * mousdown time threshold has been met
19415 * @property dragThreshMet
19420 dragThreshMet: false,
19423 * Timeout used for the click time threshold
19424 * @property clickTimeout
19429 clickTimeout: null,
19432 * The X position of the mousedown event stored for later use when a
19433 * drag threshold is met.
19442 * The Y position of the mousedown event stored for later use when a
19443 * drag threshold is met.
19452 * Each DragDrop instance must be registered with the DragDropMgr.
19453 * This is executed in DragDrop.init()
19454 * @method regDragDrop
19455 * @param {DragDrop} oDD the DragDrop object to register
19456 * @param {String} sGroup the name of the group this element belongs to
19459 regDragDrop: function(oDD, sGroup) {
19460 if (!this.initialized) { this.init(); }
19462 if (!this.ids[sGroup]) {
19463 this.ids[sGroup] = {};
19465 this.ids[sGroup][oDD.id] = oDD;
19469 * Removes the supplied dd instance from the supplied group. Executed
19470 * by DragDrop.removeFromGroup, so don't call this function directly.
19471 * @method removeDDFromGroup
19475 removeDDFromGroup: function(oDD, sGroup) {
19476 if (!this.ids[sGroup]) {
19477 this.ids[sGroup] = {};
19480 var obj = this.ids[sGroup];
19481 if (obj && obj[oDD.id]) {
19482 delete obj[oDD.id];
19487 * Unregisters a drag and drop item. This is executed in
19488 * DragDrop.unreg, use that method instead of calling this directly.
19493 _remove: function(oDD) {
19494 for (var g in oDD.groups) {
19495 if (g && this.ids[g][oDD.id]) {
19496 delete this.ids[g][oDD.id];
19499 delete this.handleIds[oDD.id];
19503 * Each DragDrop handle element must be registered. This is done
19504 * automatically when executing DragDrop.setHandleElId()
19505 * @method regHandle
19506 * @param {String} sDDId the DragDrop id this element is a handle for
19507 * @param {String} sHandleId the id of the element that is the drag
19511 regHandle: function(sDDId, sHandleId) {
19512 if (!this.handleIds[sDDId]) {
19513 this.handleIds[sDDId] = {};
19515 this.handleIds[sDDId][sHandleId] = sHandleId;
19519 * Utility function to determine if a given element has been
19520 * registered as a drag drop item.
19521 * @method isDragDrop
19522 * @param {String} id the element id to check
19523 * @return {boolean} true if this element is a DragDrop item,
19527 isDragDrop: function(id) {
19528 return ( this.getDDById(id) ) ? true : false;
19532 * Returns the drag and drop instances that are in all groups the
19533 * passed in instance belongs to.
19534 * @method getRelated
19535 * @param {DragDrop} p_oDD the obj to get related data for
19536 * @param {boolean} bTargetsOnly if true, only return targetable objs
19537 * @return {DragDrop[]} the related instances
19540 getRelated: function(p_oDD, bTargetsOnly) {
19542 for (var i in p_oDD.groups) {
19543 for (j in this.ids[i]) {
19544 var dd = this.ids[i][j];
19545 if (! this.isTypeOfDD(dd)) {
19548 if (!bTargetsOnly || dd.isTarget) {
19549 oDDs[oDDs.length] = dd;
19558 * Returns true if the specified dd target is a legal target for
19559 * the specifice drag obj
19560 * @method isLegalTarget
19561 * @param {DragDrop} the drag obj
19562 * @param {DragDrop} the target
19563 * @return {boolean} true if the target is a legal target for the
19567 isLegalTarget: function (oDD, oTargetDD) {
19568 var targets = this.getRelated(oDD, true);
19569 for (var i=0, len=targets.length;i<len;++i) {
19570 if (targets[i].id == oTargetDD.id) {
19579 * My goal is to be able to transparently determine if an object is
19580 * typeof DragDrop, and the exact subclass of DragDrop. typeof
19581 * returns "object", oDD.constructor.toString() always returns
19582 * "DragDrop" and not the name of the subclass. So for now it just
19583 * evaluates a well-known variable in DragDrop.
19584 * @method isTypeOfDD
19585 * @param {Object} the object to evaluate
19586 * @return {boolean} true if typeof oDD = DragDrop
19589 isTypeOfDD: function (oDD) {
19590 return (oDD && oDD.__ygDragDrop);
19594 * Utility function to determine if a given element has been
19595 * registered as a drag drop handle for the given Drag Drop object.
19597 * @param {String} id the element id to check
19598 * @return {boolean} true if this element is a DragDrop handle, false
19602 isHandle: function(sDDId, sHandleId) {
19603 return ( this.handleIds[sDDId] &&
19604 this.handleIds[sDDId][sHandleId] );
19608 * Returns the DragDrop instance for a given id
19609 * @method getDDById
19610 * @param {String} id the id of the DragDrop object
19611 * @return {DragDrop} the drag drop object, null if it is not found
19614 getDDById: function(id) {
19615 for (var i in this.ids) {
19616 if (this.ids[i][id]) {
19617 return this.ids[i][id];
19624 * Fired after a registered DragDrop object gets the mousedown event.
19625 * Sets up the events required to track the object being dragged
19626 * @method handleMouseDown
19627 * @param {Event} e the event
19628 * @param oDD the DragDrop object being dragged
19632 handleMouseDown: function(e, oDD) {
19634 Roo.QuickTips.disable();
19636 this.currentTarget = e.getTarget();
19638 this.dragCurrent = oDD;
19640 var el = oDD.getEl();
19642 // track start position
19643 this.startX = e.getPageX();
19644 this.startY = e.getPageY();
19646 this.deltaX = this.startX - el.offsetLeft;
19647 this.deltaY = this.startY - el.offsetTop;
19649 this.dragThreshMet = false;
19651 this.clickTimeout = setTimeout(
19653 var DDM = Roo.dd.DDM;
19654 DDM.startDrag(DDM.startX, DDM.startY);
19656 this.clickTimeThresh );
19660 * Fired when either the drag pixel threshol or the mousedown hold
19661 * time threshold has been met.
19662 * @method startDrag
19663 * @param x {int} the X position of the original mousedown
19664 * @param y {int} the Y position of the original mousedown
19667 startDrag: function(x, y) {
19668 clearTimeout(this.clickTimeout);
19669 if (this.dragCurrent) {
19670 this.dragCurrent.b4StartDrag(x, y);
19671 this.dragCurrent.startDrag(x, y);
19673 this.dragThreshMet = true;
19677 * Internal function to handle the mouseup event. Will be invoked
19678 * from the context of the document.
19679 * @method handleMouseUp
19680 * @param {Event} e the event
19684 handleMouseUp: function(e) {
19687 Roo.QuickTips.enable();
19689 if (! this.dragCurrent) {
19693 clearTimeout(this.clickTimeout);
19695 if (this.dragThreshMet) {
19696 this.fireEvents(e, true);
19706 * Utility to stop event propagation and event default, if these
19707 * features are turned on.
19708 * @method stopEvent
19709 * @param {Event} e the event as returned by this.getEvent()
19712 stopEvent: function(e){
19713 if(this.stopPropagation) {
19714 e.stopPropagation();
19717 if (this.preventDefault) {
19718 e.preventDefault();
19723 * Internal function to clean up event handlers after the drag
19724 * operation is complete
19726 * @param {Event} e the event
19730 stopDrag: function(e) {
19731 // Fire the drag end event for the item that was dragged
19732 if (this.dragCurrent) {
19733 if (this.dragThreshMet) {
19734 this.dragCurrent.b4EndDrag(e);
19735 this.dragCurrent.endDrag(e);
19738 this.dragCurrent.onMouseUp(e);
19741 this.dragCurrent = null;
19742 this.dragOvers = {};
19746 * Internal function to handle the mousemove event. Will be invoked
19747 * from the context of the html element.
19749 * @TODO figure out what we can do about mouse events lost when the
19750 * user drags objects beyond the window boundary. Currently we can
19751 * detect this in internet explorer by verifying that the mouse is
19752 * down during the mousemove event. Firefox doesn't give us the
19753 * button state on the mousemove event.
19754 * @method handleMouseMove
19755 * @param {Event} e the event
19759 handleMouseMove: function(e) {
19760 if (! this.dragCurrent) {
19764 // var button = e.which || e.button;
19766 // check for IE mouseup outside of page boundary
19767 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
19769 return this.handleMouseUp(e);
19772 if (!this.dragThreshMet) {
19773 var diffX = Math.abs(this.startX - e.getPageX());
19774 var diffY = Math.abs(this.startY - e.getPageY());
19775 if (diffX > this.clickPixelThresh ||
19776 diffY > this.clickPixelThresh) {
19777 this.startDrag(this.startX, this.startY);
19781 if (this.dragThreshMet) {
19782 this.dragCurrent.b4Drag(e);
19783 this.dragCurrent.onDrag(e);
19784 if(!this.dragCurrent.moveOnly){
19785 this.fireEvents(e, false);
19795 * Iterates over all of the DragDrop elements to find ones we are
19796 * hovering over or dropping on
19797 * @method fireEvents
19798 * @param {Event} e the event
19799 * @param {boolean} isDrop is this a drop op or a mouseover op?
19803 fireEvents: function(e, isDrop) {
19804 var dc = this.dragCurrent;
19806 // If the user did the mouse up outside of the window, we could
19807 // get here even though we have ended the drag.
19808 if (!dc || dc.isLocked()) {
19812 var pt = e.getPoint();
19814 // cache the previous dragOver array
19820 var enterEvts = [];
19822 // Check to see if the object(s) we were hovering over is no longer
19823 // being hovered over so we can fire the onDragOut event
19824 for (var i in this.dragOvers) {
19826 var ddo = this.dragOvers[i];
19828 if (! this.isTypeOfDD(ddo)) {
19832 if (! this.isOverTarget(pt, ddo, this.mode)) {
19833 outEvts.push( ddo );
19836 oldOvers[i] = true;
19837 delete this.dragOvers[i];
19840 for (var sGroup in dc.groups) {
19842 if ("string" != typeof sGroup) {
19846 for (i in this.ids[sGroup]) {
19847 var oDD = this.ids[sGroup][i];
19848 if (! this.isTypeOfDD(oDD)) {
19852 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
19853 if (this.isOverTarget(pt, oDD, this.mode)) {
19854 // look for drop interactions
19856 dropEvts.push( oDD );
19857 // look for drag enter and drag over interactions
19860 // initial drag over: dragEnter fires
19861 if (!oldOvers[oDD.id]) {
19862 enterEvts.push( oDD );
19863 // subsequent drag overs: dragOver fires
19865 overEvts.push( oDD );
19868 this.dragOvers[oDD.id] = oDD;
19876 if (outEvts.length) {
19877 dc.b4DragOut(e, outEvts);
19878 dc.onDragOut(e, outEvts);
19881 if (enterEvts.length) {
19882 dc.onDragEnter(e, enterEvts);
19885 if (overEvts.length) {
19886 dc.b4DragOver(e, overEvts);
19887 dc.onDragOver(e, overEvts);
19890 if (dropEvts.length) {
19891 dc.b4DragDrop(e, dropEvts);
19892 dc.onDragDrop(e, dropEvts);
19896 // fire dragout events
19898 for (i=0, len=outEvts.length; i<len; ++i) {
19899 dc.b4DragOut(e, outEvts[i].id);
19900 dc.onDragOut(e, outEvts[i].id);
19903 // fire enter events
19904 for (i=0,len=enterEvts.length; i<len; ++i) {
19905 // dc.b4DragEnter(e, oDD.id);
19906 dc.onDragEnter(e, enterEvts[i].id);
19909 // fire over events
19910 for (i=0,len=overEvts.length; i<len; ++i) {
19911 dc.b4DragOver(e, overEvts[i].id);
19912 dc.onDragOver(e, overEvts[i].id);
19915 // fire drop events
19916 for (i=0, len=dropEvts.length; i<len; ++i) {
19917 dc.b4DragDrop(e, dropEvts[i].id);
19918 dc.onDragDrop(e, dropEvts[i].id);
19923 // notify about a drop that did not find a target
19924 if (isDrop && !dropEvts.length) {
19925 dc.onInvalidDrop(e);
19931 * Helper function for getting the best match from the list of drag
19932 * and drop objects returned by the drag and drop events when we are
19933 * in INTERSECT mode. It returns either the first object that the
19934 * cursor is over, or the object that has the greatest overlap with
19935 * the dragged element.
19936 * @method getBestMatch
19937 * @param {DragDrop[]} dds The array of drag and drop objects
19939 * @return {DragDrop} The best single match
19942 getBestMatch: function(dds) {
19944 // Return null if the input is not what we expect
19945 //if (!dds || !dds.length || dds.length == 0) {
19947 // If there is only one item, it wins
19948 //} else if (dds.length == 1) {
19950 var len = dds.length;
19955 // Loop through the targeted items
19956 for (var i=0; i<len; ++i) {
19958 // If the cursor is over the object, it wins. If the
19959 // cursor is over multiple matches, the first one we come
19961 if (dd.cursorIsOver) {
19964 // Otherwise the object with the most overlap wins
19967 winner.overlap.getArea() < dd.overlap.getArea()) {
19978 * Refreshes the cache of the top-left and bottom-right points of the
19979 * drag and drop objects in the specified group(s). This is in the
19980 * format that is stored in the drag and drop instance, so typical
19983 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
19987 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
19989 * @TODO this really should be an indexed array. Alternatively this
19990 * method could accept both.
19991 * @method refreshCache
19992 * @param {Object} groups an associative array of groups to refresh
19995 refreshCache: function(groups) {
19996 for (var sGroup in groups) {
19997 if ("string" != typeof sGroup) {
20000 for (var i in this.ids[sGroup]) {
20001 var oDD = this.ids[sGroup][i];
20003 if (this.isTypeOfDD(oDD)) {
20004 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
20005 var loc = this.getLocation(oDD);
20007 this.locationCache[oDD.id] = loc;
20009 delete this.locationCache[oDD.id];
20010 // this will unregister the drag and drop object if
20011 // the element is not in a usable state
20020 * This checks to make sure an element exists and is in the DOM. The
20021 * main purpose is to handle cases where innerHTML is used to remove
20022 * drag and drop objects from the DOM. IE provides an 'unspecified
20023 * error' when trying to access the offsetParent of such an element
20025 * @param {HTMLElement} el the element to check
20026 * @return {boolean} true if the element looks usable
20029 verifyEl: function(el) {
20034 parent = el.offsetParent;
20037 parent = el.offsetParent;
20048 * Returns a Region object containing the drag and drop element's position
20049 * and size, including the padding configured for it
20050 * @method getLocation
20051 * @param {DragDrop} oDD the drag and drop object to get the
20053 * @return {Roo.lib.Region} a Region object representing the total area
20054 * the element occupies, including any padding
20055 * the instance is configured for.
20058 getLocation: function(oDD) {
20059 if (! this.isTypeOfDD(oDD)) {
20063 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
20066 pos= Roo.lib.Dom.getXY(el);
20074 x2 = x1 + el.offsetWidth;
20076 y2 = y1 + el.offsetHeight;
20078 t = y1 - oDD.padding[0];
20079 r = x2 + oDD.padding[1];
20080 b = y2 + oDD.padding[2];
20081 l = x1 - oDD.padding[3];
20083 return new Roo.lib.Region( t, r, b, l );
20087 * Checks the cursor location to see if it over the target
20088 * @method isOverTarget
20089 * @param {Roo.lib.Point} pt The point to evaluate
20090 * @param {DragDrop} oTarget the DragDrop object we are inspecting
20091 * @return {boolean} true if the mouse is over the target
20095 isOverTarget: function(pt, oTarget, intersect) {
20096 // use cache if available
20097 var loc = this.locationCache[oTarget.id];
20098 if (!loc || !this.useCache) {
20099 loc = this.getLocation(oTarget);
20100 this.locationCache[oTarget.id] = loc;
20108 oTarget.cursorIsOver = loc.contains( pt );
20110 // DragDrop is using this as a sanity check for the initial mousedown
20111 // in this case we are done. In POINT mode, if the drag obj has no
20112 // contraints, we are also done. Otherwise we need to evaluate the
20113 // location of the target as related to the actual location of the
20114 // dragged element.
20115 var dc = this.dragCurrent;
20116 if (!dc || !dc.getTargetCoord ||
20117 (!intersect && !dc.constrainX && !dc.constrainY)) {
20118 return oTarget.cursorIsOver;
20121 oTarget.overlap = null;
20123 // Get the current location of the drag element, this is the
20124 // location of the mouse event less the delta that represents
20125 // where the original mousedown happened on the element. We
20126 // need to consider constraints and ticks as well.
20127 var pos = dc.getTargetCoord(pt.x, pt.y);
20129 var el = dc.getDragEl();
20130 var curRegion = new Roo.lib.Region( pos.y,
20131 pos.x + el.offsetWidth,
20132 pos.y + el.offsetHeight,
20135 var overlap = curRegion.intersect(loc);
20138 oTarget.overlap = overlap;
20139 return (intersect) ? true : oTarget.cursorIsOver;
20146 * unload event handler
20147 * @method _onUnload
20151 _onUnload: function(e, me) {
20152 Roo.dd.DragDropMgr.unregAll();
20156 * Cleans up the drag and drop events and objects.
20161 unregAll: function() {
20163 if (this.dragCurrent) {
20165 this.dragCurrent = null;
20168 this._execOnAll("unreg", []);
20170 for (i in this.elementCache) {
20171 delete this.elementCache[i];
20174 this.elementCache = {};
20179 * A cache of DOM elements
20180 * @property elementCache
20187 * Get the wrapper for the DOM element specified
20188 * @method getElWrapper
20189 * @param {String} id the id of the element to get
20190 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
20192 * @deprecated This wrapper isn't that useful
20195 getElWrapper: function(id) {
20196 var oWrapper = this.elementCache[id];
20197 if (!oWrapper || !oWrapper.el) {
20198 oWrapper = this.elementCache[id] =
20199 new this.ElementWrapper(Roo.getDom(id));
20205 * Returns the actual DOM element
20206 * @method getElement
20207 * @param {String} id the id of the elment to get
20208 * @return {Object} The element
20209 * @deprecated use Roo.getDom instead
20212 getElement: function(id) {
20213 return Roo.getDom(id);
20217 * Returns the style property for the DOM element (i.e.,
20218 * document.getElById(id).style)
20220 * @param {String} id the id of the elment to get
20221 * @return {Object} The style property of the element
20222 * @deprecated use Roo.getDom instead
20225 getCss: function(id) {
20226 var el = Roo.getDom(id);
20227 return (el) ? el.style : null;
20231 * Inner class for cached elements
20232 * @class DragDropMgr.ElementWrapper
20237 ElementWrapper: function(el) {
20242 this.el = el || null;
20247 this.id = this.el && el.id;
20249 * A reference to the style property
20252 this.css = this.el && el.style;
20256 * Returns the X position of an html element
20258 * @param el the element for which to get the position
20259 * @return {int} the X coordinate
20261 * @deprecated use Roo.lib.Dom.getX instead
20264 getPosX: function(el) {
20265 return Roo.lib.Dom.getX(el);
20269 * Returns the Y position of an html element
20271 * @param el the element for which to get the position
20272 * @return {int} the Y coordinate
20273 * @deprecated use Roo.lib.Dom.getY instead
20276 getPosY: function(el) {
20277 return Roo.lib.Dom.getY(el);
20281 * Swap two nodes. In IE, we use the native method, for others we
20282 * emulate the IE behavior
20284 * @param n1 the first node to swap
20285 * @param n2 the other node to swap
20288 swapNode: function(n1, n2) {
20292 var p = n2.parentNode;
20293 var s = n2.nextSibling;
20296 p.insertBefore(n1, n2);
20297 } else if (n2 == n1.nextSibling) {
20298 p.insertBefore(n2, n1);
20300 n1.parentNode.replaceChild(n2, n1);
20301 p.insertBefore(n1, s);
20307 * Returns the current scroll position
20308 * @method getScroll
20312 getScroll: function () {
20313 var t, l, dde=document.documentElement, db=document.body;
20314 if (dde && (dde.scrollTop || dde.scrollLeft)) {
20316 l = dde.scrollLeft;
20323 return { top: t, left: l };
20327 * Returns the specified element style property
20329 * @param {HTMLElement} el the element
20330 * @param {string} styleProp the style property
20331 * @return {string} The value of the style property
20332 * @deprecated use Roo.lib.Dom.getStyle
20335 getStyle: function(el, styleProp) {
20336 return Roo.fly(el).getStyle(styleProp);
20340 * Gets the scrollTop
20341 * @method getScrollTop
20342 * @return {int} the document's scrollTop
20345 getScrollTop: function () { return this.getScroll().top; },
20348 * Gets the scrollLeft
20349 * @method getScrollLeft
20350 * @return {int} the document's scrollTop
20353 getScrollLeft: function () { return this.getScroll().left; },
20356 * Sets the x/y position of an element to the location of the
20359 * @param {HTMLElement} moveEl The element to move
20360 * @param {HTMLElement} targetEl The position reference element
20363 moveToEl: function (moveEl, targetEl) {
20364 var aCoord = Roo.lib.Dom.getXY(targetEl);
20365 Roo.lib.Dom.setXY(moveEl, aCoord);
20369 * Numeric array sort function
20370 * @method numericSort
20373 numericSort: function(a, b) { return (a - b); },
20377 * @property _timeoutCount
20384 * Trying to make the load order less important. Without this we get
20385 * an error if this file is loaded before the Event Utility.
20386 * @method _addListeners
20390 _addListeners: function() {
20391 var DDM = Roo.dd.DDM;
20392 if ( Roo.lib.Event && document ) {
20395 if (DDM._timeoutCount > 2000) {
20397 setTimeout(DDM._addListeners, 10);
20398 if (document && document.body) {
20399 DDM._timeoutCount += 1;
20406 * Recursively searches the immediate parent and all child nodes for
20407 * the handle element in order to determine wheter or not it was
20409 * @method handleWasClicked
20410 * @param node the html element to inspect
20413 handleWasClicked: function(node, id) {
20414 if (this.isHandle(id, node.id)) {
20417 // check to see if this is a text node child of the one we want
20418 var p = node.parentNode;
20421 if (this.isHandle(id, p.id)) {
20436 // shorter alias, save a few bytes
20437 Roo.dd.DDM = Roo.dd.DragDropMgr;
20438 Roo.dd.DDM._addListeners();
20442 * Ext JS Library 1.1.1
20443 * Copyright(c) 2006-2007, Ext JS, LLC.
20445 * Originally Released Under LGPL - original licence link has changed is not relivant.
20448 * <script type="text/javascript">
20453 * A DragDrop implementation where the linked element follows the
20454 * mouse cursor during a drag.
20455 * @extends Roo.dd.DragDrop
20457 * @param {String} id the id of the linked element
20458 * @param {String} sGroup the group of related DragDrop items
20459 * @param {object} config an object containing configurable attributes
20460 * Valid properties for DD:
20463 Roo.dd.DD = function(id, sGroup, config) {
20465 this.init(id, sGroup, config);
20469 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
20472 * When set to true, the utility automatically tries to scroll the browser
20473 * window wehn a drag and drop element is dragged near the viewport boundary.
20474 * Defaults to true.
20481 * Sets the pointer offset to the distance between the linked element's top
20482 * left corner and the location the element was clicked
20483 * @method autoOffset
20484 * @param {int} iPageX the X coordinate of the click
20485 * @param {int} iPageY the Y coordinate of the click
20487 autoOffset: function(iPageX, iPageY) {
20488 var x = iPageX - this.startPageX;
20489 var y = iPageY - this.startPageY;
20490 this.setDelta(x, y);
20494 * Sets the pointer offset. You can call this directly to force the
20495 * offset to be in a particular location (e.g., pass in 0,0 to set it
20496 * to the center of the object)
20498 * @param {int} iDeltaX the distance from the left
20499 * @param {int} iDeltaY the distance from the top
20501 setDelta: function(iDeltaX, iDeltaY) {
20502 this.deltaX = iDeltaX;
20503 this.deltaY = iDeltaY;
20507 * Sets the drag element to the location of the mousedown or click event,
20508 * maintaining the cursor location relative to the location on the element
20509 * that was clicked. Override this if you want to place the element in a
20510 * location other than where the cursor is.
20511 * @method setDragElPos
20512 * @param {int} iPageX the X coordinate of the mousedown or drag event
20513 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20515 setDragElPos: function(iPageX, iPageY) {
20516 // the first time we do this, we are going to check to make sure
20517 // the element has css positioning
20519 var el = this.getDragEl();
20520 this.alignElWithMouse(el, iPageX, iPageY);
20524 * Sets the element to the location of the mousedown or click event,
20525 * maintaining the cursor location relative to the location on the element
20526 * that was clicked. Override this if you want to place the element in a
20527 * location other than where the cursor is.
20528 * @method alignElWithMouse
20529 * @param {HTMLElement} el the element to move
20530 * @param {int} iPageX the X coordinate of the mousedown or drag event
20531 * @param {int} iPageY the Y coordinate of the mousedown or drag event
20533 alignElWithMouse: function(el, iPageX, iPageY) {
20534 var oCoord = this.getTargetCoord(iPageX, iPageY);
20535 var fly = el.dom ? el : Roo.fly(el);
20536 if (!this.deltaSetXY) {
20537 var aCoord = [oCoord.x, oCoord.y];
20539 var newLeft = fly.getLeft(true);
20540 var newTop = fly.getTop(true);
20541 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
20543 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
20546 this.cachePosition(oCoord.x, oCoord.y);
20547 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
20552 * Saves the most recent position so that we can reset the constraints and
20553 * tick marks on-demand. We need to know this so that we can calculate the
20554 * number of pixels the element is offset from its original position.
20555 * @method cachePosition
20556 * @param iPageX the current x position (optional, this just makes it so we
20557 * don't have to look it up again)
20558 * @param iPageY the current y position (optional, this just makes it so we
20559 * don't have to look it up again)
20561 cachePosition: function(iPageX, iPageY) {
20563 this.lastPageX = iPageX;
20564 this.lastPageY = iPageY;
20566 var aCoord = Roo.lib.Dom.getXY(this.getEl());
20567 this.lastPageX = aCoord[0];
20568 this.lastPageY = aCoord[1];
20573 * Auto-scroll the window if the dragged object has been moved beyond the
20574 * visible window boundary.
20575 * @method autoScroll
20576 * @param {int} x the drag element's x position
20577 * @param {int} y the drag element's y position
20578 * @param {int} h the height of the drag element
20579 * @param {int} w the width of the drag element
20582 autoScroll: function(x, y, h, w) {
20585 // The client height
20586 var clientH = Roo.lib.Dom.getViewWidth();
20588 // The client width
20589 var clientW = Roo.lib.Dom.getViewHeight();
20591 // The amt scrolled down
20592 var st = this.DDM.getScrollTop();
20594 // The amt scrolled right
20595 var sl = this.DDM.getScrollLeft();
20597 // Location of the bottom of the element
20600 // Location of the right of the element
20603 // The distance from the cursor to the bottom of the visible area,
20604 // adjusted so that we don't scroll if the cursor is beyond the
20605 // element drag constraints
20606 var toBot = (clientH + st - y - this.deltaY);
20608 // The distance from the cursor to the right of the visible area
20609 var toRight = (clientW + sl - x - this.deltaX);
20612 // How close to the edge the cursor must be before we scroll
20613 // var thresh = (document.all) ? 100 : 40;
20616 // How many pixels to scroll per autoscroll op. This helps to reduce
20617 // clunky scrolling. IE is more sensitive about this ... it needs this
20618 // value to be higher.
20619 var scrAmt = (document.all) ? 80 : 30;
20621 // Scroll down if we are near the bottom of the visible page and the
20622 // obj extends below the crease
20623 if ( bot > clientH && toBot < thresh ) {
20624 window.scrollTo(sl, st + scrAmt);
20627 // Scroll up if the window is scrolled down and the top of the object
20628 // goes above the top border
20629 if ( y < st && st > 0 && y - st < thresh ) {
20630 window.scrollTo(sl, st - scrAmt);
20633 // Scroll right if the obj is beyond the right border and the cursor is
20634 // near the border.
20635 if ( right > clientW && toRight < thresh ) {
20636 window.scrollTo(sl + scrAmt, st);
20639 // Scroll left if the window has been scrolled to the right and the obj
20640 // extends past the left border
20641 if ( x < sl && sl > 0 && x - sl < thresh ) {
20642 window.scrollTo(sl - scrAmt, st);
20648 * Finds the location the element should be placed if we want to move
20649 * it to where the mouse location less the click offset would place us.
20650 * @method getTargetCoord
20651 * @param {int} iPageX the X coordinate of the click
20652 * @param {int} iPageY the Y coordinate of the click
20653 * @return an object that contains the coordinates (Object.x and Object.y)
20656 getTargetCoord: function(iPageX, iPageY) {
20659 var x = iPageX - this.deltaX;
20660 var y = iPageY - this.deltaY;
20662 if (this.constrainX) {
20663 if (x < this.minX) { x = this.minX; }
20664 if (x > this.maxX) { x = this.maxX; }
20667 if (this.constrainY) {
20668 if (y < this.minY) { y = this.minY; }
20669 if (y > this.maxY) { y = this.maxY; }
20672 x = this.getTick(x, this.xTicks);
20673 y = this.getTick(y, this.yTicks);
20680 * Sets up config options specific to this class. Overrides
20681 * Roo.dd.DragDrop, but all versions of this method through the
20682 * inheritance chain are called
20684 applyConfig: function() {
20685 Roo.dd.DD.superclass.applyConfig.call(this);
20686 this.scroll = (this.config.scroll !== false);
20690 * Event that fires prior to the onMouseDown event. Overrides
20693 b4MouseDown: function(e) {
20694 // this.resetConstraints();
20695 this.autoOffset(e.getPageX(),
20700 * Event that fires prior to the onDrag event. Overrides
20703 b4Drag: function(e) {
20704 this.setDragElPos(e.getPageX(),
20708 toString: function() {
20709 return ("DD " + this.id);
20712 //////////////////////////////////////////////////////////////////////////
20713 // Debugging ygDragDrop events that can be overridden
20714 //////////////////////////////////////////////////////////////////////////
20716 startDrag: function(x, y) {
20719 onDrag: function(e) {
20722 onDragEnter: function(e, id) {
20725 onDragOver: function(e, id) {
20728 onDragOut: function(e, id) {
20731 onDragDrop: function(e, id) {
20734 endDrag: function(e) {
20741 * Ext JS Library 1.1.1
20742 * Copyright(c) 2006-2007, Ext JS, LLC.
20744 * Originally Released Under LGPL - original licence link has changed is not relivant.
20747 * <script type="text/javascript">
20751 * @class Roo.dd.DDProxy
20752 * A DragDrop implementation that inserts an empty, bordered div into
20753 * the document that follows the cursor during drag operations. At the time of
20754 * the click, the frame div is resized to the dimensions of the linked html
20755 * element, and moved to the exact location of the linked element.
20757 * References to the "frame" element refer to the single proxy element that
20758 * was created to be dragged in place of all DDProxy elements on the
20761 * @extends Roo.dd.DD
20763 * @param {String} id the id of the linked html element
20764 * @param {String} sGroup the group of related DragDrop objects
20765 * @param {object} config an object containing configurable attributes
20766 * Valid properties for DDProxy in addition to those in DragDrop:
20767 * resizeFrame, centerFrame, dragElId
20769 Roo.dd.DDProxy = function(id, sGroup, config) {
20771 this.init(id, sGroup, config);
20777 * The default drag frame div id
20778 * @property Roo.dd.DDProxy.dragElId
20782 Roo.dd.DDProxy.dragElId = "ygddfdiv";
20784 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
20787 * By default we resize the drag frame to be the same size as the element
20788 * we want to drag (this is to get the frame effect). We can turn it off
20789 * if we want a different behavior.
20790 * @property resizeFrame
20796 * By default the frame is positioned exactly where the drag element is, so
20797 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
20798 * you do not have constraints on the obj is to have the drag frame centered
20799 * around the cursor. Set centerFrame to true for this effect.
20800 * @property centerFrame
20803 centerFrame: false,
20806 * Creates the proxy element if it does not yet exist
20807 * @method createFrame
20809 createFrame: function() {
20811 var body = document.body;
20813 if (!body || !body.firstChild) {
20814 setTimeout( function() { self.createFrame(); }, 50 );
20818 var div = this.getDragEl();
20821 div = document.createElement("div");
20822 div.id = this.dragElId;
20825 s.position = "absolute";
20826 s.visibility = "hidden";
20828 s.border = "2px solid #aaa";
20831 // appendChild can blow up IE if invoked prior to the window load event
20832 // while rendering a table. It is possible there are other scenarios
20833 // that would cause this to happen as well.
20834 body.insertBefore(div, body.firstChild);
20839 * Initialization for the drag frame element. Must be called in the
20840 * constructor of all subclasses
20841 * @method initFrame
20843 initFrame: function() {
20844 this.createFrame();
20847 applyConfig: function() {
20848 Roo.dd.DDProxy.superclass.applyConfig.call(this);
20850 this.resizeFrame = (this.config.resizeFrame !== false);
20851 this.centerFrame = (this.config.centerFrame);
20852 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
20856 * Resizes the drag frame to the dimensions of the clicked object, positions
20857 * it over the object, and finally displays it
20858 * @method showFrame
20859 * @param {int} iPageX X click position
20860 * @param {int} iPageY Y click position
20863 showFrame: function(iPageX, iPageY) {
20864 var el = this.getEl();
20865 var dragEl = this.getDragEl();
20866 var s = dragEl.style;
20868 this._resizeProxy();
20870 if (this.centerFrame) {
20871 this.setDelta( Math.round(parseInt(s.width, 10)/2),
20872 Math.round(parseInt(s.height, 10)/2) );
20875 this.setDragElPos(iPageX, iPageY);
20877 Roo.fly(dragEl).show();
20881 * The proxy is automatically resized to the dimensions of the linked
20882 * element when a drag is initiated, unless resizeFrame is set to false
20883 * @method _resizeProxy
20886 _resizeProxy: function() {
20887 if (this.resizeFrame) {
20888 var el = this.getEl();
20889 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
20893 // overrides Roo.dd.DragDrop
20894 b4MouseDown: function(e) {
20895 var x = e.getPageX();
20896 var y = e.getPageY();
20897 this.autoOffset(x, y);
20898 this.setDragElPos(x, y);
20901 // overrides Roo.dd.DragDrop
20902 b4StartDrag: function(x, y) {
20903 // show the drag frame
20904 this.showFrame(x, y);
20907 // overrides Roo.dd.DragDrop
20908 b4EndDrag: function(e) {
20909 Roo.fly(this.getDragEl()).hide();
20912 // overrides Roo.dd.DragDrop
20913 // By default we try to move the element to the last location of the frame.
20914 // This is so that the default behavior mirrors that of Roo.dd.DD.
20915 endDrag: function(e) {
20917 var lel = this.getEl();
20918 var del = this.getDragEl();
20920 // Show the drag frame briefly so we can get its position
20921 del.style.visibility = "";
20924 // Hide the linked element before the move to get around a Safari
20926 lel.style.visibility = "hidden";
20927 Roo.dd.DDM.moveToEl(lel, del);
20928 del.style.visibility = "hidden";
20929 lel.style.visibility = "";
20934 beforeMove : function(){
20938 afterDrag : function(){
20942 toString: function() {
20943 return ("DDProxy " + this.id);
20949 * Ext JS Library 1.1.1
20950 * Copyright(c) 2006-2007, Ext JS, LLC.
20952 * Originally Released Under LGPL - original licence link has changed is not relivant.
20955 * <script type="text/javascript">
20959 * @class Roo.dd.DDTarget
20960 * A DragDrop implementation that does not move, but can be a drop
20961 * target. You would get the same result by simply omitting implementation
20962 * for the event callbacks, but this way we reduce the processing cost of the
20963 * event listener and the callbacks.
20964 * @extends Roo.dd.DragDrop
20966 * @param {String} id the id of the element that is a drop target
20967 * @param {String} sGroup the group of related DragDrop objects
20968 * @param {object} config an object containing configurable attributes
20969 * Valid properties for DDTarget in addition to those in
20973 Roo.dd.DDTarget = function(id, sGroup, config) {
20975 this.initTarget(id, sGroup, config);
20977 if (config.listeners || config.events) {
20978 Roo.dd.DragDrop.superclass.constructor.call(this, {
20979 listeners : config.listeners || {},
20980 events : config.events || {}
20985 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
20986 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
20987 toString: function() {
20988 return ("DDTarget " + this.id);
20993 * Ext JS Library 1.1.1
20994 * Copyright(c) 2006-2007, Ext JS, LLC.
20996 * Originally Released Under LGPL - original licence link has changed is not relivant.
20999 * <script type="text/javascript">
21004 * @class Roo.dd.ScrollManager
21005 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
21006 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
21009 Roo.dd.ScrollManager = function(){
21010 var ddm = Roo.dd.DragDropMgr;
21017 var onStop = function(e){
21022 var triggerRefresh = function(){
21023 if(ddm.dragCurrent){
21024 ddm.refreshCache(ddm.dragCurrent.groups);
21028 var doScroll = function(){
21029 if(ddm.dragCurrent){
21030 var dds = Roo.dd.ScrollManager;
21032 if(proc.el.scroll(proc.dir, dds.increment)){
21036 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
21041 var clearProc = function(){
21043 clearInterval(proc.id);
21050 var startProc = function(el, dir){
21051 Roo.log('scroll startproc');
21055 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
21058 var onFire = function(e, isDrop){
21060 if(isDrop || !ddm.dragCurrent){ return; }
21061 var dds = Roo.dd.ScrollManager;
21062 if(!dragEl || dragEl != ddm.dragCurrent){
21063 dragEl = ddm.dragCurrent;
21064 // refresh regions on drag start
21065 dds.refreshCache();
21068 var xy = Roo.lib.Event.getXY(e);
21069 var pt = new Roo.lib.Point(xy[0], xy[1]);
21070 for(var id in els){
21071 var el = els[id], r = el._region;
21072 if(r && r.contains(pt) && el.isScrollable()){
21073 if(r.bottom - pt.y <= dds.thresh){
21075 startProc(el, "down");
21078 }else if(r.right - pt.x <= dds.thresh){
21080 startProc(el, "left");
21083 }else if(pt.y - r.top <= dds.thresh){
21085 startProc(el, "up");
21088 }else if(pt.x - r.left <= dds.thresh){
21090 startProc(el, "right");
21099 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
21100 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
21104 * Registers new overflow element(s) to auto scroll
21105 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
21107 register : function(el){
21108 if(el instanceof Array){
21109 for(var i = 0, len = el.length; i < len; i++) {
21110 this.register(el[i]);
21116 Roo.dd.ScrollManager.els = els;
21120 * Unregisters overflow element(s) so they are no longer scrolled
21121 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
21123 unregister : function(el){
21124 if(el instanceof Array){
21125 for(var i = 0, len = el.length; i < len; i++) {
21126 this.unregister(el[i]);
21135 * The number of pixels from the edge of a container the pointer needs to be to
21136 * trigger scrolling (defaults to 25)
21142 * The number of pixels to scroll in each scroll increment (defaults to 50)
21148 * The frequency of scrolls in milliseconds (defaults to 500)
21154 * True to animate the scroll (defaults to true)
21160 * The animation duration in seconds -
21161 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
21167 * Manually trigger a cache refresh.
21169 refreshCache : function(){
21170 for(var id in els){
21171 if(typeof els[id] == 'object'){ // for people extending the object prototype
21172 els[id]._region = els[id].getRegion();
21179 * Ext JS Library 1.1.1
21180 * Copyright(c) 2006-2007, Ext JS, LLC.
21182 * Originally Released Under LGPL - original licence link has changed is not relivant.
21185 * <script type="text/javascript">
21190 * @class Roo.dd.Registry
21191 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
21192 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
21195 Roo.dd.Registry = function(){
21198 var autoIdSeed = 0;
21200 var getId = function(el, autogen){
21201 if(typeof el == "string"){
21205 if(!id && autogen !== false){
21206 id = "roodd-" + (++autoIdSeed);
21214 * Register a drag drop element
21215 * @param {String|HTMLElement} element The id or DOM node to register
21216 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
21217 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
21218 * knows how to interpret, plus there are some specific properties known to the Registry that should be
21219 * populated in the data object (if applicable):
21221 Value Description<br />
21222 --------- ------------------------------------------<br />
21223 handles Array of DOM nodes that trigger dragging<br />
21224 for the element being registered<br />
21225 isHandle True if the element passed in triggers<br />
21226 dragging itself, else false
21229 register : function(el, data){
21231 if(typeof el == "string"){
21232 el = document.getElementById(el);
21235 elements[getId(el)] = data;
21236 if(data.isHandle !== false){
21237 handles[data.ddel.id] = data;
21240 var hs = data.handles;
21241 for(var i = 0, len = hs.length; i < len; i++){
21242 handles[getId(hs[i])] = data;
21248 * Unregister a drag drop element
21249 * @param {String|HTMLElement} element The id or DOM node to unregister
21251 unregister : function(el){
21252 var id = getId(el, false);
21253 var data = elements[id];
21255 delete elements[id];
21257 var hs = data.handles;
21258 for(var i = 0, len = hs.length; i < len; i++){
21259 delete handles[getId(hs[i], false)];
21266 * Returns the handle registered for a DOM Node by id
21267 * @param {String|HTMLElement} id The DOM node or id to look up
21268 * @return {Object} handle The custom handle data
21270 getHandle : function(id){
21271 if(typeof id != "string"){ // must be element?
21274 return handles[id];
21278 * Returns the handle that is registered for the DOM node that is the target of the event
21279 * @param {Event} e The event
21280 * @return {Object} handle The custom handle data
21282 getHandleFromEvent : function(e){
21283 var t = Roo.lib.Event.getTarget(e);
21284 return t ? handles[t.id] : null;
21288 * Returns a custom data object that is registered for a DOM node by id
21289 * @param {String|HTMLElement} id The DOM node or id to look up
21290 * @return {Object} data The custom data
21292 getTarget : function(id){
21293 if(typeof id != "string"){ // must be element?
21296 return elements[id];
21300 * Returns a custom data object that is registered for the DOM node that is the target of the event
21301 * @param {Event} e The event
21302 * @return {Object} data The custom data
21304 getTargetFromEvent : function(e){
21305 var t = Roo.lib.Event.getTarget(e);
21306 return t ? elements[t.id] || handles[t.id] : null;
21311 * Ext JS Library 1.1.1
21312 * Copyright(c) 2006-2007, Ext JS, LLC.
21314 * Originally Released Under LGPL - original licence link has changed is not relivant.
21317 * <script type="text/javascript">
21322 * @class Roo.dd.StatusProxy
21323 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
21324 * default drag proxy used by all Roo.dd components.
21326 * @param {Object} config
21328 Roo.dd.StatusProxy = function(config){
21329 Roo.apply(this, config);
21330 this.id = this.id || Roo.id();
21331 this.el = new Roo.Layer({
21333 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
21334 {tag: "div", cls: "x-dd-drop-icon"},
21335 {tag: "div", cls: "x-dd-drag-ghost"}
21338 shadow: !config || config.shadow !== false
21340 this.ghost = Roo.get(this.el.dom.childNodes[1]);
21341 this.dropStatus = this.dropNotAllowed;
21344 Roo.dd.StatusProxy.prototype = {
21346 * @cfg {String} dropAllowed
21347 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
21349 dropAllowed : "x-dd-drop-ok",
21351 * @cfg {String} dropNotAllowed
21352 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
21354 dropNotAllowed : "x-dd-drop-nodrop",
21357 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
21358 * over the current target element.
21359 * @param {String} cssClass The css class for the new drop status indicator image
21361 setStatus : function(cssClass){
21362 cssClass = cssClass || this.dropNotAllowed;
21363 if(this.dropStatus != cssClass){
21364 this.el.replaceClass(this.dropStatus, cssClass);
21365 this.dropStatus = cssClass;
21370 * Resets the status indicator to the default dropNotAllowed value
21371 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
21373 reset : function(clearGhost){
21374 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
21375 this.dropStatus = this.dropNotAllowed;
21377 this.ghost.update("");
21382 * Updates the contents of the ghost element
21383 * @param {String} html The html that will replace the current innerHTML of the ghost element
21385 update : function(html){
21386 if(typeof html == "string"){
21387 this.ghost.update(html);
21389 this.ghost.update("");
21390 html.style.margin = "0";
21391 this.ghost.dom.appendChild(html);
21393 // ensure float = none set?? cant remember why though.
21394 var el = this.ghost.dom.firstChild;
21396 Roo.fly(el).setStyle('float', 'none');
21401 * Returns the underlying proxy {@link Roo.Layer}
21402 * @return {Roo.Layer} el
21404 getEl : function(){
21409 * Returns the ghost element
21410 * @return {Roo.Element} el
21412 getGhost : function(){
21418 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
21420 hide : function(clear){
21428 * Stops the repair animation if it's currently running
21431 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
21437 * Displays this proxy
21444 * Force the Layer to sync its shadow and shim positions to the element
21451 * Causes the proxy to return to its position of origin via an animation. Should be called after an
21452 * invalid drop operation by the item being dragged.
21453 * @param {Array} xy The XY position of the element ([x, y])
21454 * @param {Function} callback The function to call after the repair is complete
21455 * @param {Object} scope The scope in which to execute the callback
21457 repair : function(xy, callback, scope){
21458 this.callback = callback;
21459 this.scope = scope;
21460 if(xy && this.animRepair !== false){
21461 this.el.addClass("x-dd-drag-repair");
21462 this.el.hideUnders(true);
21463 this.anim = this.el.shift({
21464 duration: this.repairDuration || .5,
21468 callback: this.afterRepair,
21472 this.afterRepair();
21477 afterRepair : function(){
21479 if(typeof this.callback == "function"){
21480 this.callback.call(this.scope || this);
21482 this.callback = null;
21487 * Ext JS Library 1.1.1
21488 * Copyright(c) 2006-2007, Ext JS, LLC.
21490 * Originally Released Under LGPL - original licence link has changed is not relivant.
21493 * <script type="text/javascript">
21497 * @class Roo.dd.DragSource
21498 * @extends Roo.dd.DDProxy
21499 * A simple class that provides the basic implementation needed to make any element draggable.
21501 * @param {String/HTMLElement/Element} el The container element
21502 * @param {Object} config
21504 Roo.dd.DragSource = function(el, config){
21505 this.el = Roo.get(el);
21506 this.dragData = {};
21508 Roo.apply(this, config);
21511 this.proxy = new Roo.dd.StatusProxy();
21514 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
21515 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
21517 this.dragging = false;
21520 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
21522 * @cfg {String} dropAllowed
21523 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21525 dropAllowed : "x-dd-drop-ok",
21527 * @cfg {String} dropNotAllowed
21528 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21530 dropNotAllowed : "x-dd-drop-nodrop",
21533 * Returns the data object associated with this drag source
21534 * @return {Object} data An object containing arbitrary data
21536 getDragData : function(e){
21537 return this.dragData;
21541 onDragEnter : function(e, id){
21542 var target = Roo.dd.DragDropMgr.getDDById(id);
21543 this.cachedTarget = target;
21544 if(this.beforeDragEnter(target, e, id) !== false){
21545 if(target.isNotifyTarget){
21546 var status = target.notifyEnter(this, e, this.dragData);
21547 this.proxy.setStatus(status);
21549 this.proxy.setStatus(this.dropAllowed);
21552 if(this.afterDragEnter){
21554 * An empty function by default, but provided so that you can perform a custom action
21555 * when the dragged item enters the drop target by providing an implementation.
21556 * @param {Roo.dd.DragDrop} target The drop target
21557 * @param {Event} e The event object
21558 * @param {String} id The id of the dragged element
21559 * @method afterDragEnter
21561 this.afterDragEnter(target, e, id);
21567 * An empty function by default, but provided so that you can perform a custom action
21568 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
21569 * @param {Roo.dd.DragDrop} target The drop target
21570 * @param {Event} e The event object
21571 * @param {String} id The id of the dragged element
21572 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21574 beforeDragEnter : function(target, e, id){
21579 alignElWithMouse: function() {
21580 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
21585 onDragOver : function(e, id){
21586 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21587 if(this.beforeDragOver(target, e, id) !== false){
21588 if(target.isNotifyTarget){
21589 var status = target.notifyOver(this, e, this.dragData);
21590 this.proxy.setStatus(status);
21593 if(this.afterDragOver){
21595 * An empty function by default, but provided so that you can perform a custom action
21596 * while the dragged item is over the drop target by providing an implementation.
21597 * @param {Roo.dd.DragDrop} target The drop target
21598 * @param {Event} e The event object
21599 * @param {String} id The id of the dragged element
21600 * @method afterDragOver
21602 this.afterDragOver(target, e, id);
21608 * An empty function by default, but provided so that you can perform a custom action
21609 * while the dragged item is over the drop target and optionally cancel the onDragOver.
21610 * @param {Roo.dd.DragDrop} target The drop target
21611 * @param {Event} e The event object
21612 * @param {String} id The id of the dragged element
21613 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21615 beforeDragOver : function(target, e, id){
21620 onDragOut : function(e, id){
21621 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21622 if(this.beforeDragOut(target, e, id) !== false){
21623 if(target.isNotifyTarget){
21624 target.notifyOut(this, e, this.dragData);
21626 this.proxy.reset();
21627 if(this.afterDragOut){
21629 * An empty function by default, but provided so that you can perform a custom action
21630 * after the dragged item is dragged out of the target without dropping.
21631 * @param {Roo.dd.DragDrop} target The drop target
21632 * @param {Event} e The event object
21633 * @param {String} id The id of the dragged element
21634 * @method afterDragOut
21636 this.afterDragOut(target, e, id);
21639 this.cachedTarget = null;
21643 * An empty function by default, but provided so that you can perform a custom action before the dragged
21644 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
21645 * @param {Roo.dd.DragDrop} target The drop target
21646 * @param {Event} e The event object
21647 * @param {String} id The id of the dragged element
21648 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21650 beforeDragOut : function(target, e, id){
21655 onDragDrop : function(e, id){
21656 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
21657 if(this.beforeDragDrop(target, e, id) !== false){
21658 if(target.isNotifyTarget){
21659 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
21660 this.onValidDrop(target, e, id);
21662 this.onInvalidDrop(target, e, id);
21665 this.onValidDrop(target, e, id);
21668 if(this.afterDragDrop){
21670 * An empty function by default, but provided so that you can perform a custom action
21671 * after a valid drag drop has occurred by providing an implementation.
21672 * @param {Roo.dd.DragDrop} target The drop target
21673 * @param {Event} e The event object
21674 * @param {String} id The id of the dropped element
21675 * @method afterDragDrop
21677 this.afterDragDrop(target, e, id);
21680 delete this.cachedTarget;
21684 * An empty function by default, but provided so that you can perform a custom action before the dragged
21685 * item is dropped onto the target and optionally cancel the onDragDrop.
21686 * @param {Roo.dd.DragDrop} target The drop target
21687 * @param {Event} e The event object
21688 * @param {String} id The id of the dragged element
21689 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
21691 beforeDragDrop : function(target, e, id){
21696 onValidDrop : function(target, e, id){
21698 if(this.afterValidDrop){
21700 * An empty function by default, but provided so that you can perform a custom action
21701 * after a valid drop has occurred by providing an implementation.
21702 * @param {Object} target The target DD
21703 * @param {Event} e The event object
21704 * @param {String} id The id of the dropped element
21705 * @method afterInvalidDrop
21707 this.afterValidDrop(target, e, id);
21712 getRepairXY : function(e, data){
21713 return this.el.getXY();
21717 onInvalidDrop : function(target, e, id){
21718 this.beforeInvalidDrop(target, e, id);
21719 if(this.cachedTarget){
21720 if(this.cachedTarget.isNotifyTarget){
21721 this.cachedTarget.notifyOut(this, e, this.dragData);
21723 this.cacheTarget = null;
21725 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
21727 if(this.afterInvalidDrop){
21729 * An empty function by default, but provided so that you can perform a custom action
21730 * after an invalid drop has occurred by providing an implementation.
21731 * @param {Event} e The event object
21732 * @param {String} id The id of the dropped element
21733 * @method afterInvalidDrop
21735 this.afterInvalidDrop(e, id);
21740 afterRepair : function(){
21742 this.el.highlight(this.hlColor || "c3daf9");
21744 this.dragging = false;
21748 * An empty function by default, but provided so that you can perform a custom action after an invalid
21749 * drop has occurred.
21750 * @param {Roo.dd.DragDrop} target The drop target
21751 * @param {Event} e The event object
21752 * @param {String} id The id of the dragged element
21753 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
21755 beforeInvalidDrop : function(target, e, id){
21760 handleMouseDown : function(e){
21761 if(this.dragging) {
21764 var data = this.getDragData(e);
21765 if(data && this.onBeforeDrag(data, e) !== false){
21766 this.dragData = data;
21768 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
21773 * An empty function by default, but provided so that you can perform a custom action before the initial
21774 * drag event begins and optionally cancel it.
21775 * @param {Object} data An object containing arbitrary data to be shared with drop targets
21776 * @param {Event} e The event object
21777 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
21779 onBeforeDrag : function(data, e){
21784 * An empty function by default, but provided so that you can perform a custom action once the initial
21785 * drag event has begun. The drag cannot be canceled from this function.
21786 * @param {Number} x The x position of the click on the dragged object
21787 * @param {Number} y The y position of the click on the dragged object
21789 onStartDrag : Roo.emptyFn,
21791 // private - YUI override
21792 startDrag : function(x, y){
21793 this.proxy.reset();
21794 this.dragging = true;
21795 this.proxy.update("");
21796 this.onInitDrag(x, y);
21801 onInitDrag : function(x, y){
21802 var clone = this.el.dom.cloneNode(true);
21803 clone.id = Roo.id(); // prevent duplicate ids
21804 this.proxy.update(clone);
21805 this.onStartDrag(x, y);
21810 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
21811 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
21813 getProxy : function(){
21818 * Hides the drag source's {@link Roo.dd.StatusProxy}
21820 hideProxy : function(){
21822 this.proxy.reset(true);
21823 this.dragging = false;
21827 triggerCacheRefresh : function(){
21828 Roo.dd.DDM.refreshCache(this.groups);
21831 // private - override to prevent hiding
21832 b4EndDrag: function(e) {
21835 // private - override to prevent moving
21836 endDrag : function(e){
21837 this.onEndDrag(this.dragData, e);
21841 onEndDrag : function(data, e){
21844 // private - pin to cursor
21845 autoOffset : function(x, y) {
21846 this.setDelta(-12, -20);
21850 * Ext JS Library 1.1.1
21851 * Copyright(c) 2006-2007, Ext JS, LLC.
21853 * Originally Released Under LGPL - original licence link has changed is not relivant.
21856 * <script type="text/javascript">
21861 * @class Roo.dd.DropTarget
21862 * @extends Roo.dd.DDTarget
21863 * A simple class that provides the basic implementation needed to make any element a drop target that can have
21864 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
21866 * @param {String/HTMLElement/Element} el The container element
21867 * @param {Object} config
21869 Roo.dd.DropTarget = function(el, config){
21870 this.el = Roo.get(el);
21872 var listeners = false; ;
21873 if (config && config.listeners) {
21874 listeners= config.listeners;
21875 delete config.listeners;
21877 Roo.apply(this, config);
21879 if(this.containerScroll){
21880 Roo.dd.ScrollManager.register(this.el);
21884 * @scope Roo.dd.DropTarget
21889 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
21890 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
21891 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
21893 * IMPORTANT : it should set this.overClass and this.dropAllowed
21895 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21896 * @param {Event} e The event
21897 * @param {Object} data An object containing arbitrary data supplied by the drag source
21903 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
21904 * This method will be called on every mouse movement while the drag source is over the drop target.
21905 * This default implementation simply returns the dropAllowed config value.
21907 * IMPORTANT : it should set this.dropAllowed
21909 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21910 * @param {Event} e The event
21911 * @param {Object} data An object containing arbitrary data supplied by the drag source
21917 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
21918 * out of the target without dropping. This default implementation simply removes the CSS class specified by
21919 * overClass (if any) from the drop element.
21921 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21922 * @param {Event} e The event
21923 * @param {Object} data An object containing arbitrary data supplied by the drag source
21929 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
21930 * been dropped on it. This method has no default implementation and returns false, so you must provide an
21931 * implementation that does something to process the drop event and returns true so that the drag source's
21932 * repair action does not run.
21934 * IMPORTANT : it should set this.success
21936 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
21937 * @param {Event} e The event
21938 * @param {Object} data An object containing arbitrary data supplied by the drag source
21944 Roo.dd.DropTarget.superclass.constructor.call( this,
21946 this.ddGroup || this.group,
21949 listeners : listeners || {}
21957 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
21959 * @cfg {String} overClass
21960 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
21963 * @cfg {String} ddGroup
21964 * The drag drop group to handle drop events for
21968 * @cfg {String} dropAllowed
21969 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
21971 dropAllowed : "x-dd-drop-ok",
21973 * @cfg {String} dropNotAllowed
21974 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
21976 dropNotAllowed : "x-dd-drop-nodrop",
21978 * @cfg {boolean} success
21979 * set this after drop listener..
21983 * @cfg {boolean|String} valid true/false or string (ok-add/ok-sub/ok/nodrop)
21984 * if the drop point is valid for over/enter..
21991 isNotifyTarget : true,
21996 notifyEnter : function(dd, e, data)
21999 this.fireEvent('enter', dd, e, data);
22000 if(this.overClass){
22001 this.el.addClass(this.overClass);
22003 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
22004 this.valid ? this.dropAllowed : this.dropNotAllowed
22011 notifyOver : function(dd, e, data)
22014 this.fireEvent('over', dd, e, data);
22015 return typeof(this.valid) == 'string' ? 'x-dd-drop-' + this.valid : (
22016 this.valid ? this.dropAllowed : this.dropNotAllowed
22023 notifyOut : function(dd, e, data)
22025 this.fireEvent('out', dd, e, data);
22026 if(this.overClass){
22027 this.el.removeClass(this.overClass);
22034 notifyDrop : function(dd, e, data)
22036 this.success = false;
22037 this.fireEvent('drop', dd, e, data);
22038 return this.success;
22042 * Ext JS Library 1.1.1
22043 * Copyright(c) 2006-2007, Ext JS, LLC.
22045 * Originally Released Under LGPL - original licence link has changed is not relivant.
22048 * <script type="text/javascript">
22053 * @class Roo.dd.DragZone
22054 * @extends Roo.dd.DragSource
22055 * This class provides a container DD instance that proxies for multiple child node sources.<br />
22056 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
22058 * @param {String/HTMLElement/Element} el The container element
22059 * @param {Object} config
22061 Roo.dd.DragZone = function(el, config){
22062 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
22063 if(this.containerScroll){
22064 Roo.dd.ScrollManager.register(this.el);
22068 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
22070 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
22071 * for auto scrolling during drag operations.
22074 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
22075 * method after a failed drop (defaults to "c3daf9" - light blue)
22079 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
22080 * for a valid target to drag based on the mouse down. Override this method
22081 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
22082 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
22083 * @param {EventObject} e The mouse down event
22084 * @return {Object} The dragData
22086 getDragData : function(e){
22087 return Roo.dd.Registry.getHandleFromEvent(e);
22091 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
22092 * this.dragData.ddel
22093 * @param {Number} x The x position of the click on the dragged object
22094 * @param {Number} y The y position of the click on the dragged object
22095 * @return {Boolean} true to continue the drag, false to cancel
22097 onInitDrag : function(x, y){
22098 this.proxy.update(this.dragData.ddel.cloneNode(true));
22099 this.onStartDrag(x, y);
22104 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
22106 afterRepair : function(){
22108 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
22110 this.dragging = false;
22114 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
22115 * the XY of this.dragData.ddel
22116 * @param {EventObject} e The mouse up event
22117 * @return {Array} The xy location (e.g. [100, 200])
22119 getRepairXY : function(e){
22120 return Roo.Element.fly(this.dragData.ddel).getXY();
22124 * Ext JS Library 1.1.1
22125 * Copyright(c) 2006-2007, Ext JS, LLC.
22127 * Originally Released Under LGPL - original licence link has changed is not relivant.
22130 * <script type="text/javascript">
22133 * @class Roo.dd.DropZone
22134 * @extends Roo.dd.DropTarget
22135 * This class provides a container DD instance that proxies for multiple child node targets.<br />
22136 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
22138 * @param {String/HTMLElement/Element} el The container element
22139 * @param {Object} config
22141 Roo.dd.DropZone = function(el, config){
22142 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
22145 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
22147 * Returns a custom data object associated with the DOM node that is the target of the event. By default
22148 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
22149 * provide your own custom lookup.
22150 * @param {Event} e The event
22151 * @return {Object} data The custom data
22153 getTargetFromEvent : function(e){
22154 return Roo.dd.Registry.getTargetFromEvent(e);
22158 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
22159 * that it has registered. This method has no default implementation and should be overridden to provide
22160 * node-specific processing if necessary.
22161 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22162 * {@link #getTargetFromEvent} for this node)
22163 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22164 * @param {Event} e The event
22165 * @param {Object} data An object containing arbitrary data supplied by the drag source
22167 onNodeEnter : function(n, dd, e, data){
22172 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
22173 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
22174 * overridden to provide the proper feedback.
22175 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22176 * {@link #getTargetFromEvent} for this node)
22177 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22178 * @param {Event} e The event
22179 * @param {Object} data An object containing arbitrary data supplied by the drag source
22180 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22181 * underlying {@link Roo.dd.StatusProxy} can be updated
22183 onNodeOver : function(n, dd, e, data){
22184 return this.dropAllowed;
22188 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
22189 * the drop node without dropping. This method has no default implementation and should be overridden to provide
22190 * node-specific processing if necessary.
22191 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22192 * {@link #getTargetFromEvent} for this node)
22193 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22194 * @param {Event} e The event
22195 * @param {Object} data An object containing arbitrary data supplied by the drag source
22197 onNodeOut : function(n, dd, e, data){
22202 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
22203 * the drop node. The default implementation returns false, so it should be overridden to provide the
22204 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
22205 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
22206 * {@link #getTargetFromEvent} for this node)
22207 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22208 * @param {Event} e The event
22209 * @param {Object} data An object containing arbitrary data supplied by the drag source
22210 * @return {Boolean} True if the drop was valid, else false
22212 onNodeDrop : function(n, dd, e, data){
22217 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
22218 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
22219 * it should be overridden to provide the proper feedback if necessary.
22220 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22221 * @param {Event} e The event
22222 * @param {Object} data An object containing arbitrary data supplied by the drag source
22223 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22224 * underlying {@link Roo.dd.StatusProxy} can be updated
22226 onContainerOver : function(dd, e, data){
22227 return this.dropNotAllowed;
22231 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
22232 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
22233 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
22234 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
22235 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22236 * @param {Event} e The event
22237 * @param {Object} data An object containing arbitrary data supplied by the drag source
22238 * @return {Boolean} True if the drop was valid, else false
22240 onContainerDrop : function(dd, e, data){
22245 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
22246 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
22247 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
22248 * you should override this method and provide a custom implementation.
22249 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22250 * @param {Event} e The event
22251 * @param {Object} data An object containing arbitrary data supplied by the drag source
22252 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22253 * underlying {@link Roo.dd.StatusProxy} can be updated
22255 notifyEnter : function(dd, e, data){
22256 return this.dropNotAllowed;
22260 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
22261 * This method will be called on every mouse movement while the drag source is over the drop zone.
22262 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
22263 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
22264 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
22265 * registered node, it will call {@link #onContainerOver}.
22266 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22267 * @param {Event} e The event
22268 * @param {Object} data An object containing arbitrary data supplied by the drag source
22269 * @return {String} status The CSS class that communicates the drop status back to the source so that the
22270 * underlying {@link Roo.dd.StatusProxy} can be updated
22272 notifyOver : function(dd, e, data){
22273 var n = this.getTargetFromEvent(e);
22274 if(!n){ // not over valid drop target
22275 if(this.lastOverNode){
22276 this.onNodeOut(this.lastOverNode, dd, e, data);
22277 this.lastOverNode = null;
22279 return this.onContainerOver(dd, e, data);
22281 if(this.lastOverNode != n){
22282 if(this.lastOverNode){
22283 this.onNodeOut(this.lastOverNode, dd, e, data);
22285 this.onNodeEnter(n, dd, e, data);
22286 this.lastOverNode = n;
22288 return this.onNodeOver(n, dd, e, data);
22292 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
22293 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
22294 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
22295 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
22296 * @param {Event} e The event
22297 * @param {Object} data An object containing arbitrary data supplied by the drag zone
22299 notifyOut : function(dd, e, data){
22300 if(this.lastOverNode){
22301 this.onNodeOut(this.lastOverNode, dd, e, data);
22302 this.lastOverNode = null;
22307 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
22308 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
22309 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
22310 * otherwise it will call {@link #onContainerDrop}.
22311 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
22312 * @param {Event} e The event
22313 * @param {Object} data An object containing arbitrary data supplied by the drag source
22314 * @return {Boolean} True if the drop was valid, else false
22316 notifyDrop : function(dd, e, data){
22317 if(this.lastOverNode){
22318 this.onNodeOut(this.lastOverNode, dd, e, data);
22319 this.lastOverNode = null;
22321 var n = this.getTargetFromEvent(e);
22323 this.onNodeDrop(n, dd, e, data) :
22324 this.onContainerDrop(dd, e, data);
22328 triggerCacheRefresh : function(){
22329 Roo.dd.DDM.refreshCache(this.groups);