/**
* @class Roo.DomHelper
* Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
- * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
+ * 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>.
* @singleton
*/
Roo.DomHelper = function(){
}
};
/*
+ * Based on:
+ * Roo JS
+ * (c)) Alan Knowles
+ * Licence : LGPL
+ */
+
+
+/**
+ * @class Roo.DomTemplate
+ * @extends Roo.Template
+ * An effort at a dom based template engine..
+ *
+ * Similar to XTemplate, except it uses dom parsing to create the template..
+ *
+ * Supported features:
+ *
+ * Tags:
+
+<pre><code>
+ {a_variable} - output encoded.
+ {a_variable.format:("Y-m-d")} - call a method on the variable
+ {a_variable:raw} - unencoded output
+ {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
+ {a_variable:this.method_on_template(...)} - call a method on the template object.
+
+</code></pre>
+ * The tpl tag:
+<pre><code>
+ <div roo-for="a_variable or condition.."></div>
+ <div roo-if="a_variable or condition"></div>
+ <div roo-exec="some javascript"></div>
+ <div roo-name="named_template"></div>
+
+</code></pre>
+ *
+ */
+Roo.DomTemplate = function()
+{
+ Roo.DomTemplate.superclass.constructor.apply(this, arguments);
+ if (this.html) {
+ this.compile();
+ }
+};
+
+
+Roo.extend(Roo.DomTemplate, Roo.Template, {
+ /**
+ * id counter for sub templates.
+ */
+ id : 0,
+ /**
+ * flag to indicate if dom parser is inside a pre,
+ * it will strip whitespace if not.
+ */
+ inPre : false,
+
+ /**
+ * The various sub templates
+ */
+ tpls : false,
+
+
+
+ /**
+ *
+ * basic tag replacing syntax
+ * WORD:WORD()
+ *
+ * // you can fake an object call by doing this
+ * x.t:(test,tesT)
+ *
+ */
+ re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\}|\%7D)/g,
+ //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
+
+ iterChild : function (node, method) {
+
+ var oldPre = this.inPre;
+ if (node.tagName == 'PRE') {
+ this.inPre = true;
+ }
+ for( var i = 0; i < node.childNodes.length; i++) {
+ method.call(this, node.childNodes[i]);
+ }
+ this.inPre = oldPre;
+ },
+
+
+
+ /**
+ * compile the template
+ *
+ * This is not recursive, so I'm not sure how nested templates are really going to be handled..
+ *
+ */
+ compile: function()
+ {
+ var s = this.html;
+
+ // covert the html into DOM...
+
+ var div = document.createElement('div');
+ div.innerHTML = this.html ;
+
+ this.tpls = [];
+ var _t = this;
+ this.iterChild(div, function(n) {_t.compileNode(n, true); });
+
+ var tpls = this.tpls;
+
+ // create a top level template from the snippet..
+
+ //Roo.log(div.innerHTML);
+
+ var tpl = {
+ uid : 'master',
+ id : this.id++,
+ attr : false,
+ value : false,
+ body : div.innerHTML,
+
+ forCall : false,
+ execCall : false,
+ dom : div,
+ isTop : true
+
+ };
+ tpls.unshift(tpl);
+
+
+ // compile them...
+ this.tpls = [];
+ Roo.each(tpls, function(tp){
+ this.compileTpl(tp);
+ this.tpls[tp.id] = tp;
+ }, this);
+
+ this.master = tpls[0];
+ return this;
+
+
+ },
+
+ compileNode : function(node, istop) {
+ // test for
+ //Roo.log(node);
+
+
+ // skip anything not a tag..
+ if (node.nodeType != 1) {
+ if (node.nodeType == 3 && !this.inPre) {
+ // reduce white space..
+ node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
+
+ }
+ return;
+ }
+
+ var tpl = {
+ uid : false,
+ id : false,
+ attr : false,
+ value : false,
+ body : '',
+
+ forCall : false,
+ execCall : false,
+ dom : false,
+ isTop : istop
+
+
+ };
+
+
+ switch(true) {
+ case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
+ case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
+ case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
+ case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
+ // no default..
+ }
+
+
+ if (!tpl.attr) {
+ // just itterate children..
+ this.iterChild(node,this.compileNode);
+ return;
+ }
+ tpl.uid = this.id++;
+ tpl.value = node.getAttribute('roo-' + tpl.attr);
+ node.removeAttribute('roo-'+ tpl.attr);
+ if (tpl.attr != 'name') {
+ var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
+ node.parentNode.replaceChild(placeholder, node);
+ } else {
+
+ var placeholder = document.createElement('span');
+ placeholder.className = 'roo-tpl-' + tpl.value;
+ node.parentNode.replaceChild(placeholder, node);
+ }
+
+ // parent now sees '{domtplXXXX}
+ this.iterChild(node,this.compileNode);
+
+ // we should now have node body...
+ var div = document.createElement('div');
+ div.appendChild(node);
+ tpl.dom = node;
+ // this has the unfortunate side effect of converting tagged attributes
+ // eg. href="{...}" into %7C...%7D
+ // this has been fixed by searching for those combo's although it's a bit hacky..
+
+
+ tpl.body = div.innerHTML;
+
+
+
+ tpl.id = tpl.uid;
+ switch(tpl.attr) {
+ case 'for' :
+ switch (tpl.value) {
+ case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
+ case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
+ default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
+ }
+ break;
+
+ case 'exec':
+ tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
+ break;
+
+ case 'if':
+ tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
+ break;
+
+ case 'name':
+ tpl.id = tpl.value; // replace non characters???
+ break;
+
+ }
+
+
+ this.tpls.push(tpl);
+
+
+
+ },
+
+
+
+
+ /**
+ * Compile a segment of the template into a 'sub-template'
+ *
+ *
+ *
+ *
+ */
+ compileTpl : function(tpl)
+ {
+ var fm = Roo.util.Format;
+ var useF = this.disableFormats !== true;
+
+ var sep = Roo.isGecko ? "+\n" : ",\n";
+
+ var undef = function(str) {
+ Roo.debug && Roo.log("Property not found :" + str);
+ return '';
+ };
+
+ //Roo.log(tpl.body);
+
+
+
+ var fn = function(m, lbrace, name, format, args)
+ {
+ //Roo.log("ARGS");
+ //Roo.log(arguments);
+ args = args ? args.replace(/\\'/g,"'") : args;
+ //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
+ if (typeof(format) == 'undefined') {
+ format = 'htmlEncode';
+ }
+ if (format == 'raw' ) {
+ format = false;
+ }
+
+ if(name.substr(0, 6) == 'domtpl'){
+ return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
+ }
+
+ // build an array of options to determine if value is undefined..
+
+ // basically get 'xxxx.yyyy' then do
+ // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
+ // (function () { Roo.log("Property not found"); return ''; })() :
+ // ......
+
+ var udef_ar = [];
+ var lookfor = '';
+ Roo.each(name.split('.'), function(st) {
+ lookfor += (lookfor.length ? '.': '') + st;
+ udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
+ });
+
+ var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
+
+
+ if(format && useF){
+
+ args = args ? ',' + args : "";
+
+ if(format.substr(0, 5) != "this."){
+ format = "fm." + format + '(';
+ }else{
+ format = 'this.call("'+ format.substr(5) + '", ';
+ args = ", values";
+ }
+
+ return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
+ }
+
+ if (args.length) {
+ // called with xxyx.yuu:(test,test)
+ // change to ()
+ return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
+ }
+ // raw.. - :raw modifier..
+ return "'"+ sep + udef_st + name + ")"+sep+"'";
+
+ };
+ var body;
+ // branched to use + in gecko and [].join() in others
+ if(Roo.isGecko){
+ body = "tpl.compiled = function(values, parent){ with(values) { return '" +
+ tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
+ "';};};";
+ }else{
+ body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
+ body.push(tpl.body.replace(/(\r\n|\n)/g,
+ '\\n').replace(/'/g, "\\'").replace(this.re, fn));
+ body.push("'].join('');};};");
+ body = body.join('');
+ }
+
+ Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
+
+ /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
+ eval(body);
+
+ return this;
+ },
+
+ /**
+ * same as applyTemplate, except it's done to one of the subTemplates
+ * when using named templates, you can do:
+ *
+ * var str = pl.applySubTemplate('your-name', values);
+ *
+ *
+ * @param {Number} id of the template
+ * @param {Object} values to apply to template
+ * @param {Object} parent (normaly the instance of this object)
+ */
+ applySubTemplate : function(id, values, parent)
+ {
+
+
+ var t = this.tpls[id];
+
+
+ try {
+ if(t.ifCall && !t.ifCall.call(this, values, parent)){
+ Roo.log('if call on ' + t.value + ' return false');
+ return '';
+ }
+ } catch(e) {
+ Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
+ Roo.log(values);
+
+ return '';
+ }
+ try {
+
+ if(t.execCall && t.execCall.call(this, values, parent)){
+ return '';
+ }
+ } catch(e) {
+ Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
+ Roo.log(values);
+ return '';
+ }
+
+ try {
+ var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
+ parent = t.target ? values : parent;
+ if(t.forCall && vs instanceof Array){
+ var buf = [];
+ for(var i = 0, len = vs.length; i < len; i++){
+ try {
+ buf[buf.length] = t.compiled.call(this, vs[i], parent);
+ } catch (e) {
+ Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
+ Roo.log(e.body);
+ //Roo.log(t.compiled);
+ Roo.log(vs[i]);
+ }
+ }
+ return buf.join('');
+ }
+ } catch (e) {
+ Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
+ Roo.log(values);
+ return '';
+ }
+ try {
+ return t.compiled.call(this, vs, parent);
+ } catch (e) {
+ Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
+ Roo.log(e.body);
+ //Roo.log(t.compiled);
+ Roo.log(values);
+ return '';
+ }
+ },
+
+
+
+ applyTemplate : function(values){
+ return this.master.compiled.call(this, values, {});
+ //var s = this.subs;
+ },
+
+ apply : function(){
+ return this.applyTemplate.apply(this, arguments);
+ }
+
+ });
+
+Roo.DomTemplate.from = function(el){
+ el = Roo.getDom(el);
+ return new Roo.Domtemplate(el.value || el.innerHTML);
+};/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
* @return {String} The formatted currency string
*/
usMoney : function(v){
- v = (Math.round((v-0)*100))/100;
- v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
+ return '$' + Roo.util.Format.number(v);
+ },
+
+ /**
+ * Format a number
+ * eventually this should probably emulate php's number_format
+ * @param {Number/String} value The numeric value to format
+ * @param {Number} decimals number of decimal places
+ * @return {String} The formatted currency string
+ */
+ number : function(v,decimals)
+ {
+ // multiply and round.
+ decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
+ var mul = Math.pow(10, decimals);
+ var zero = String(mul).substring(1);
+ v = (Math.round((v-0)*mul))/mul;
+
+ // if it's '0' number.. then
+
+ //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
v = String(v);
var ps = v.split('.');
var whole = ps[0];
- var sub = ps[1] ? '.'+ ps[1] : '.00';
+
+
var r = /(\d+)(\d{3})/;
+ // add comma's
while (r.test(whole)) {
whole = whole.replace(r, '$1' + ',' + '$2');
}
- return "$" + whole + sub ;
+
+
+ var sub = ps[1] ?
+ // has decimals..
+ (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
+ // does not have decimals
+ (decimals ? ('.' + zero) : '');
+
+
+ return whole + sub ;
},
/**
var dragEl = null;
var proc = {};
+
+
var onStop = function(e){
dragEl = null;
clearProc();
};
var startProc = function(el, dir){
+ Roo.log('scroll startproc');
clearProc();
proc.el = el;
proc.dir = dir;
};
var onFire = function(e, isDrop){
+
if(isDrop || !ddm.dragCurrent){ return; }
var dds = Roo.dd.ScrollManager;
if(!dragEl || dragEl != ddm.dragCurrent){
el = Roo.get(el);
els[el.id] = el;
}
+ Roo.dd.ScrollManager.els = els;
},
/**
* The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
* out of the target without dropping. This default implementation simply removes the CSS class specified by
* overClass (if any) from the drop element.
+ *
* @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
* @param {Event} e The event
* @param {Object} data An object containing arbitrary data supplied by the drag source
this.id = Roo.id(null, "ynode-");
this.attributes.id = this.id;
}
+
+
/**
* All child nodes of this node. @type Array
*/
*/
setValue : function(value){
var old = this.value;
+
+ if (typeof(value) == 'string') {
+
+ value = Date.parseDate(value, this.format);
+ }
+ if (!value) {
+ value = new Date();
+ }
+
this.value = value.clearTime(true);
if(this.el){
this.update(this.value);
}
},
- // private
+ // privateval
onRender : function(container, position){
+
var m = [
'<table cellspacing="0">',
'<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>',
}
this.getSelectionModel().init(this);
if (!this.root) {
- console.log("ROOT not set in tree");
- return;
+ Roo.log("ROOT not set in tree");
+ return this;
}
this.root.render();
if(!this.rootVisible){
* to be loaded.
*/
/**
+ * @cfg {String} requestMethod either GET or POST
+ * defaults to POST (due to BC)
+ * to be loaded.
+ */
+ /**
* @cfg {Object} baseParams (optional) An object containing properties which
* specify HTTP parameters to be passed to each request for child nodes.
*/
Roo.extend(Roo.tree.TreeDropZone, Roo.dd.DropZone, {
ddGroup : "TreeDD",
+ scroll: true,
expandDelay : 1000,
return overEvent.cancel === false && result !== false;
},
- getDropPoint : function(e, n, dd){
+ getDropPoint : function(e, n, dd)
+ {
var tn = n.node;
if(tn.isRoot){
return tn.allowChildren !== false ? "append" : false; // always append for root
}
},
- onNodeEnter : function(n, dd, e, data){
+ onNodeEnter : function(n, dd, e, data)
+ {
this.cancelExpand();
},
- onNodeOver : function(n, dd, e, data){
+ onNodeOver : function(n, dd, e, data)
+ {
+
var pt = this.getDropPoint(e, n, dd);
var node = n.node;
},
onNodeOut : function(n, dd, e, data){
+
this.cancelExpand();
this.removeDropIndicators(n);
},
data.node.ui.highlight();
}
this.hideProxy();
- }
+ }
+
});
}
Roo.extend(Roo.tree.TreeDragZone, Roo.dd.DragZone, {
ddGroup : "TreeDD",
-
+
onBeforeDrag : function(data, e){
var n = data.node;
return n && n.draggable && !n.disabled;
},
+
onInitDrag : function(e){
var data = this.dragData;
onEndDrag : function(data, e){
this.tree.fireEvent("enddrag", this.tree, data.node, e);
+
+
},
onValidDrop : function(dd, e, id){
* @param {Date} date
*/
this.relayEvents(di, ["select"]);
-
this.on('beforeshow', function(){
if(this.picker){
- this.picker.hideMonthPicker(true);
+ this.picker.hideMonthPicker(false);
}
}, this);
};
/**
- * @cfg {bool} useIso
+ * @cfg {Boolean} useIso
* if enabled, then the date field will use a hidden field to store the
* real value as iso formated date. default (false)
*/
this.el.dom.removeAttribute('name');
this.hiddenField = this.el.insertSibling({ tag:'input', type:'hidden', name: this.name },
'before', true);
- this.hiddenField.value = this.formatDate(this.value, 'Y-m-d');
+ this.hiddenField.value = this.value ? this.formatDate(this.value, 'Y-m-d') : '';
// prevent input submission
this.hiddenName = this.name;
}
{
value = this.formatDate(value);
if(!Roo.form.DateField.superclass.validateValue.call(this, value)){
+ Roo.log('super failed');
return false;
}
if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid
var svalue = value;
value = this.parseDate(value);
if(!value){
+ Roo.log('parse date failed' + svalue);
this.markInvalid(String.format(this.invalidText, svalue, this.format));
return false;
}
*/
getValue : function(){
- return this.hiddenField ? this.hiddenField.value : this.parseDate(Roo.form.DateField.superclass.getValue.call(this)) || "";
+ return this.hiddenField ?
+ this.hiddenField.value :
+ this.parseDate(Roo.form.DateField.superclass.getValue.call(this)) || "";
},
/**
this.hiddenField.value = this.formatDate(this.parseDate(date), 'Y-m-d');
}
Roo.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
+ // make sure the value field is always stored as a date..
+ this.value = this.parseDate(date);
+
+
},
// private
return value;
}
var v = Date.parseDate(value, this.format);
+ if (!v && this.useIso) {
+ v = Date.parseDate(value, 'Y-m-d');
+ }
if(!v && this.altFormats){
if(!this.altFormatsArray){
this.altFormatsArray = this.altFormats.split("|");
// private
menuListeners : {
select: function(m, d){
+
this.setValue(d);
this.fireEvent('select', this, d);
},
disabledDatesText : this.disabledDatesText,
disabledDays : this.disabledDays,
disabledDaysText : this.disabledDaysText,
- format : this.format,
+ format : this.useIso ? 'Y-m-d' : this.format,
minText : String.format(this.minText, this.formatDate(this.minValue)),
maxText : String.format(this.maxText, this.formatDate(this.maxValue))
});
* <script type="text/javascript">
*/
+/**
+ * @class Roo.form.MonthField
+ * @extends Roo.form.TriggerField
+ * Provides a date input field with a {@link Roo.DatePicker} dropdown and automatic date validation.
+* @constructor
+* Create a new MonthField
+* @param {Object} config
+ */
+Roo.form.MonthField = function(config){
+
+ Roo.form.MonthField.superclass.constructor.call(this, config);
+
+ this.addEvents({
+
+ /**
+ * @event select
+ * Fires when a date is selected
+ * @param {Roo.form.MonthFieeld} combo This combo box
+ * @param {Date} date The date selected
+ */
+ 'select' : true
+
+ });
+
+
+ if(typeof this.minValue == "string") this.minValue = this.parseDate(this.minValue);
+ if(typeof this.maxValue == "string") this.maxValue = this.parseDate(this.maxValue);
+ this.ddMatch = null;
+ if(this.disabledDates){
+ var dd = this.disabledDates;
+ var re = "(?:";
+ for(var i = 0; i < dd.length; i++){
+ re += dd[i];
+ if(i != dd.length-1) re += "|";
+ }
+ this.ddMatch = new RegExp(re + ")");
+ }
+};
+
+Roo.extend(Roo.form.MonthField, Roo.form.TriggerField, {
+ /**
+ * @cfg {String} format
+ * The default date format string which can be overriden for localization support. The format must be
+ * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
+ */
+ format : "M Y",
+ /**
+ * @cfg {String} altFormats
+ * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined
+ * format (defaults to 'm/d/Y|m-d-y|m-d-Y|m/d|m-d|d').
+ */
+ altFormats : "M Y|m/Y|m-y|m-Y|my|mY",
+ /**
+ * @cfg {Array} disabledDays
+ * An array of days to disable, 0 based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
+ */
+ disabledDays : [0,1,2,3,4,5,6],
+ /**
+ * @cfg {String} disabledDaysText
+ * The tooltip to display when the date falls on a disabled day (defaults to 'Disabled')
+ */
+ disabledDaysText : "Disabled",
+ /**
+ * @cfg {Array} disabledDates
+ * An array of "dates" to disable, as strings. These strings will be used to build a dynamic regular
+ * expression so they are very powerful. Some examples:
+ * <ul>
+ * <li>["03/08/2003", "09/16/2003"] would disable those exact dates</li>
+ * <li>["03/08", "09/16"] would disable those days for every year</li>
+ * <li>["^03/08"] would only match the beginning (useful if you are using short years)</li>
+ * <li>["03/../2006"] would disable every day in March 2006</li>
+ * <li>["^03"] would disable every day in every March</li>
+ * </ul>
+ * In order to support regular expressions, if you are using a date format that has "." in it, you will have to
+ * escape the dot when restricting dates. For example: ["03\\.08\\.03"].
+ */
+ disabledDates : null,
+ /**
+ * @cfg {String} disabledDatesText
+ * The tooltip text to display when the date falls on a disabled date (defaults to 'Disabled')
+ */
+ disabledDatesText : "Disabled",
+ /**
+ * @cfg {Date/String} minValue
+ * The minimum allowed date. Can be either a Javascript date object or a string date in a
+ * valid format (defaults to null).
+ */
+ minValue : null,
+ /**
+ * @cfg {Date/String} maxValue
+ * The maximum allowed date. Can be either a Javascript date object or a string date in a
+ * valid format (defaults to null).
+ */
+ maxValue : null,
+ /**
+ * @cfg {String} minText
+ * The error text to display when the date in the cell is before minValue (defaults to
+ * 'The date in this field must be after {minValue}').
+ */
+ minText : "The date in this field must be equal to or after {0}",
+ /**
+ * @cfg {String} maxTextf
+ * The error text to display when the date in the cell is after maxValue (defaults to
+ * 'The date in this field must be before {maxValue}').
+ */
+ maxText : "The date in this field must be equal to or before {0}",
+ /**
+ * @cfg {String} invalidText
+ * The error text to display when the date in the field is invalid (defaults to
+ * '{value} is not a valid date - it must be in the format {format}').
+ */
+ invalidText : "{0} is not a valid date - it must be in the format {1}",
+ /**
+ * @cfg {String} triggerClass
+ * An additional CSS class used to style the trigger button. The trigger will always get the
+ * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified (defaults to 'x-form-date-trigger'
+ * which displays a calendar icon).
+ */
+ triggerClass : 'x-form-date-trigger',
+
+
+ /**
+ * @cfg {Boolean} useIso
+ * if enabled, then the date field will use a hidden field to store the
+ * real value as iso formated date. default (true)
+ */
+ useIso : true,
+ /**
+ * @cfg {String/Object} autoCreate
+ * A DomHelper element spec, or true for a default element spec (defaults to
+ * {tag: "input", type: "text", size: "10", autocomplete: "off"})
+ */
+ // private
+ defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
+
+ // private
+ hiddenField: false,
+
+ hideMonthPicker : false,
+
+ onRender : function(ct, position)
+ {
+ Roo.form.MonthField.superclass.onRender.call(this, ct, position);
+ if (this.useIso) {
+ this.el.dom.removeAttribute('name');
+ this.hiddenField = this.el.insertSibling({ tag:'input', type:'hidden', name: this.name },
+ 'before', true);
+ this.hiddenField.value = this.value ? this.formatDate(this.value, 'Y-m-d') : '';
+ // prevent input submission
+ this.hiddenName = this.name;
+ }
+
+
+ },
+
+ // private
+ validateValue : function(value)
+ {
+ value = this.formatDate(value);
+ if(!Roo.form.MonthField.superclass.validateValue.call(this, value)){
+ return false;
+ }
+ if(value.length < 1){ // if it's blank and textfield didn't flag it then it's valid
+ return true;
+ }
+ var svalue = value;
+ value = this.parseDate(value);
+ if(!value){
+ this.markInvalid(String.format(this.invalidText, svalue, this.format));
+ return false;
+ }
+ var time = value.getTime();
+ if(this.minValue && time < this.minValue.getTime()){
+ this.markInvalid(String.format(this.minText, this.formatDate(this.minValue)));
+ return false;
+ }
+ if(this.maxValue && time > this.maxValue.getTime()){
+ this.markInvalid(String.format(this.maxText, this.formatDate(this.maxValue)));
+ return false;
+ }
+ /*if(this.disabledDays){
+ var day = value.getDay();
+ for(var i = 0; i < this.disabledDays.length; i++) {
+ if(day === this.disabledDays[i]){
+ this.markInvalid(this.disabledDaysText);
+ return false;
+ }
+ }
+ }
+ */
+ var fvalue = this.formatDate(value);
+ /*if(this.ddMatch && this.ddMatch.test(fvalue)){
+ this.markInvalid(String.format(this.disabledDatesText, fvalue));
+ return false;
+ }
+ */
+ return true;
+ },
+
+ // private
+ // Provides logic to override the default TriggerField.validateBlur which just returns true
+ validateBlur : function(){
+ return !this.menu || !this.menu.isVisible();
+ },
+
+ /**
+ * Returns the current date value of the date field.
+ * @return {Date} The date value
+ */
+ getValue : function(){
+
+
+
+ return this.hiddenField ?
+ this.hiddenField.value :
+ this.parseDate(Roo.form.MonthField.superclass.getValue.call(this)) || "";
+ },
+
+ /**
+ * Sets the value of the date field. You can pass a date object or any string that can be parsed into a valid
+ * date, using MonthField.format as the date format, according to the same rules as {@link Date#parseDate}
+ * (the default format used is "m/d/y").
+ * <br />Usage:
+ * <pre><code>
+//All of these calls set the same date value (May 4, 2006)
+
+//Pass a date object:
+var dt = new Date('5/4/06');
+monthField.setValue(dt);
+
+//Pass a date string (default format):
+monthField.setValue('5/4/06');
+
+//Pass a date string (custom format):
+monthField.format = 'Y-m-d';
+monthField.setValue('2006-5-4');
+</code></pre>
+ * @param {String/Date} date The date or valid date string
+ */
+ setValue : function(date){
+ Roo.log('month setValue' + date);
+ // can only be first of month..
+
+ var val = this.parseDate(date);
+
+ if (this.hiddenField) {
+ this.hiddenField.value = this.formatDate(this.parseDate(date), 'Y-m-d');
+ }
+ Roo.form.MonthField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
+ this.value = this.parseDate(date);
+ },
+
+ // private
+ parseDate : function(value){
+ if(!value || value instanceof Date){
+ value = value ? Date.parseDate(value.format('Y-m') + '-01', 'Y-m-d') : null;
+ return value;
+ }
+ var v = Date.parseDate(value, this.format);
+ if (!v && this.useIso) {
+ v = Date.parseDate(value, 'Y-m-d');
+ }
+ if (v) {
+ //
+ v = Date.parseDate(v.format('Y-m') +'-01', 'Y-m-d');
+ }
+
+
+ if(!v && this.altFormats){
+ if(!this.altFormatsArray){
+ this.altFormatsArray = this.altFormats.split("|");
+ }
+ for(var i = 0, len = this.altFormatsArray.length; i < len && !v; i++){
+ v = Date.parseDate(value, this.altFormatsArray[i]);
+ }
+ }
+ return v;
+ },
+
+ // private
+ formatDate : function(date, fmt){
+ return (!date || !(date instanceof Date)) ?
+ date : date.dateFormat(fmt || this.format);
+ },
+
+ // private
+ menuListeners : {
+ select: function(m, d){
+ this.setValue(d);
+ this.fireEvent('select', this, d);
+ },
+ show : function(){ // retain focus styling
+ this.onFocus();
+ },
+ hide : function(){
+ this.focus.defer(10, this);
+ var ml = this.menuListeners;
+ this.menu.un("select", ml.select, this);
+ this.menu.un("show", ml.show, this);
+ this.menu.un("hide", ml.hide, this);
+ }
+ },
+ // private
+ // Implements the default empty TriggerField.onTriggerClick function to display the DatePicker
+ onTriggerClick : function(){
+ if(this.disabled){
+ return;
+ }
+ if(this.menu == null){
+ this.menu = new Roo.menu.DateMenu();
+
+ }
+
+ Roo.apply(this.menu.picker, {
+
+ showClear: this.allowBlank,
+ minDate : this.minValue,
+ maxDate : this.maxValue,
+ disabledDatesRE : this.ddMatch,
+ disabledDatesText : this.disabledDatesText,
+
+ format : this.useIso ? 'Y-m-d' : this.format,
+ minText : String.format(this.minText, this.formatDate(this.minValue)),
+ maxText : String.format(this.maxText, this.formatDate(this.maxValue))
+
+ });
+ this.menu.on(Roo.apply({}, this.menuListeners, {
+ scope:this
+ }));
+
+
+ var m = this.menu;
+ var p = m.picker;
+
+ // hide month picker get's called when we called by 'before hide';
+
+ var ignorehide = true;
+ p.hideMonthPicker = function(disableAnim){
+ if (ignorehide) {
+ return;
+ }
+ if(this.monthPicker){
+ Roo.log("hideMonthPicker called");
+ if(disableAnim === true){
+ this.monthPicker.hide();
+ }else{
+ this.monthPicker.slideOut('t', {duration:.2});
+ p.setValue(new Date(m.picker.mpSelYear, m.picker.mpSelMonth, 1));
+ p.fireEvent("select", this, this.value);
+ m.hide();
+ }
+ }
+ }
+
+ Roo.log('picker set value');
+ Roo.log(this.getValue());
+ p.setValue(this.getValue() ? this.parseDate(this.getValue()) : new Date());
+ m.show(this.el, 'tl-bl?');
+ ignorehide = false;
+ // this will trigger hideMonthPicker..
+
+
+ // hidden the day picker
+ Roo.select('.x-date-picker table', true).first().dom.style.visibility = "hidden";
+
+
+
+
+
+ p.showMonthPicker.defer(100, p);
+
+
+
+ },
+
+ beforeBlur : function(){
+ var v = this.parseDate(this.getRawValue());
+ if(v){
+ this.setValue(v);
+ }
+ }
+
+ /** @cfg {Boolean} grow @hide */
+ /** @cfg {Number} growMin @hide */
+ /** @cfg {Number} growMax @hide */
+ /**
+ * @hide
+ * @method autoSize
+ */
+});/*
+ * 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.form.ComboBox
this.setValue(this.originalValue);
this.clearInvalid();
this.lastData = false;
+ if (this.view) {
+ this.view.clearSelections();
+ }
},
// private
findRecord : function(prop, value){
/**
* @class Roo.form.ComboBoxArray
- * @extends Roo.form.ComboBox
+ * @extends Roo.form.TextField
* A facebook style adder... for lists of email / people / countries etc...
* pick multiple items from a combo box, and shows each one.
*
* Fred [x] Brian [x] [Pick another |v]
- *
+ *
+ *
+ * For this to work: it needs various extra information
+ * - normal combo problay has
+ * name, hiddenName
+ * + displayField, valueField
+ *
+ * For our purpose...
+ *
+ *
+ * If we change from 'extends' to wrapping...
+ *
+ *
+ *
+
+
* @constructor
* Create a new ComboBoxArray.
* @param {Object} config Configuration options
{
Roo.form.ComboBoxArray.superclass.constructor.call(this, config);
+
this.items = new Roo.util.MixedCollection(false);
- this.on('select', function(cb, rec, ix) {
- this.addItem(rec.data);
- this.setValue('');
- this.el.dom.value = '';
- //cb.lastData = rec.data;
- // add to list
-
- });
+
+ // construct the child combo...
+
+
+
+
+
}
+
-Roo.extend(Roo.form.ComboBoxArray, Roo.form.ComboBox,
+Roo.extend(Roo.form.ComboBoxArray, Roo.form.TextField,
{
+ /**
+ * @cfg {Roo.form.Combo} combo The combo box that is wrapped
+ */
+
lastData : false,
- items : false,
- nameField : 'name',
+ // behavies liek a hiddne field
+ inputType: 'hidden',
+ /**
+ * @cfg {Number} width The width of the box that displays the selected element
+ */
+ width: 300,
+
- tipField : 'email',
- idField : 'id',
+ /**
+ * @cfg {String} name The name of the visable items on this form (eg. titles not ids)
+ */
+ name : false,
+ /**
+ * @cfg {String} hiddenName The hidden name of the field, often contains an comma seperated list of names
+ */
+ hiddenName : false,
- renderer : false,
- hiddenName : false, // set this if you want a , sperated list of values in it for form posting..
- hiddenListName : false,
+ // private the array of items that are displayed..
+ items : false,
+ // private - the hidden field el.
hiddenEl : false,
+ // private - the filed el..
+ el : false,
- /**
- * @cfg {Number} boxWidth The width of the box that displays the selected element
- */
- boxWidth : 200, // use to set the box around the entry..
- allowBlank: true,
- disableClear: true,
//validateValue : function() { return true; }, // all values are ok!
//onAddClick: function() { },
onRender : function(ct, position)
{
-
- Roo.form.ComboBoxArray.superclass.onRender.call(this, ct, position);
- this.wrap.addClass('p-cblist-grp');
- var cbwrap = this.wrap.createChild(
- {tag: 'div', cls: 'p-cblist-cb'},
- this.el.dom
- );
- if (this.hiddenListName) {
+
+ // create the standard hidden element
+ //Roo.form.ComboBoxArray.superclass.onRender.call(this, ct, position);
+
+
+ // give fake names to child combo;
+ this.combo.hiddenName = this.hiddenName ? (this.hiddenName+'-subcombo') : this.hiddenName;
+ this.combo.name = this.name? (this.name+'-subcombo') : this.name;
+
+ this.combo = Roo.factory(this.combo, Roo.form);
+ this.combo.onRender(ct, position);
+
+ // assigned so form know we need to do this..
+ this.store = this.combo.store;
+ this.valueField = this.combo.valueField;
+ this.displayField = this.combo.displayField ;
+
+
+ this.combo.wrap.addClass('x-cbarray-grp');
+
+ var cbwrap = this.combo.wrap.createChild(
+ {tag: 'div', cls: 'x-cbarray-cb'},
+ this.combo.el.dom
+ );
+
- this.hiddenEl = this.wrap.createChild({
- tag: 'input', type:'hidden' , name: this.hiddenListName, value : ''
- });
+ this.hiddenEl = this.combo.wrap.createChild({
+ tag: 'input', type:'hidden' , name: this.hiddenName, value : ''
+ });
+ this.el = this.combo.wrap.createChild({
+ tag: 'input', type:'hidden' , name: this.name, value : ''
+ });
// this.el.dom.removeAttribute("name");
- }
- this.outerWrap = this.wrap;
+
+ this.outerWrap = this.combo.wrap;
this.wrap = cbwrap;
- this.outerWrap.setWidth(this.boxWidth);
+
+ this.outerWrap.setWidth(this.width);
this.outerWrap.dom.removeChild(this.el.dom);
+
this.wrap.dom.appendChild(this.el.dom);
- this.outerWrap.dom.removeChild(this.trigger.dom);
- this.wrap.dom.appendChild(this.trigger.dom);
-
- this.trigger.setStyle('position','relative');
- this.trigger.setStyle('left', '0px');
- this.trigger.setStyle('top', '2px');
- this.el.setStyle('vertical-align', 'text-bottom');
+ this.outerWrap.dom.removeChild(this.combo.trigger.dom);
+ this.combo.wrap.dom.appendChild(this.combo.trigger.dom);
+
+ this.combo.trigger.setStyle('position','relative');
+ this.combo.trigger.setStyle('left', '0px');
+ this.combo.trigger.setStyle('top', '2px');
+
+ this.combo.el.setStyle('vertical-align', 'text-bottom');
//this.trigger.setStyle('vertical-align', 'top');
+
+ // this should use the code from combo really... on('add' ....)
if (this.adder) {
//var _t = this;
//this.adder.on('click', this.onAddClick, _t);
+
+ this.combo.on('select', function(cb, rec, ix) {
+ this.addItem(rec.data);
+
+ cb.setValue('');
+ cb.el.dom.value = '';
+ //cb.lastData = rec.data;
+ // add to list
+
+ }, this);
+
+
+ },
+
+
+ getName: function()
+ {
+ // returns hidden if it's set..
+ if (!this.rendered) {return ''};
+ return this.hiddenName ? this.hiddenName : this.name;
+
},
onResize: function(w, h){
- Roo.form.ComboBox.superclass.onResize.apply(this, arguments);
+
+ return;
+ // not sure if this is needed..
+ //this.combo.onResize(w,h);
if(typeof w != 'number'){
// we do not handle it!?!?
return;
}
- var tw = this.trigger.getWidth();
+ var tw = this.combo.trigger.getWidth();
tw += this.addicon ? this.addicon.getWidth() : 0;
tw += this.editicon ? this.editicon.getWidth() : 0;
var x = w - tw;
- this.el.setWidth( this.adjustWidth('input', x));
+ this.combo.el.setWidth( this.combo.adjustWidth('input', x));
- this.trigger.setStyle('left', '0px');
+ this.combo.trigger.setStyle('left', '0px');
if(this.list && this.listWidth === undefined){
- var lw = Math.max(x + this.trigger.getWidth(), this.minListWidth);
+ var lw = Math.max(x + this.combo.trigger.getWidth(), this.combo.minListWidth);
this.list.setWidth(lw);
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
}
addItem: function(rec)
{
- if (this.items.indexOfKey(rec[this.idField]) > -1) {
+ var valueField = this.combo.valueField;
+ var displayField = this.combo.displayField;
+ if (this.items.indexOfKey(rec[valueField]) > -1) {
//console.log("GOT " + rec.data.id);
return;
}
var x = new Roo.form.ComboBoxArray.Item({
//id : rec[this.idField],
data : rec,
- nameField : this.nameField,
- tipField : this.tipField,
+ displayField : displayField ,
+ tipField : displayField ,
cb : this
});
// use the
- this.items.add(rec[this.idField],x);
+ this.items.add(rec[valueField],x);
// add it before the element..
this.updateHiddenEl();
x.render(this.outerWrap, this.wrap.dom);
return;
}
var ar = [];
- var idField = this.idField;
+ var idField = this.combo.valueField;
+
this.items.each(function(f) {
ar.push(f.data[idField]);
reset : function()
{
- Roo.form.ComboBoxArray.superclass.reset.call(this);
+ //Roo.form.ComboBoxArray.superclass.reset.call(this);
this.items.each(function(f) {
f.remove();
});
+ this.el.dom.value = '';
if (this.hiddenEl) {
this.hiddenEl.dom.value = '';
}
},
setValue: function(v) // not a valid action - must use addItems..
{
- if (typeof(v) != 'object') {
+
+ this.reset();
+
+
+
+ if (this.store.isLocal && (typeof(v) == 'string')) {
+ // then we can use the store to find the values..
+ // comma seperated at present.. this needs to allow JSON based encoding..
+ this.hiddenEl.value = v;
+ var v_ar = [];
+ Roo.each(v.split(','), function(k) {
+ Roo.log("CHECK " + this.valueField + ',' + k);
+ var li = this.store.query(this.valueField, k);
+ if (!li.length) {
+ return;
+ }
+ add = {};
+ add[this.valueField] = k;
+ add[this.displayField] = li.item(0).data[this.displayField];
+
+ this.addItem(add);
+ }, this)
+
+ }
+ if (typeof(v) == 'object') {
+ // then let's assume it's an array of objects..
+ Roo.each(v, function(l) {
+ this.addItem(l);
+ }, this);
+
+ }
+
+
+ },
+ setFromData: function(v)
+ {
+ // this recieves an object, if setValues is called.
+ this.reset();
+ this.el.dom.value = v[this.displayField];
+ this.hiddenEl.dom.value = v[this.valueField];
+ if (typeof(v[this.valueField]) != 'string' || !v[this.valueField].length) {
return;
}
- var _this = this;
- Roo.each(v, function(l) {
- _this.addItem(l);
- });
+ var kv = v[this.valueField];
+ var dv = v[this.displayField];
+ kv = typeof(kv) != 'string' ? '' : kv;
+ dv = typeof(dv) != 'string' ? '' : dv;
+
+
+ var keys = kv.split(',');
+ var display = dv.split(',');
+ for (var i = 0 ; i < keys.length; i++) {
+
+ add = {};
+ add[this.valueField] = keys[i];
+ add[this.displayField] = display[i];
+ this.addItem(add);
+ }
+
},
+
+
validateValue : function(value){
return Roo.form.ComboBoxArray.superclass.validateValue.call(this, this.getValue());
Roo.extend(Roo.form.ComboBoxArray.Item, Roo.BoxComponent, {
data : {},
cb: false,
- defaultAutoCreate : {tag: 'div', cls: 'p-cblist-item', cn : [
+ displayField : false,
+ tipField : false,
+
+
+ defaultAutoCreate : {
+ tag: 'div',
+ cls: 'x-cbarray-item',
+ cn : [
{ tag: 'div' },
- { tag: 'img', width:16, height : 16, src : Roo.BLANK_IMAGE_URL , align: 'center' }
+ {
+ tag: 'img',
+ width:16,
+ height : 16,
+ src : Roo.BLANK_IMAGE_URL ,
+ align: 'center'
+ }
]
},
- onRender : function(ct, position){
+ onRender : function(ct, position)
+ {
Roo.form.Field.superclass.onRender.call(this, ct, position);
+
if(!this.el){
var cfg = this.getAutoCreate();
this.el = ct.createChild(cfg, position);
}
+
this.el.child('img').dom.setAttribute('src', Roo.BLANK_IMAGE_URL);
this.el.child('div').dom.innerHTML = this.cb.renderer ?
- this.cb.renderer(this.data) : String.format('{0}',this.data[this.nameField]);
- this.el.child('div').dom.setAttribute('qtip', String.format('{0}',this.data[this.tipField]));
+ this.cb.renderer(this.data) :
+ String.format('{0}',this.data[this.displayField]);
+
+
+ this.el.child('div').dom.setAttribute('qtip',
+ String.format('{0}',this.data[this.tipField])
+ );
this.el.child('img').on('click', this.remove, this);
if (v.match(/^(http|https):\/\//) || v.match(/^mailto:/)) {
return;
}
+ if (v.match(/^#/)) {
+ return;
+ }
Roo.log("(REMOVE)"+ node.tagName +'.' + n + '=' + v);
node.removeAttribute(n);
//console.log(a);
if (Roo.form.HtmlEditor.ablack.indexOf(a.name.toLowerCase()) > -1) {
node.removeAttribute(a.name);
- return;
+ continue;
}
if (Roo.form.HtmlEditor.aclean.indexOf(a.name.toLowerCase()) > -1) {
cleanAttr(a.name,a.value); // fixme..
- return;
+ continue;
}
if (a.name == 'style') {
cleanStyle(a.name,a.value);
+ continue;
}
/// clean up MS crap..
// tecnically this should be a list of valid class'es..
if (a.value.match(/body/)) {
node.className = '';
}
+ continue;
}
// style cleanup!?
if (this.btns) {
for(var i =0; i< this.btns.length;i++) {
- var b = this.btns[i];
+ var b = Roo.factory(this.btns[i],Roo.form);
b.cls = 'x-edit-none';
b.scope = editor;
tb.add(b);
}
if (!rdata || !rdata.success) {
Roo.log(rdata);
+ Roo.MessageBox.alert(Roo.encode(rdata));
return;
}
var data = rdata.data;
this.toolbar = new Roo.Toolbar(this.toolbar);
}
+ // xtype created footer. - not sure if will work as we normally have to render first..
+ if (this.footer && !this.footer.el && this.footer.xtype) {
+ if (!this.wrapEl) {
+ this.wrapEl = this.el.wrap();
+ }
+ this.footer.container = this.wrapEl.createChild();
+
+ this.footer = Roo.factory(this.footer, Roo);
+
+ }
if(this.resizeEl){
this.resizeEl = Roo.get(this.resizeEl, true);
return this.wrapEl || this.el;
},
- adjustForComponents : function(width, height){
+ adjustForComponents : function(width, height)
+ {
+ Roo.log('adjustForComponents ');
if(this.resizeEl != this.el){
width -= this.el.getFrameWidth('lr');
height -= this.el.getFrameWidth('tb');
height -= te.getHeight();
te.setWidth(width);
}
+ if(this.footer){
+ var te = this.footer.getEl();
+ Roo.log("footer:" + te.getHeight());
+
+ height -= te.getHeight();
+ te.setWidth(width);
+ }
+
+
if(this.adjustments){
width += this.adjustments[0];
height += this.adjustments[1];
addxtype : function(cfg) {
// add form..
if (cfg.xtype.match(/^Form$/)) {
- var el = this.el.createChild();
+
+ var el;
+ //if (this.footer) {
+ // el = this.footer.container.insertSibling(false, 'before');
+ //} else {
+ el = this.el.createChild();
+ //}
this.form = new Roo.form.Form(cfg);
//console.log('render tree');
this.tree.render();
});
+ // this should not be needed.. - it's actually the 'el' that resizes?
+ // actuall it breaks the containerScroll - dragging nodes auto scroll at top
- this.on('resize', function (cp, w, h) {
- this.tree.innerCt.setWidth(w);
- this.tree.innerCt.setHeight(h);
- this.tree.innerCt.setStyle('overflow-y', 'auto');
- });
+ //this.on('resize', function (cp, w, h) {
+ // this.tree.innerCt.setWidth(w);
+ // this.tree.innerCt.setHeight(h);
+ // //this.tree.innerCt.setStyle('overflow-y', 'auto');
+ //});
}
}
-
+ if (!this.parent.el) {
+ // probably an old style ctor, which has been disabled.
+ return;
+
+ }
// The 'tree' method is '_tree now'
var tree = this._tree ? this._tree() : this.tree();
});
Roo.apply(Roo.XComponent, {
-
+ /**
+ * @property hideProgress
+ * true to disable the building progress bar.. usefull on single page renders.
+ * @type Boolean
+ */
+ hideProgress : false,
/**
* @property buildCompleted
* True when the builder has completed building the interface.
*/
register : function(obj) {
- Roo.XComponent.event.fireEvent('register', obj);
- switch(typeof(obj.disabled) ) {
-
- case 'undefined':
- break;
-
- case 'function':
- if ( obj.disabled() ) {
- return;
- }
- break;
- default:
- if (obj.disabled) {
- return;
- }
- break;
- }
+ Roo.XComponent.event.fireEvent('register', obj);
+ switch(typeof(obj.disabled) ) {
+
+ case 'undefined':
+ break;
+
+ case 'function':
+ if ( obj.disabled() ) {
+ return;
+ }
+ break;
+
+ default:
+ if (obj.disabled) {
+ return;
+ }
+ break;
+ }
this.modules.push(obj);
var _t = this;
Roo.each(this.modules , function (obj)
{
+ Roo.XComponent.event.fireEvent('beforebuild', obj);
+
var opar = obj.parent;
try {
obj.parent = this.toObject(opar);
}
if (!obj.parent) {
- Roo.debug && Roo.log("GOT top level module");
- Roo.debug && Roo.log(obj);
- obj.modules = new Roo.util.MixedCollection(false,
+ Roo.debug && Roo.log("GOT top level module");
+ Roo.debug && Roo.log(obj);
+ obj.modules = new Roo.util.MixedCollection(false,
function(o) { return o.order + '' }
);
this.topModule = obj;
function(o) { return o.order + '' }
);
}
-
+ if (obj.parent.disabled) {
+ obj.disabled = true;
+ }
obj.parent.modules.add(obj);
}, this);
},
// make a flat list in order of modules to build.
var mods = this.topModule ? [ this.topModule ] : [];
- // elmodules (is a list of DOM based modules )
- Roo.each(this.elmodules,function(e) { mods.push(e) });
+ // elmodules (is a list of DOM based modules )
+ Roo.each(this.elmodules, function(e) {
+ mods.push(e)
+ });
// add modules to their parents..
var addMod = function(m) {
- Roo.debug && Roo.log("build Order: add: " + m.name);
+ Roo.debug && Roo.log("build Order: add: " + m.name);
- mods.push(m);
- if (m.modules) {
- Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
- m.modules.keySort('ASC', cmp );
- Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
+ mods.push(m);
+ if (m.modules && !m.disabled) {
+ Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
+ m.modules.keySort('ASC', cmp );
+ Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
- m.modules.each(addMod);
- } else {
- Roo.debug && Roo.log("build Order: no child modules");
- }
+ m.modules.each(addMod);
+ } else {
+ Roo.debug && Roo.log("build Order: no child modules");
+ }
// not sure if this is used any more..
if (m.finalize) {
m.finalize.name = m.name + " (clean up) ";
var msg = "Building Interface...";
// flash it up as modal - so we store the mask!?
- Roo.MessageBox.show({ title: 'loading' });
- Roo.MessageBox.show({
- title: "Please wait...",
- msg: msg,
- width:450,
- progress:true,
- closable:false,
- modal: false
-
- });
+ if (!this.hideProgress) {
+ Roo.MessageBox.show({ title: 'loading' });
+ Roo.MessageBox.show({
+ title: "Please wait...",
+ msg: msg,
+ width:450,
+ progress:true,
+ closable:false,
+ modal: false
+
+ });
+ }
var total = mods.length;
var _this = this;
var progressRun = function() {
if (!mods.length) {
Roo.debug && Roo.log('hide?');
- Roo.MessageBox.hide();
+ if (!this.hideProgress) {
+ Roo.MessageBox.hide();
+ }
Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
// THE END...
" of " + total +
(m.name ? (' - ' + m.name) : '');
Roo.debug && Roo.log(msg);
- Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
+ if (!this.hideProgress) {
+ Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
+ }
// is the module disabled?
*
*/
'register' : true,
+ /**
+ * @event beforebuild
+ * Fires before each Component is built
+ * can be used to apply permissions.
+ * @param {Roo.XComponent} c the component being registerd.
+ *
+ */
+ 'beforebuild' : true,
/**
* @event buildcomplete
* Fires on the top level element when all elements have been built