document.execCommand("BackgroundImageCache", false, true);
}catch(e){}
}
-
+
Roo.apply(Roo, {
/**
* True if the browser is in strict mode
* @type Boolean
*/
isReady : false,
+ /**
+ * Turn on debugging output (currently only the factory uses this)
+ * @type Boolean
+ */
+
+ debug: false,
/**
* True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
return c;
}
if (ns[c.xtype]) {
- if (Roo.debug) console.log("Roo.Factory(" + c.xtype + ")");
+ if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
var ret = new ns[c.xtype](c);
ret.xns = false;
return ret;
c.xns = false; // prevent recursion..
return c;
},
-
+ /**
+ * Logs to console if it can.
+ *
+ * @param {String|Object} string
+ * @method log
+ */
+ log : function(s)
+ {
+ if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
+ return; // alerT?
+ }
+ console.log(s);
+
+ },
/**
* 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.
* @param {Object} o
}
var buf = [];
for(var key in o){
- var ov = o[key], k = encodeURIComponent(key);
+ var ov = o[key], k = Roo.encodeURIComponent(key);
var type = typeof ov;
if(type == 'undefined'){
buf.push(k, "=&");
}else if(type != "function" && type != "object"){
- buf.push(k, "=", encodeURIComponent(ov), "&");
+ buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
}else if(ov instanceof Array){
if (ov.length) {
for(var i = 0, len = ov.length; i < len; i++) {
- buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
+ buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
}
} else {
buf.push(k, "=&");
}
buf.pop();
return buf.join("");
+ },
+ /**
+ * Safe version of encodeURIComponent
+ * @param {String} data
+ * @return {String}
+ */
+
+ encodeURIComponent : function (data)
+ {
+ try {
+ return encodeURIComponent(data);
+ } catch(e) {} // should be an uri encode error.
+
+ if (data == '' || data == null){
+ return '';
+ }
+ // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
+ function nibble_to_hex(nibble){
+ var chars = '0123456789ABCDEF';
+ return chars.charAt(nibble);
+ }
+ data = data.toString();
+ var buffer = '';
+ for(var i=0; i<data.length; i++){
+ var c = data.charCodeAt(i);
+ var bs = new Array();
+ if (c > 0x10000){
+ // 4 bytes
+ bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
+ bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
+ bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
+ bs[3] = 0x80 | (c & 0x3F);
+ }else if (c > 0x800){
+ // 3 bytes
+ bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
+ bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
+ bs[2] = 0x80 | (c & 0x3F);
+ }else if (c > 0x80){
+ // 2 bytes
+ bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
+ bs[1] = 0x80 | (c & 0x3F);
+ }else{
+ // 1 byte
+ bs[0] = c;
+ }
+ for(var j=0; j<bs.length; j++){
+ var b = bs[j];
+ var hex = nibble_to_hex((b & 0xF0) >>> 4)
+ + nibble_to_hex(b &0x0F);
+ buffer += '%'+hex;
+ }
+ }
+ return buffer;
+
},
/**
* you may want to set this to true.
* @type Boolean
*/
- useShims : ((isIE && !isIE7) || (isGecko && isMac))
+ useShims : ((isIE && !isIE7) || (isGecko && isMac)),
+
+
+
+ /**
+ * Selects a single element as a Roo Element
+ * This is about as close as you can get to jQuery's $('do crazy stuff')
+ * @param {String} selector The selector/xpath query
+ * @param {Node} root (optional) The start of the query (defaults to document).
+ * @return {Roo.Element}
+ */
+ selectNode : function(selector, root)
+ {
+ var node = Roo.DomQuery.selectNode(selector,root);
+ return node ? Roo.get(node) : new Roo.Element(false);
+ }
+
});
i 05 Minutes with leading zeros
s 01 Seconds, with leading zeros
O -0600 Difference to Greenwich time (GMT) in hours
+ P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
T CST Timezone setting of the machine running the code
Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
</pre>
return "String.leftPad(this.getSeconds(), 2, '0') + ";
case "O":
return "this.getGMTOffset() + ";
+ case "P":
+ return "this.getGMTColonOffset() + ";
case "T":
return "this.getTimezone() + ";
case "Z":
" (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
].join(""),
s:"([+\-]\\d{4})"};
+ case "P":
+ return {g:1,
+ c:[
+ "o = results[", currentGroup, "];\n",
+ "var sn = o.substring(0,1);\n",
+ "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
+ "var mn = o.substring(4,6) % 60;\n",
+ "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
+ " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
+ ].join(""),
+ s:"([+\-]\\d{4})"};
case "T":
return {g:0,
c:null,
+ String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
};
+/**
+ * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
+ * @return {String} 2-characters representing hours and 2-characters representing minutes
+ * seperated by a colon and prefixed with + or - (e.g. '-06:00')
+ */
+Date.prototype.getGMTColonOffset = function() {
+ return (this.getTimezoneOffset() > 0 ? "-" : "+")
+ + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
+ + ":"
+ + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
+}
+
/**
* Get the numeric day number of the year, adjusted for leap year.
* @return {Number} 0 through 364 (365 in leap years)
break;
}
return d;
-};/*
+};
+/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
*/
(function() {
-
+ /**
+ * @class Roo.lib.Ajax
+ *
+ */
Roo.lib.Ajax = {
+ /**
+ * @static
+ */
request : function(method, uri, cb, data, options) {
if(options){
var hs = options.headers;
for (var j = 0; j < el.options.length; j++) {
if (el.options[j].selected) {
if (Roo.isIE) {
- data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
+ data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
}
else {
- data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
+ data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
}
}
}
case 'radio':
case 'checkbox':
if (el.checked) {
- data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
+ data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
}
break;
case 'file':
break;
case 'submit':
if(hasSubmit == false) {
- data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
+ data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
hasSubmit = true;
}
break;
default:
- data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
+ data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
break;
}
}
* Fork - LGPL
* <script type="text/javascript">
*/
-
+
+
+// nasty IE9 hack - what a pile of crap that is..
+
+ if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
+ Range.prototype.createContextualFragment = function (html) {
+ var doc = window.document;
+ var container = doc.createElement("div");
+ container.innerHTML = html;
+ var frag = doc.createDocumentFragment(), n;
+ while ((n = container.firstChild)) {
+ frag.appendChild(n);
+ }
+ return frag;
+ };
+}
/**
* @class Roo.DomHelper
* For a list of available format functions, see {@link Roo.util.Format}.<br />
* Usage:
<pre><code>
-var t = new Roo.Template(
- '<div name="{id}">',
- '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
- '</div>'
-);
+var t = new Roo.Template({
+ html : '<div name="{id}">' +
+ '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
+ '</div>',
+ myformat: function (value, allValues) {
+ return 'XX' + value;
+ }
+});
t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
</code></pre>
* For more information see this blog post with examples: <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">DomHelper - Create Elements using DOM, HTML fragments and Templates</a>.
* @constructor
-* @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
+* @param {Object} cfg - Configuration object.
*/
-Roo.Template = function(html){
- if(html instanceof Array){
- html = html.join("");
+Roo.Template = function(cfg){
+ // BC!
+ if(cfg instanceof Array){
+ cfg = cfg.join("");
}else if(arguments.length > 1){
- html = Array.prototype.join.call(arguments, "");
+ cfg = Array.prototype.join.call(arguments, "");
+ }
+
+
+ if (typeof(cfg) == 'object') {
+ Roo.apply(this,cfg)
+ } else {
+ // bc
+ this.html = cfg;
}
- /**@private*/
- this.html = html;
+
};
Roo.Template.prototype = {
+
+ /**
+ * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
+ */
+ html : '',
/**
* Returns an HTML fragment of this template with the specified values applied.
* @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'})
* @return {String} The HTML fragment
*/
applyTemplate : function(values){
- if(this.compiled){
- return this.compiled(values);
- }
- var useF = this.disableFormats !== true;
- var fm = Roo.util.Format, tpl = this;
- var fn = function(m, name, format, args){
- if(format && useF){
- if(format.substr(0, 5) == "this."){
- return tpl.call(format.substr(5), values[name], values);
- }else{
- if(args){
- // quoted values are required for strings in compiled templates,
- // but for non compiled we need to strip them
- // quoted reversed for jsmin
- var re = /^\s*['"](.*)["']\s*$/;
- args = args.split(',');
- for(var i = 0, len = args.length; i < len; i++){
- args[i] = args[i].replace(re, "$1");
- }
- args = [values[name]].concat(args);
+ try {
+
+ if(this.compiled){
+ return this.compiled(values);
+ }
+ var useF = this.disableFormats !== true;
+ var fm = Roo.util.Format, tpl = this;
+ var fn = function(m, name, format, args){
+ if(format && useF){
+ if(format.substr(0, 5) == "this."){
+ return tpl.call(format.substr(5), values[name], values);
}else{
- args = [values[name]];
+ if(args){
+ // quoted values are required for strings in compiled templates,
+ // but for non compiled we need to strip them
+ // quoted reversed for jsmin
+ var re = /^\s*['"](.*)["']\s*$/;
+ args = args.split(',');
+ for(var i = 0, len = args.length; i < len; i++){
+ args[i] = args[i].replace(re, "$1");
+ }
+ args = [values[name]].concat(args);
+ }else{
+ args = [values[name]];
+ }
+ return fm[format].apply(fm, args);
}
- return fm[format].apply(fm, args);
+ }else{
+ return values[name] !== undefined ? values[name] : "";
}
- }else{
- return values[name] !== undefined ? values[name] : "";
- }
- };
- return this.html.replace(this.re, fn);
+ };
+ return this.html.replace(this.re, fn);
+ } catch (e) {
+ Roo.log(e);
+ throw e;
+ }
+
},
/**
*/
setStyle : function(prop, value){
if(typeof prop == "string"){
+
+ if (prop == 'float') {
+ this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
+ return this;
+ }
+
var camel;
if(!(camel = propCache[prop])){
camel = propCache[prop] = prop.replace(camelRe, camelFn);
}
+
if(camel == 'opacity') {
this.setOpacity(value);
}else{
* @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
*/
addListener : function(eventName, fn, scope, options){
- Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
+ if (this.dom) {
+ Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
+ }
},
/**
* @param {String} msgCls (optional) A css class to apply to the msg element
* @return {Element} The mask element
*/
- mask : function(msg, msgCls){
+ mask : function(msg, msgCls)
+ {
if(this.getStyle("position") == "static"){
this.setStyle("position", "relative");
}
}
this.addClass("x-masked");
this._mask.setDisplayed(true);
+
+ // we wander
+ var z = 0;
+ var dom = this.dom
+ while (dom && dom.style) {
+ if (!isNaN(parseInt(dom.style.zIndex))) {
+ z = Math.max(z, parseInt(dom.style.zIndex));
+ }
+ dom = dom.parentNode;
+ }
+ // if we are masking the body - then it hides everything..
+ if (this.dom == document.body) {
+ z = 1000000;
+ this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
+ this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
+ }
+
if(typeof msg == 'string'){
if(!this._maskMsg){
this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
mm.dom.firstChild.innerHTML = msg;
mm.setDisplayed(true);
mm.center(this);
+ mm.setStyle('z-index', z + 102);
}
if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
this._mask.setHeight(this.getHeight());
}
+ this._mask.setStyle('z-index', z + 100);
+
return this._mask;
},
*/
/**
+ * Global Ajax request class.
+ *
* @class Roo.Ajax
* @extends Roo.data.Connection
- * Global Ajax request class.
- *
- * @instanceOf Roo.data.Connection
+ * @static
+ *
+ * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
+ * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
+ * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
+ * @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)
+ * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
+ * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
+ * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
*/
Roo.Ajax = new Roo.data.Connection({
// fix up the docs
-
/**
- * fix up scoping
* @scope Roo.Ajax
- */
-
- /**
- * @cfg {String} url @hide
- */
- /**
- * @cfg {Object} extraParams @hide
- */
- /**
- * @cfg {Object} defaultHeaders @hide
- */
- /**
- * @cfg {String} method (Optional) @hide
- */
- /**
- * @cfg {Number} timeout (Optional) @hide
- */
- /**
- * @cfg {Boolean} autoAbort (Optional) @hide
- */
-
- /**
- * @cfg {Boolean} disableCaching (Optional) @hide
- */
-
- /**
- * @property disableCaching
- * True to add a unique cache-buster param to GET requests. (defaults to true)
- * @type Boolean
- */
- /**
- * @property url
- * The default URL to be used for requests to the server. (defaults to undefined)
- * @type String
- */
- /**
- * @property extraParams
- * An object containing properties which are used as
- * extra parameters to each request made by this object. (defaults to undefined)
- * @type Object
- */
- /**
- * @property defaultHeaders
- * An object containing request headers which are added to each request made by this object. (defaults to undefined)
- * @type Object
- */
- /**
- * @property method
- * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
- * @type String
- */
- /**
- * @property timeout
- * The timeout in milliseconds to be used for requests. (defaults to 30000)
- * @type Number
- */
-
- /**
- * @property autoAbort
- * Whether a new request should abort any pending requests. (defaults to false)
- * @type Boolean
+ * @type {Boolear}
*/
autoAbort : false,
/**
* Serialize the passed form into a url encoded string
+ * @scope Roo.Ajax
* @param {String/HTMLElement} form
* @return {String}
*/
this.fireEvent("add", this.length-1, o, key);
return o;
},
-
+
/**
* MixedCollection has a generic way to fetch keys if you implement getKey.
<pre><code>
* @param {Mixed} o The variable to encode
* @return {String} The JSON string
*/
- this.encode = function(o){
+ this.encode = function(o)
+ {
+ // should this be extended to fully wrap stringify..
+
if(typeof o == "undefined" || o === null){
return "null";
}else if(o instanceof Array){
* @return {Object} The resulting object
*/
this.decode = function(json){
- /**
- * eval:var:json
- */
- return eval("(" + json + ')');
+
+ return /** eval:var:json */ eval("(" + json + ')');
};
})();
/**
* Shorthand for {@link Roo.util.JSON#encode}
* @member Roo encode
* @method */
-Roo.encode = Roo.util.JSON.encode;
+Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
/**
* Shorthand for {@link Roo.util.JSON#decode}
* @member Roo decode
* @method */
-Roo.decode = Roo.util.JSON.decode;
+Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
/*
* Based on:
* Ext JS Library 1.1.1
}
},
+
+ /**
+ * safer version of Math.toFixed..??/
+ * @param {Number/String} value The numeric value to format
+ * @param {Number/String} value Decimal places
+ * @return {String} The formatted currency string
+ */
+ toFixed : function(v, n)
+ {
+ // why not use to fixed - precision is buggered???
+ if (!n) {
+ return Math.round(v-0);
+ }
+ var fact = Math.pow(10,n+1);
+ v = (Math.round((v-0)*fact))/fact;
+ var z = (''+fact).substring(2);
+ if (v == Math.floor(v)) {
+ return Math.floor(v) + '.' + z;
+ }
+
+ // now just padd decimals..
+ var ps = String(v).split('.');
+ var fd = (ps[1] + z);
+ var r = fd.substring(0,n);
+ var rm = fd.substring(n);
+ if (rm < 5) {
+ return ps[0] + '.' + r;
+ }
+ r*=1; // turn it into a number;
+ r++;
+ if (String(r).length != n) {
+ ps[0]*=1;
+ ps[0]++;
+ r = String(r).substring(1); // chop the end off.
+ }
+
+ return ps[0] + '.' + r;
+
+ },
+
/**
* Format a number as US currency
* @param {Number/String} value The numeric value to format
}
return "$" + whole + sub ;
},
-
+
/**
* Parse a value into a formatted date using the specified format pattern.
* @param {Mixed} value The value to format
/**
* Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
* tag and appended to the HEAD of the document.
- * @param {String} cssText The text containing the css rules
+ * @param {String|Object} cssText The text containing the css rules
* @param {String} id An id to add to the stylesheet for later removal
* @return {StyleSheet}
*/
- createStyleSheet : function(cssText, id){
- var ss;
- var head = doc.getElementsByTagName("head")[0];
- var rules = doc.createElement("style");
- rules.setAttribute("type", "text/css");
- if(id){
- rules.setAttribute("id", id);
- }
+ createStyleSheet : function(cssText, id){
+ var ss;
+ var head = doc.getElementsByTagName("head")[0];
+ var nrules = doc.createElement("style");
+ nrules.setAttribute("type", "text/css");
+ if(id){
+ nrules.setAttribute("id", id);
+ }
+ if (typeof(cssText) != 'string') {
+ // support object maps..
+ // not sure if this a good idea..
+ // perhaps it should be merged with the general css handling
+ // and handle js style props.
+ var cssTextNew = [];
+ for(var n in cssText) {
+ var citems = [];
+ for(var k in cssText[n]) {
+ citems.push( k + ' : ' +cssText[n][k] + ';' );
+ }
+ cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
+
+ }
+ cssText = cssTextNew.join("\n");
+
+ }
+
+
if(Roo.isIE){
- head.appendChild(rules);
- ss = rules.styleSheet;
+ head.appendChild(nrules);
+ ss = nrules.styleSheet;
ss.cssText = cssText;
}else{
try{
- rules.appendChild(doc.createTextNode(cssText));
+ nrules.appendChild(doc.createTextNode(cssText));
}catch(e){
- rules.cssText = cssText;
+ nrules.cssText = cssText;
}
- head.appendChild(rules);
- ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
+ head.appendChild(nrules);
+ ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
}
this.cacheStyleSheet(ss);
return ss;
},
// private
- cacheStyleSheet : function(ss){
+ cacheStyleSheet : function(stylesheet){
if(!rules){
rules = {};
}
try{// try catch for cross domain access issue
- var ssRules = ss.cssRules || ss.rules;
+ var ssRules = stylesheet.cssRules || stylesheet.rules;
for(var j = ssRules.length-1; j >= 0; --j){
rules[ssRules[j].selectorText] = ssRules[j];
}
return false;
}
};
-}();
\ No newline at end of file
+}();/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+
+
+/**
+ * @class Roo.util.ClickRepeater
+ * @extends Roo.util.Observable
+ *
+ * A wrapper class which can be applied to any element. Fires a "click" event while the
+ * mouse is pressed. The interval between firings may be specified in the config but
+ * defaults to 10 milliseconds.
+ *
+ * Optionally, a CSS class may be applied to the element during the time it is pressed.
+ *
+ * @cfg {String/HTMLElement/Element} el The element to act as a button.
+ * @cfg {Number} delay The initial delay before the repeating event begins firing.
+ * Similar to an autorepeat key delay.
+ * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
+ * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
+ * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
+ * "interval" and "delay" are ignored. "immediate" is honored.
+ * @cfg {Boolean} preventDefault True to prevent the default click event
+ * @cfg {Boolean} stopDefault True to stop the default click event
+ *
+ * @history
+ * 2007-02-02 jvs Original code contributed by Nige "Animal" White
+ * 2007-02-02 jvs Renamed to ClickRepeater
+ * 2007-02-03 jvs Modifications for FF Mac and Safari
+ *
+ * @constructor
+ * @param {String/HTMLElement/Element} el The element to listen on
+ * @param {Object} config
+ **/
+Roo.util.ClickRepeater = function(el, config)
+{
+ this.el = Roo.get(el);
+ this.el.unselectable();
+
+ Roo.apply(this, config);
+
+ this.addEvents({
+ /**
+ * @event mousedown
+ * Fires when the mouse button is depressed.
+ * @param {Roo.util.ClickRepeater} this
+ */
+ "mousedown" : true,
+ /**
+ * @event click
+ * Fires on a specified interval during the time the element is pressed.
+ * @param {Roo.util.ClickRepeater} this
+ */
+ "click" : true,
+ /**
+ * @event mouseup
+ * Fires when the mouse key is released.
+ * @param {Roo.util.ClickRepeater} this
+ */
+ "mouseup" : true
+ });
+
+ this.el.on("mousedown", this.handleMouseDown, this);
+ if(this.preventDefault || this.stopDefault){
+ this.el.on("click", function(e){
+ if(this.preventDefault){
+ e.preventDefault();
+ }
+ if(this.stopDefault){
+ e.stopEvent();
+ }
+ }, this);
+ }
+
+ // allow inline handler
+ if(this.handler){
+ this.on("click", this.handler, this.scope || this);
+ }
+
+ Roo.util.ClickRepeater.superclass.constructor.call(this);
+};
+
+Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
+ interval : 20,
+ delay: 250,
+ preventDefault : true,
+ stopDefault : false,
+ timer : 0,
+
+ // private
+ handleMouseDown : function(){
+ clearTimeout(this.timer);
+ this.el.blur();
+ if(this.pressClass){
+ this.el.addClass(this.pressClass);
+ }
+ this.mousedownTime = new Date();
+
+ Roo.get(document).on("mouseup", this.handleMouseUp, this);
+ this.el.on("mouseout", this.handleMouseOut, this);
+
+ this.fireEvent("mousedown", this);
+ this.fireEvent("click", this);
+
+ this.timer = this.click.defer(this.delay || this.interval, this);
+ },
+
+ // private
+ click : function(){
+ this.fireEvent("click", this);
+ this.timer = this.click.defer(this.getInterval(), this);
+ },
+
+ // private
+ getInterval: function(){
+ if(!this.accelerate){
+ return this.interval;
+ }
+ var pressTime = this.mousedownTime.getElapsed();
+ if(pressTime < 500){
+ return 400;
+ }else if(pressTime < 1700){
+ return 320;
+ }else if(pressTime < 2600){
+ return 250;
+ }else if(pressTime < 3500){
+ return 180;
+ }else if(pressTime < 4400){
+ return 140;
+ }else if(pressTime < 5300){
+ return 80;
+ }else if(pressTime < 6200){
+ return 50;
+ }else{
+ return 10;
+ }
+ },
+
+ // private
+ handleMouseOut : function(){
+ clearTimeout(this.timer);
+ if(this.pressClass){
+ this.el.removeClass(this.pressClass);
+ }
+ this.el.on("mouseover", this.handleMouseReturn, this);
+ },
+
+ // private
+ handleMouseReturn : function(){
+ this.el.un("mouseover", this.handleMouseReturn);
+ if(this.pressClass){
+ this.el.addClass(this.pressClass);
+ }
+ this.click();
+ },
+
+ // private
+ handleMouseUp : function(){
+ clearTimeout(this.timer);
+ this.el.un("mouseover", this.handleMouseReturn);
+ this.el.un("mouseout", this.handleMouseOut);
+ Roo.get(document).un("mouseup", this.handleMouseUp);
+ this.el.removeClass(this.pressClass);
+ this.fireEvent("mouseup", this);
+ }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+
+/**
+ * @class Roo.KeyNav
+ * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
+ * navigation keys to function calls that will get called when the keys are pressed, providing an easy
+ * way to implement custom navigation schemes for any UI component.</p>
+ * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
+ * pageUp, pageDown, del, home, end. Usage:</p>
+ <pre><code>
+var nav = new Roo.KeyNav("my-element", {
+ "left" : function(e){
+ this.moveLeft(e.ctrlKey);
+ },
+ "right" : function(e){
+ this.moveRight(e.ctrlKey);
+ },
+ "enter" : function(e){
+ this.save();
+ },
+ scope : this
+});
+</code></pre>
+ * @constructor
+ * @param {String/HTMLElement/Roo.Element} el The element to bind to
+ * @param {Object} config The config
+ */
+Roo.KeyNav = function(el, config){
+ this.el = Roo.get(el);
+ Roo.apply(this, config);
+ if(!this.disabled){
+ this.disabled = true;
+ this.enable();
+ }
+};
+
+Roo.KeyNav.prototype = {
+ /**
+ * @cfg {Boolean} disabled
+ * True to disable this KeyNav instance (defaults to false)
+ */
+ disabled : false,
+ /**
+ * @cfg {String} defaultEventAction
+ * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
+ * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
+ * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
+ */
+ defaultEventAction: "stopEvent",
+ /**
+ * @cfg {Boolean} forceKeyDown
+ * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
+ * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
+ * handle keydown instead of keypress.
+ */
+ forceKeyDown : false,
+
+ // private
+ prepareEvent : function(e){
+ var k = e.getKey();
+ var h = this.keyToHandler[k];
+ //if(h && this[h]){
+ // e.stopPropagation();
+ //}
+ if(Roo.isSafari && h && k >= 37 && k <= 40){
+ e.stopEvent();
+ }
+ },
+
+ // private
+ relay : function(e){
+ var k = e.getKey();
+ var h = this.keyToHandler[k];
+ if(h && this[h]){
+ if(this.doRelay(e, this[h], h) !== true){
+ e[this.defaultEventAction]();
+ }
+ }
+ },
+
+ // private
+ doRelay : function(e, h, hname){
+ return h.call(this.scope || this, e);
+ },
+
+ // possible handlers
+ enter : false,
+ left : false,
+ right : false,
+ up : false,
+ down : false,
+ tab : false,
+ esc : false,
+ pageUp : false,
+ pageDown : false,
+ del : false,
+ home : false,
+ end : false,
+
+ // quick lookup hash
+ keyToHandler : {
+ 37 : "left",
+ 39 : "right",
+ 38 : "up",
+ 40 : "down",
+ 33 : "pageUp",
+ 34 : "pageDown",
+ 46 : "del",
+ 36 : "home",
+ 35 : "end",
+ 13 : "enter",
+ 27 : "esc",
+ 9 : "tab"
+ },
+
+ /**
+ * Enable this KeyNav
+ */
+ enable: function(){
+ if(this.disabled){
+ // ie won't do special keys on keypress, no one else will repeat keys with keydown
+ // the EventObject will normalize Safari automatically
+ if(this.forceKeyDown || Roo.isIE || Roo.isAir){
+ this.el.on("keydown", this.relay, this);
+ }else{
+ this.el.on("keydown", this.prepareEvent, this);
+ this.el.on("keypress", this.relay, this);
+ }
+ this.disabled = false;
+ }
+ },
+
+ /**
+ * Disable this KeyNav
+ */
+ disable: function(){
+ if(!this.disabled){
+ if(this.forceKeyDown || Roo.isIE || Roo.isAir){
+ this.el.un("keydown", this.relay);
+ }else{
+ this.el.un("keydown", this.prepareEvent);
+ this.el.un("keypress", this.relay);
+ }
+ this.disabled = true;
+ }
+ }
+};/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+
+/**
+ * @class Roo.KeyMap
+ * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
+ * The constructor accepts the same config object as defined by {@link #addBinding}.
+ * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
+ * combination it will call the function with this signature (if the match is a multi-key
+ * combination the callback will still be called only once): (String key, Roo.EventObject e)
+ * A KeyMap can also handle a string representation of keys.<br />
+ * Usage:
+ <pre><code>
+// map one key by key code
+var map = new Roo.KeyMap("my-element", {
+ key: 13, // or Roo.EventObject.ENTER
+ fn: myHandler,
+ scope: myObject
+});
+
+// map multiple keys to one action by string
+var map = new Roo.KeyMap("my-element", {
+ key: "a\r\n\t",
+ fn: myHandler,
+ scope: myObject
+});
+
+// map multiple keys to multiple actions by strings and array of codes
+var map = new Roo.KeyMap("my-element", [
+ {
+ key: [10,13],
+ fn: function(){ alert("Return was pressed"); }
+ }, {
+ key: "abc",
+ fn: function(){ alert('a, b or c was pressed'); }
+ }, {
+ key: "\t",
+ ctrl:true,
+ shift:true,
+ fn: function(){ alert('Control + shift + tab was pressed.'); }
+ }
+]);
+</code></pre>
+ * <b>Note: A KeyMap starts enabled</b>
+ * @constructor
+ * @param {String/HTMLElement/Roo.Element} el The element to bind to
+ * @param {Object} config The config (see {@link #addBinding})
+ * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
+ */
+Roo.KeyMap = function(el, config, eventName){
+ this.el = Roo.get(el);
+ this.eventName = eventName || "keydown";
+ this.bindings = [];
+ if(config){
+ this.addBinding(config);
+ }
+ this.enable();
+};
+
+Roo.KeyMap.prototype = {
+ /**
+ * True to stop the event from bubbling and prevent the default browser action if the
+ * key was handled by the KeyMap (defaults to false)
+ * @type Boolean
+ */
+ stopEvent : false,
+
+ /**
+ * Add a new binding to this KeyMap. The following config object properties are supported:
+ * <pre>
+Property Type Description
+---------- --------------- ----------------------------------------------------------------------
+key String/Array A single keycode or an array of keycodes to handle
+shift Boolean True to handle key only when shift is pressed (defaults to false)
+ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
+alt Boolean True to handle key only when alt is pressed (defaults to false)
+fn Function The function to call when KeyMap finds the expected key combination
+scope Object The scope of the callback function
+</pre>
+ *
+ * Usage:
+ * <pre><code>
+// Create a KeyMap
+var map = new Roo.KeyMap(document, {
+ key: Roo.EventObject.ENTER,
+ fn: handleKey,
+ scope: this
+});
+
+//Add a new binding to the existing KeyMap later
+map.addBinding({
+ key: 'abc',
+ shift: true,
+ fn: handleKey,
+ scope: this
+});
+</code></pre>
+ * @param {Object/Array} config A single KeyMap config or an array of configs
+ */
+ addBinding : function(config){
+ if(config instanceof Array){
+ for(var i = 0, len = config.length; i < len; i++){
+ this.addBinding(config[i]);
+ }
+ return;
+ }
+ var keyCode = config.key,
+ shift = config.shift,
+ ctrl = config.ctrl,
+ alt = config.alt,
+ fn = config.fn,
+ scope = config.scope;
+ if(typeof keyCode == "string"){
+ var ks = [];
+ var keyString = keyCode.toUpperCase();
+ for(var j = 0, len = keyString.length; j < len; j++){
+ ks.push(keyString.charCodeAt(j));
+ }
+ keyCode = ks;
+ }
+ var keyArray = keyCode instanceof Array;
+ var handler = function(e){
+ if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
+ var k = e.getKey();
+ if(keyArray){
+ for(var i = 0, len = keyCode.length; i < len; i++){
+ if(keyCode[i] == k){
+ if(this.stopEvent){
+ e.stopEvent();
+ }
+ fn.call(scope || window, k, e);
+ return;
+ }
+ }
+ }else{
+ if(k == keyCode){
+ if(this.stopEvent){
+ e.stopEvent();
+ }
+ fn.call(scope || window, k, e);
+ }
+ }
+ }
+ };
+ this.bindings.push(handler);
+ },
+
+ /**
+ * Shorthand for adding a single key listener
+ * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
+ * following options:
+ * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
+ * @param {Function} fn The function to call
+ * @param {Object} scope (optional) The scope of the function
+ */
+ on : function(key, fn, scope){
+ var keyCode, shift, ctrl, alt;
+ if(typeof key == "object" && !(key instanceof Array)){
+ keyCode = key.key;
+ shift = key.shift;
+ ctrl = key.ctrl;
+ alt = key.alt;
+ }else{
+ keyCode = key;
+ }
+ this.addBinding({
+ key: keyCode,
+ shift: shift,
+ ctrl: ctrl,
+ alt: alt,
+ fn: fn,
+ scope: scope
+ })
+ },
+
+ // private
+ handleKeyDown : function(e){
+ if(this.enabled){ //just in case
+ var b = this.bindings;
+ for(var i = 0, len = b.length; i < len; i++){
+ b[i].call(this, e);
+ }
+ }
+ },
+
+ /**
+ * Returns true if this KeyMap is enabled
+ * @return {Boolean}
+ */
+ isEnabled : function(){
+ return this.enabled;
+ },
+
+ /**
+ * Enables this KeyMap
+ */
+ enable: function(){
+ if(!this.enabled){
+ this.el.on(this.eventName, this.handleKeyDown, this);
+ this.enabled = true;
+ }
+ },
+
+ /**
+ * Disable this KeyMap
+ */
+ disable: function(){
+ if(this.enabled){
+ this.el.removeListener(this.eventName, this.handleKeyDown, this);
+ this.enabled = false;
+ }
+ }
+};/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+
+/**
+ * @class Roo.util.TextMetrics
+ * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
+ * wide, in pixels, a given block of text will be.
+ * @singleton
+ */
+Roo.util.TextMetrics = function(){
+ var shared;
+ return {
+ /**
+ * Measures the size of the specified text
+ * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
+ * that can affect the size of the rendered text
+ * @param {String} text The text to measure
+ * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
+ * in order to accurately measure the text height
+ * @return {Object} An object containing the text's size {width: (width), height: (height)}
+ */
+ measure : function(el, text, fixedWidth){
+ if(!shared){
+ shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
+ }
+ shared.bind(el);
+ shared.setFixedWidth(fixedWidth || 'auto');
+ return shared.getSize(text);
+ },
+
+ /**
+ * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
+ * the overhead of multiple calls to initialize the style properties on each measurement.
+ * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
+ * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
+ * in order to accurately measure the text height
+ * @return {Roo.util.TextMetrics.Instance} instance The new instance
+ */
+ createInstance : function(el, fixedWidth){
+ return Roo.util.TextMetrics.Instance(el, fixedWidth);
+ }
+ };
+}();
+
+
+
+Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
+ var ml = new Roo.Element(document.createElement('div'));
+ document.body.appendChild(ml.dom);
+ ml.position('absolute');
+ ml.setLeftTop(-1000, -1000);
+ ml.hide();
+
+ if(fixedWidth){
+ ml.setWidth(fixedWidth);
+ }
+
+ var instance = {
+ /**
+ * Returns the size of the specified text based on the internal element's style and width properties
+ * @memberOf Roo.util.TextMetrics.Instance#
+ * @param {String} text The text to measure
+ * @return {Object} An object containing the text's size {width: (width), height: (height)}
+ */
+ getSize : function(text){
+ ml.update(text);
+ var s = ml.getSize();
+ ml.update('');
+ return s;
+ },
+
+ /**
+ * Binds this TextMetrics instance to an element from which to copy existing CSS styles
+ * that can affect the size of the rendered text
+ * @memberOf Roo.util.TextMetrics.Instance#
+ * @param {String/HTMLElement} el The element, dom node or id
+ */
+ bind : function(el){
+ ml.setStyle(
+ Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
+ );
+ },
+
+ /**
+ * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
+ * to set a fixed width in order to accurately measure the text height.
+ * @memberOf Roo.util.TextMetrics.Instance#
+ * @param {Number} width The width to set on the element
+ */
+ setFixedWidth : function(width){
+ ml.setWidth(width);
+ },
+
+ /**
+ * Returns the measured width of the specified text
+ * @memberOf Roo.util.TextMetrics.Instance#
+ * @param {String} text The text to measure
+ * @return {Number} width The width in pixels
+ */
+ getWidth : function(text){
+ ml.dom.style.width = 'auto';
+ return this.getSize(text).width;
+ },
+
+ /**
+ * Returns the measured height of the specified text. For multiline text, be sure to call
+ * {@link #setFixedWidth} if necessary.
+ * @memberOf Roo.util.TextMetrics.Instance#
+ * @param {String} text The text to measure
+ * @return {Number} height The height in pixels
+ */
+ getHeight : function(text){
+ return this.getSize(text).height;
+ }
+ };
+
+ instance.bind(bindTo);
+
+ return instance;
+};
+
+// backwards compat
+Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+/**
+ * @class Roo.state.Provider
+ * Abstract base class for state provider implementations. This class provides methods
+ * for encoding and decoding <b>typed</b> variables including dates and defines the
+ * Provider interface.
+ */
+Roo.state.Provider = function(){
+ /**
+ * @event statechange
+ * Fires when a state change occurs.
+ * @param {Provider} this This state provider
+ * @param {String} key The state key which was changed
+ * @param {String} value The encoded value for the state
+ */
+ this.addEvents({
+ "statechange": true
+ });
+ this.state = {};
+ Roo.state.Provider.superclass.constructor.call(this);
+};
+Roo.extend(Roo.state.Provider, Roo.util.Observable, {
+ /**
+ * Returns the current value for a key
+ * @param {String} name The key name
+ * @param {Mixed} defaultValue A default value to return if the key's value is not found
+ * @return {Mixed} The state data
+ */
+ get : function(name, defaultValue){
+ return typeof this.state[name] == "undefined" ?
+ defaultValue : this.state[name];
+ },
+
+ /**
+ * Clears a value from the state
+ * @param {String} name The key name
+ */
+ clear : function(name){
+ delete this.state[name];
+ this.fireEvent("statechange", this, name, null);
+ },
+
+ /**
+ * Sets the value for a key
+ * @param {String} name The key name
+ * @param {Mixed} value The value to set
+ */
+ set : function(name, value){
+ this.state[name] = value;
+ this.fireEvent("statechange", this, name, value);
+ },
+
+ /**
+ * Decodes a string previously encoded with {@link #encodeValue}.
+ * @param {String} value The value to decode
+ * @return {Mixed} The decoded value
+ */
+ decodeValue : function(cookie){
+ var re = /^(a|n|d|b|s|o)\:(.*)$/;
+ var matches = re.exec(unescape(cookie));
+ if(!matches || !matches[1]) return; // non state cookie
+ var type = matches[1];
+ var v = matches[2];
+ switch(type){
+ case "n":
+ return parseFloat(v);
+ case "d":
+ return new Date(Date.parse(v));
+ case "b":
+ return (v == "1");
+ case "a":
+ var all = [];
+ var values = v.split("^");
+ for(var i = 0, len = values.length; i < len; i++){
+ all.push(this.decodeValue(values[i]));
+ }
+ return all;
+ case "o":
+ var all = {};
+ var values = v.split("^");
+ for(var i = 0, len = values.length; i < len; i++){
+ var kv = values[i].split("=");
+ all[kv[0]] = this.decodeValue(kv[1]);
+ }
+ return all;
+ default:
+ return v;
+ }
+ },
+
+ /**
+ * Encodes a value including type information. Decode with {@link #decodeValue}.
+ * @param {Mixed} value The value to encode
+ * @return {String} The encoded value
+ */
+ encodeValue : function(v){
+ var enc;
+ if(typeof v == "number"){
+ enc = "n:" + v;
+ }else if(typeof v == "boolean"){
+ enc = "b:" + (v ? "1" : "0");
+ }else if(v instanceof Date){
+ enc = "d:" + v.toGMTString();
+ }else if(v instanceof Array){
+ var flat = "";
+ for(var i = 0, len = v.length; i < len; i++){
+ flat += this.encodeValue(v[i]);
+ if(i != len-1) flat += "^";
+ }
+ enc = "a:" + flat;
+ }else if(typeof v == "object"){
+ var flat = "";
+ for(var key in v){
+ if(typeof v[key] != "function"){
+ flat += key + "=" + this.encodeValue(v[key]) + "^";
+ }
+ }
+ enc = "o:" + flat.substring(0, flat.length-1);
+ }else{
+ enc = "s:" + v;
+ }
+ return escape(enc);
+ }
+});
+
+/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+/**
+ * @class Roo.state.Manager
+ * This is the global state manager. By default all components that are "state aware" check this class
+ * for state information if you don't pass them a custom state provider. In order for this class
+ * to be useful, it must be initialized with a provider when your application initializes.
+ <pre><code>
+// in your initialization function
+init : function(){
+ Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
+ ...
+ // supposed you have a {@link Roo.BorderLayout}
+ var layout = new Roo.BorderLayout(...);
+ layout.restoreState();
+ // or a {Roo.BasicDialog}
+ var dialog = new Roo.BasicDialog(...);
+ dialog.restoreState();
+ </code></pre>
+ * @singleton
+ */
+Roo.state.Manager = function(){
+ var provider = new Roo.state.Provider();
+
+ return {
+ /**
+ * Configures the default state provider for your application
+ * @param {Provider} stateProvider The state provider to set
+ */
+ setProvider : function(stateProvider){
+ provider = stateProvider;
+ },
+
+ /**
+ * Returns the current value for a key
+ * @param {String} name The key name
+ * @param {Mixed} defaultValue The default value to return if the key lookup does not match
+ * @return {Mixed} The state data
+ */
+ get : function(key, defaultValue){
+ return provider.get(key, defaultValue);
+ },
+
+ /**
+ * Sets the value for a key
+ * @param {String} name The key name
+ * @param {Mixed} value The state data
+ */
+ set : function(key, value){
+ provider.set(key, value);
+ },
+
+ /**
+ * Clears a value from the state
+ * @param {String} name The key name
+ */
+ clear : function(key){
+ provider.clear(key);
+ },
+
+ /**
+ * Gets the currently configured state provider
+ * @return {Provider} The state provider
+ */
+ getProvider : function(){
+ return provider;
+ }
+ };
+}();
+/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+/**
+ * @class Roo.state.CookieProvider
+ * @extends Roo.state.Provider
+ * The default Provider implementation which saves state via cookies.
+ * <br />Usage:
+ <pre><code>
+ var cp = new Roo.state.CookieProvider({
+ path: "/cgi-bin/",
+ expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
+ domain: "roojs.com"
+ })
+ Roo.state.Manager.setProvider(cp);
+ </code></pre>
+ * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
+ * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
+ * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
+ * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
+ * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
+ * domain the page is running on including the 'www' like 'www.roojs.com')
+ * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
+ * @constructor
+ * Create a new CookieProvider
+ * @param {Object} config The configuration object
+ */
+Roo.state.CookieProvider = function(config){
+ Roo.state.CookieProvider.superclass.constructor.call(this);
+ this.path = "/";
+ this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
+ this.domain = null;
+ this.secure = false;
+ Roo.apply(this, config);
+ this.state = this.readCookies();
+};
+
+Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
+ // private
+ set : function(name, value){
+ if(typeof value == "undefined" || value === null){
+ this.clear(name);
+ return;
+ }
+ this.setCookie(name, value);
+ Roo.state.CookieProvider.superclass.set.call(this, name, value);
+ },
+
+ // private
+ clear : function(name){
+ this.clearCookie(name);
+ Roo.state.CookieProvider.superclass.clear.call(this, name);
+ },
+
+ // private
+ readCookies : function(){
+ var cookies = {};
+ var c = document.cookie + ";";
+ var re = /\s?(.*?)=(.*?);/g;
+ var matches;
+ while((matches = re.exec(c)) != null){
+ var name = matches[1];
+ var value = matches[2];
+ if(name && name.substring(0,3) == "ys-"){
+ cookies[name.substr(3)] = this.decodeValue(value);
+ }
+ }
+ return cookies;
+ },
+
+ // private
+ setCookie : function(name, value){
+ document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
+ ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
+ ((this.path == null) ? "" : ("; path=" + this.path)) +
+ ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
+ ((this.secure == true) ? "; secure" : "");
+ },
+
+ // private
+ clearCookie : function(name){
+ document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
+ ((this.path == null) ? "" : ("; path=" + this.path)) +
+ ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
+ ((this.secure == true) ? "; secure" : "");
+ }
+});
\ No newline at end of file