* Small helper class to make creating Stores from Array data easier.
* @cfg {Number} id The array index of the record id. Leave blank to auto generate ids.
* @cfg {Array} fields An array of field definition objects, or field name strings.
+ * @cfg {Object} an existing reader (eg. copied from another store)
* @cfg {Array} data The multi-dimensional array of data
* @constructor
* @param {Object} config
*/
-Roo.data.SimpleStore = function(config){
+Roo.data.SimpleStore = function(config)
+{
Roo.data.SimpleStore.superclass.constructor.call(this, {
isLocal : true,
- reader: new Roo.data.ArrayReader({
- id: config.id
+ reader: new Roo.data.ArrayReader({
+ id: config.id,
+ fields : config.fields
},
Roo.data.Record.create(config.fields)
),
return new this.recordType(Roo.apply(da, d));
}
+
};/*
* Based on:
* Ext JS Library 1.1.1
params = params || {};
var result;
try {
- result = reader.readRecords(this.data);
+ result = reader.readRecords(params.data ? params.data :this.data);
}catch(e){
this.fireEvent("loadexception", this, arg, null, e);
callback.call(scope, null, arg, false);
* <pre><code>
[ [1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist'] ]
</code></pre>
- * @cfg {String} id (optional) The subscript within row Array that provides an ID for the Record
+
* @constructor
* Create a new JsonReader
* @param {Object} meta Metadata configuration options.
- * @param {Object} recordType Either an Array of field definition objects
+ * @param {Object|Array} recordType Either an Array of field definition objects
+ *
+ * @cfg {Array} fields Array of field definition objects
+ * @cfg {String} id Name of the property within a row object that contains a record identifier value.
* as specified to {@link Roo.data.Record#create},
* or an {@link Roo.data.Record} object
+ *
+ *
* created using {@link Roo.data.Record#create}.
*/
-Roo.data.ArrayReader = function(meta, recordType){
- Roo.data.ArrayReader.superclass.constructor.call(this, meta, recordType);
+Roo.data.ArrayReader = function(meta, recordType)
+{
+ Roo.data.ArrayReader.superclass.constructor.call(this, meta, recordType||meta.fields);
};
Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
/**
* Create a data block containing Roo.data.Records from an XML document.
* @param {Object} o An Array of row objects which represents the dataset.
- * @return {Object} data A data block which is used by an Roo.data.Store object as
+ * @return {Object} A data block which is used by an {@link Roo.data.Store} object as
* a cache of Roo.data.Records.
*/
- readRecords : function(o){
+ readRecords : function(o)
+ {
var sid = this.meta ? this.meta.id : null;
var recordType = this.recordType, fields = recordType.prototype.fields;
var records = [];
var root = o;
- for(var i = 0; i < root.length; i++){
- var n = root[i];
- var values = {};
- var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
- for(var j = 0, jlen = fields.length; j < jlen; j++){
- var f = fields.items[j];
- var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
- var v = n[k] !== undefined ? n[k] : f.defaultValue;
- v = f.convert(v);
- values[f.name] = v;
- }
- var record = new recordType(values, id);
- record.json = n;
- records[records.length] = record;
+ for(var i = 0; i < root.length; i++){
+ var n = root[i];
+ var values = {};
+ var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
+ for(var j = 0, jlen = fields.length; j < jlen; j++){
+ var f = fields.items[j];
+ var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
+ var v = n[k] !== undefined ? n[k] : f.defaultValue;
+ v = f.convert(v);
+ values[f.name] = v;
}
- return {
- records : records,
- totalRecords : records.length
- };
+ var record = new recordType(values, id);
+ record.json = n;
+ records[records.length] = record;
+ }
+ return {
+ records : records,
+ totalRecords : records.length
+ };
}
});/*
* Based on:
}else if(arguments.length > 1){
multi = arguments;
}
+
// if passed an array or multiple args do them one by one
if(multi){
for(var i = 0, len = multi.length; i < len; i++) {
}
oldParent.removeChild(node);
}
+
index = this.childNodes.length;
if(index == 0){
this.setFirstChild(node);
this.setLastChild(node);
node.setOwnerTree(this.getOwnerTree());
this.fireEvent("append", this.ownerTree, this, node, index);
+ if(this.ownerTree) {
+ this.ownerTree.fireEvent("appendnode", this, node, index);
+ }
if(oldParent){
node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
}
* </ul>
* @param {Object} dragOverEvent
*/
- "nodedragover" : true
+ "nodedragover" : true,
+ /**
+ * @event appendnode
+ * Fires when append node to the tree
+ * @param {Roo.tree.TreePanel} this
+ * @param {Roo.tree.TreeNode} node
+ * @param {Number} index The index of the newly appended node
+ */
+ "appendnode" : true
});
if(this.singleExpand){
* @cfg {Boolean} allowDrop false if this node cannot be drop on
* @cfg {Boolean} disabled true to start the node disabled
* @cfg {String} icon The path to an icon for the node. The preferred way to do this
- * is to use the cls or iconCls attributes and add the icon via a CSS background image.
+ * is to use the cls or iconCls attributes and add the icon via a CSS background image.
* @cfg {String} cls A css class to be added to the node
* @cfg {String} iconCls A css class to be added to the nodes icon element for applying css background images
* @cfg {String} href URL of the link used for the node (defaults to #)
this.renderChildren();
}
this.expanded = true;
- if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
+
+ if(!this.isHiddenRoot() && (this.getOwnerTree() && this.getOwnerTree().animate && anim !== false) || anim){
this.ui.animExpand(function(){
this.fireEvent("expand", this);
if(typeof callback == "function"){
this.addClass("x-tree-node-disabled");
}
var ot = this.node.getOwnerTree();
- var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
+ var dd = ot ? (ot.enableDD || ot.enableDrag || ot.enableDrop) : false;
if(dd && (!this.node.isRoot || ot.rootVisible)){
Roo.dd.Registry.register(this.elNode, {
node: this.node,
// add some indent caching, this helps performance when rendering a large tree
this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
var t = n.getOwnerTree();
- var txt = t.renderer ? t.renderer(n.attributes) : Roo.util.Format.htmlEncode(n.text);
+ var txt = t && t.renderer ? t.renderer(n.attributes) : Roo.util.Format.htmlEncode(n.text);
if (typeof(n.attributes.html) != 'undefined') {
txt = n.attributes.html;
}
- var tip = t.rendererTip ? t.rendererTip(n.attributes) : txt;
+ var tip = t && t.rendererTip ? t.rendererTip(n.attributes) : txt;
var cb = typeof a.checked == 'boolean';
var href = a.href ? a.href : Roo.isGecko ? "" : "#";
var buf = ['<li class="x-tree-node"><div class="x-tree-node-el ', a.cls,'">',
myTreeLoader.on("beforeload", function(treeLoader, node) {
this.baseParams.category = node.attributes.category;
}, this);
-</code></pre><
+
+</code></pre>
+ *
* This would pass an HTTP parameter called "category" to the server containing
* the value of the Node's "category" attribute.
* @constructor
* @param {Object} config Configuration options
*/
Roo.menu.Menu = function(config){
- Roo.apply(this, config);
+
+ Roo.menu.Menu.superclass.constructor.call(this, config);
+
this.id = this.id || Roo.id();
this.addEvents({
/**
* <script type="text/javascript">
*/
+/**
+ * @class Roo.form.TextItem
+ * @extends Roo.BoxComponent
+ * Base class for form fields that provides default event handling, sizing, value handling and other functionality.
+ * @constructor
+ * Creates a new TextItem
+ * @param {Object} config Configuration options
+ */
+Roo.form.TextItem = function(config){
+ Roo.form.TextItem.superclass.constructor.call(this, config);
+};
+
+Roo.extend(Roo.form.TextItem, Roo.BoxComponent, {
+
+ /**
+ * @cfg {String} tag the tag for this item (default div)
+ */
+ tag : 'div',
+ /**
+ * @cfg {String} html the content for this item
+ */
+ html : '',
+
+ getAutoCreate : function()
+ {
+ var cfg = {
+ id: this.id,
+ tag: this.tag,
+ html: this.html,
+ cls: 'x-form-item'
+ };
+
+ return cfg;
+
+ },
+
+ onRender : function(ct, position)
+ {
+ Roo.form.TextItem.superclass.onRender.call(this, ct, position);
+
+ if(!this.el){
+ var cfg = this.getAutoCreate();
+ if(!cfg.name){
+ cfg.name = typeof(this.name) == 'undefined' ? this.id : this.name;
+ }
+ if (!cfg.name.length) {
+ delete cfg.name;
+ }
+ this.el = ct.createChild(cfg, position);
+ }
+ }
+
+});/*
+ * 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.Field
* @extends Roo.BoxComponent
* @cfg {Boolean} selectOnFocus True to automatically select any existing field text when the field receives input focus (defaults to false)
*/
selectOnFocus : false,
+ /**
+ * @cfg {Boolean} allowLeadingSpace True to prevent the stripping of leading white space
+ */
+ allowLeadingSpace : false,
/**
* @cfg {String} blankText Error text to display if the allow blank validation fails (defaults to "This field is required")
*/
if(this.selectOnFocus){
this.on("focus", this.preFocus, this);
-
}
+ if (!this.allowLeadingSpace) {
+ this.on('blur', this.cleanLeadingSpace, this);
+ }
+
if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Roo.form.VTypes[this.vtype+'Mask']))){
this.el.on("keypress", this.filterKeys, this);
}
this.autoSize();
}
},
-
+ // private - clean the leading white space
+ cleanLeadingSpace : function(e)
+ {
+ if ( this.inputType == 'file') {
+ return;
+ }
+
+ this.setValue((this.getValue() + '').replace(/^\s+/,''));
+ },
/**
* Resets the current field value to the originally-loaded value and clears any validation messages.
*
reset : function(){
Roo.form.TextField.superclass.reset.call(this);
- },
-
-
+ },
// private
preFocus : function(){
* Create a new DateField
* @param {Object} config
*/
-Roo.form.DateField = function(config){
+Roo.form.DateField = function(config)
+{
Roo.form.DateField.superclass.constructor.call(this, config);
this.addEvents({
return String(this.getValue()) !== String(this.startValue);
+ },
+ // @overide
+ cleanLeadingSpace : function(e)
+ {
+ return;
}
+
});/*
* Based on:
* Ext JS Library 1.1.1
// element that contains real text value.. (when hidden is used..)
// private
- onRender : function(ct, position){
+ onRender : function(ct, position)
+ {
Roo.form.ComboBox.superclass.onRender.call(this, ct, position);
- if(this.hiddenName){
+
+ if(this.hiddenName){
this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
'before', true);
this.hiddenField.value =
}
+
if(Roo.isGecko){
this.el.dom.setAttribute('autocomplete', 'off');
}
}
this.view = new Roo.View(this.innerList, this.tpl, {
- singleSelect:true, store: this.store, selectedClass: this.selectedClass
+ singleSelect:true,
+ store: this.store,
+ selectedClass: this.selectedClass
});
this.view.on('click', this.onViewClick, this);
this.view.select(match);
var sn = Roo.get(this.view.getSelectedNodes()[0]);
sn.scrollIntoView(sn.dom.parentNode, false);
- }
+ }
/**
* @cfg {Boolean} grow
// 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.name = this.name ? (this.name+'-subcombo') : this.name;
this.combo = Roo.factory(this.combo, Roo.form);
this.combo.onRender(ct, position);
{
var valueField = this.combo.valueField;
var displayField = this.combo.displayField;
+
if (this.items.indexOfKey(rec[valueField]) > -1) {
//console.log("GOT " + rec.data.id);
return;
this.items.each(function(f) {
ar.push(f.data[idField]);
-
});
this.hiddenEl.dom.value = ar.join(',');
this.validate();
},
setValue: function(v) // not a valid action - must use addItems..
{
-
- this.reset();
-
-
+ 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..
}
}
+});/*
+ * RooJS Library 1.1.1
+ * Copyright(c) 2008-2011 Alan Knowles
+ *
+ * License - LGPL
+ */
+
+
+/**
+ * @class Roo.form.ComboNested
+ * @extends Roo.form.ComboBox
+ * A combobox for that allows selection of nested items in a list,
+ * eg.
+ *
+ * Book
+ * -> red
+ * -> green
+ * Table
+ * -> square
+ * ->red
+ * ->green
+ * -> rectangle
+ * ->green
+ *
+ *
+ * @constructor
+ * Create a new ComboNested
+ * @param {Object} config Configuration options
+ */
+Roo.form.ComboNested = function(config){
+ Roo.form.ComboCheck.superclass.constructor.call(this, config);
+ // should verify some data...
+ // like
+ // hiddenName = required..
+ // displayField = required
+ // valudField == required
+ var req= [ 'hiddenName', 'displayField', 'valueField' ];
+ var _t = this;
+ Roo.each(req, function(e) {
+ if ((typeof(_t[e]) == 'undefined' ) || !_t[e].length) {
+ throw "Roo.form.ComboNested : missing value for: " + e;
+ }
+ });
+
+
+};
+
+Roo.extend(Roo.form.ComboNested, Roo.form.ComboBox, {
+
+
+ list : null, // the outermost div..
+ innerLists : null, // the
+ views : null,
+ stores : null,
+ // private
+ onRender : function(ct, position)
+ {
+ Roo.form.ComboBox.superclass.onRender.call(this, ct, position); // skip parent call - got to above..
+
+ if(this.hiddenName){
+ this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
+ 'before', true);
+ this.hiddenField.value =
+ this.hiddenValue !== undefined ? this.hiddenValue :
+ this.value !== undefined ? this.value : '';
+
+ // prevent input submission
+ this.el.dom.removeAttribute('name');
+
+
+ }
+
+ if(Roo.isGecko){
+ this.el.dom.setAttribute('autocomplete', 'off');
+ }
+
+ var cls = 'x-combo-list';
+
+ this.list = new Roo.Layer({
+ shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
+ });
+
+ var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
+ this.list.setWidth(lw);
+ this.list.swallowEvent('mousewheel');
+ this.assetHeight = 0;
+
+ if(this.title){
+ this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
+ this.assetHeight += this.header.getHeight();
+ }
+ this.innerLists = [];
+ this.views = [];
+ this.stores = [];
+ for (var i =0 ; i < 3; i++) {
+ this.onRenderList( cls, i);
+ }
+
+ // always needs footer, as we are going to have an 'OK' button.
+ this.footer = this.list.createChild({cls:cls+'-ft'});
+ this.pageTb = new Roo.Toolbar(this.footer);
+ var _this = this;
+ this.pageTb.add( {
+
+ text: 'Done',
+ handler: function()
+ {
+ _this.collapse();
+ }
+ });
+
+ if ( this.allowBlank && !this.disableClear) {
+
+ this.pageTb.add(new Roo.Toolbar.Fill(), {
+ cls: 'x-btn-icon x-btn-clear',
+ text: ' ',
+ handler: function()
+ {
+ _this.collapse();
+ _this.clearValue();
+ _this.onSelect(false, -1);
+ }
+ });
+ }
+ if (this.footer) {
+ this.assetHeight += this.footer.getHeight();
+ }
+
+ },
+ onRenderList : function ( cls, i)
+ {
+
+ var lw = Math.floor(
+ ((this.listWidth * 3 || Math.max(this.wrap.getWidth(), this.minListWidth)) - this.list.getFrameWidth('lr')) / 3
+ );
+
+ this.list.setWidth(lw); // default to '1'
+
+ var il = this.innerLists[i] = this.list.createChild({cls:cls+'-inner'});
+ //il.on('mouseover', this.onViewOver, this, { list: i });
+ //il.on('mousemove', this.onViewMove, this, { list: i });
+ il.setWidth(lw);
+ il.setStyle({ 'overflow-x' : 'hidden'});
+
+ if(!this.tpl){
+ this.tpl = new Roo.Template({
+ html : '<div class="'+cls+'-item '+cls+'-item-{cn:this.isEmpty}">{' + this.displayField + '}</div>',
+ isEmpty: function (value, allValues) {
+ return value && value.length ? 'has-children' : 'no-children'
+ }
+ });
+ }
+
+ var store = this.store;
+ if (i > 0) {
+ store = new Roo.data.SimpleStore({
+ fields : this.store.reader.meta.fields,
+ data : [ ]
+ });
+ }
+ this.stores[i] = store;
+
+
+
+ var view = this.views[i] = new Roo.View(
+ il,
+ this.tpl,
+ {
+ singleSelect:true,
+ store: store,
+ selectedClass: this.selectedClass
+ }
+ );
+ view.getEl().setWidth(lw);
+ view.getEl().setStyle({
+ position: i < 1 ? 'relative' : 'absolute',
+ top: 0,
+ left: (i * lw ) + 'px',
+ display : i > 0 ? 'none' : 'block'
+ });
+ view.on('selectionchange', this.onSelectChange, this, {list : i });
+ view.on('dblclick', this.onDoubleClick, this, {list : i });
+ //view.on('click', this.onViewClick, this, { list : i });
+
+ store.on('beforeload', this.onBeforeLoad, this);
+ store.on('load', this.onLoad, this, { list : i});
+ store.on('loadexception', this.onLoadException, this);
+
+ // hide the other vies..
+
+
+
+ },
+ onResize : function() {},
+
+ restrictHeight : function()
+ {
+ var mh = 0;
+ Roo.each(this.innerLists, function(il,i) {
+ var el = this.views[i].getEl();
+ el.dom.style.height = '';
+ var inner = el.dom;
+ var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
+ // only adjust heights on other ones..
+ if (i < 1) {
+
+ el.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
+ il.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
+ mh = Math.max(el.getHeight(), mh);
+ }
+
+
+ }, this);
+
+ this.list.beginUpdate();
+ this.list.setHeight(mh+this.list.getFrameWidth('tb')+this.assetHeight);
+ this.list.alignTo(this.el, this.listAlign);
+ this.list.endUpdate();
+
+ },
+
+
+ // -- store handlers..
+ // private
+ onBeforeLoad : function()
+ {
+ if(!this.hasFocus){
+ return;
+ }
+ this.innerLists[0].update(this.loadingText ?
+ '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
+ this.restrictHeight();
+ this.selectedIndex = -1;
+ },
+ // private
+ onLoad : function(a,b,c,d)
+ {
+
+ if(!this.hasFocus){
+ return;
+ }
+
+ if(this.store.getCount() > 0) {
+ this.expand();
+ this.restrictHeight();
+ } else {
+ this.onEmptyResults();
+ }
+ /*
+ this.stores[1].loadData([]);
+ this.stores[2].loadData([]);
+ this.views
+ */
+
+ //this.el.focus();
+ },
+
+
+ // private
+ onLoadException : function()
+ {
+ this.collapse();
+ Roo.log(this.store.reader.jsonData);
+ if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
+ Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
+ }
+
+
+ } ,
+
+
+
+ onSelectChange : function (view, sels, opts )
+ {
+ var ix = view.getSelectedIndexes();
+
+
+ if (opts.list > 1) {
+
+ this.setFromData(ix.length ? view.store.getAt(ix[0]).data : {});
+ return;
+ }
+
+ if (!ix.length) {
+ this.setFromData({});
+ this.stores[opts.list+1].loadData( [] );
+ return;
+ }
+
+ var rec = view.store.getAt(ix[0]);
+ this.setFromData(rec.data);
+
+ var lw = Math.floor(
+ ((this.listWidth * 3 || Math.max(this.wrap.getWidth(), this.minListWidth)) - this.list.getFrameWidth('lr')) / 3
+ );
+ var data = typeof(rec.data.cn) == 'undefined' ? [] : rec.data.cn;
+ this.stores[opts.list+1].loadData( data );
+ this.views[opts.list+1].getEl().setHeight( this.innerLists[0].getHeight());
+ this.views[opts.list+1].getEl().setStyle({ display : data .length ? 'block' : 'none' });
+ this.innerLists[opts.list+1].setHeight( this.innerLists[0].getHeight());
+ this.list.setWidth(lw * (opts.list + (data.length ? 2 : 1)));
+ },
+ onDoubleClick : function()
+ {
+ this.collapse(); //??
+ },
+
+
+
+ findRecord : function (prop,value)
+ {
+ return this.findRecordInStore(this.store, prop,value);
+ },
+
+ // private
+ findRecordInStore : function(store, prop, value)
+ {
+ var cstore = new Roo.data.SimpleStore({
+ fields : this.store.reader.meta.fields, // we need array reader.. for
+ data : [ ]
+ });
+ var _this = this;
+ var record = false;
+ if(store.getCount() > 0){
+ store.each(function(r){
+ if(r.data[prop] == value){
+ record = r;
+ return false;
+ }
+ if (r.data.cn && r.data.cn.length) {
+ cstore.loadData( r.data.cn);
+ var cret = _this.findRecordInStore(cstore, prop, value);
+ if (cret !== false) {
+ record = cret;
+ return false;
+ }
+ }
+
+ return true;
+ });
+ }
+ return record;
+ }
+
+
+
+
});/*
* Based on:
* Ext JS Library 1.1.1
html = this.cleanHtml(html);
// fix up the special chars.. normaly like back quotes in word...
// however we do not want to do this with chinese..
- html = html.replace(/([\x80-\uffff])/g, function (a, b) {
- var cc = b.charCodeAt();
- if (
+ html = html.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0080-\uFFFF]/g, function(match) {
+
+ var cc = match.charCodeAt();
+
+ // Get the character value, handling surrogate pairs
+ if (match.length == 2) {
+ // It's a surrogate pair, calculate the Unicode code point
+ var high = match.charCodeAt(0) - 0xD800;
+ var low = match.charCodeAt(1) - 0xDC00;
+ cc = (high * 0x400) + low + 0x10000;
+ } else if (
(cc >= 0x4E00 && cc < 0xA000 ) ||
(cc >= 0x3400 && cc < 0x4E00 ) ||
(cc >= 0xf900 && cc < 0xfb00 )
) {
- return b;
- }
- return "&#"+cc+";"
+ return match;
+ }
+
+ // No, use a numeric entity. Here we brazenly (and possibly mistakenly)
+ return "&#" + cc + ";";
+
+
});
+
+
+
if(this.owner.fireEvent('beforesync', this, html) !== false){
this.el.dom.value = html;
this.owner.fireEvent('sync', this, html);
insertTag : function(tg)
{
// could be a bit smarter... -> wrap the current selected tRoo..
- if (tg.toLowerCase() == 'span' || tg.toLowerCase() == 'code') {
+ if (tg.toLowerCase() == 'span' ||
+ tg.toLowerCase() == 'code' ||
+ tg.toLowerCase() == 'sup' ||
+ tg.toLowerCase() == 'sub'
+ ) {
range = this.createRange(this.getSelection());
var wrappingNode = this.doc.createElement(tg.toLowerCase());
var remove_keep_children= Roo.HtmlEditorCore.remove.indexOf(node.tagName.toLowerCase()) > -1;
+ // spans with no attributes - just remove them..
+ if ((!node.attributes || !node.attributes.length) && lcname == 'span') {
+ remove_keep_children = true;
+ }
+
// remove <a name=....> as rendering on yahoo mailer is borked with this.
// this will have to be flaged elsewhere - perhaps ablack=name... on the mailer..
}
if (!node.attributes || !node.attributes.length) {
+
+
+
+
this.cleanUpChildren(node);
return;
}
if (a.name == 'class') {
if (a.value.match(/^Mso/)) {
- node.className = '';
+ node.removeAttribute('class');
}
if (a.value.match(/^body$/)) {
- node.className = '';
+ node.removeAttribute('class');
}
continue;
}
*/
cleanWord : function(node)
{
-
-
if (!node) {
this.cleanWord(this.doc.body);
return;
}
+
+ if(
+ node.nodeName == 'SPAN' &&
+ !node.hasAttributes() &&
+ node.childNodes.length == 1 &&
+ node.firstChild.nodeName == "#text"
+ ) {
+ var textNode = node.firstChild;
+ node.removeChild(textNode);
+ if (node.getAttribute('lang') != 'zh-CN') { // do not space pad on chinese characters..
+ node.parentNode.insertBefore(node.ownerDocument.createTextNode(" "), node);
+ }
+ node.parentNode.insertBefore(textNode, node);
+ if (node.getAttribute('lang') != 'zh-CN') { // do not space pad on chinese characters..
+ node.parentNode.insertBefore(node.ownerDocument.createTextNode(" ") , node);
+ }
+ node.parentNode.removeChild(node);
+ }
+
if (node.nodeName == "#text") {
// clean up silly Windows -- stuff?
return;
node.parentNode.removeChild(node);
return;
}
-
+ //Roo.log(node.tagName);
// remove - but keep children..
- if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|font)/)) {
+ if (node.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)) {
+ //Roo.log('-- removed');
while (node.childNodes.length) {
var cn = node.childNodes[0];
node.removeChild(cn);
node.parentNode.insertBefore(cn, node);
+ // move node to parent - and clean it..
+ this.cleanWord(cn);
}
node.parentNode.removeChild(node);
- this.iterateChildren(node, this.cleanWord);
+ /// no need to iterate chidlren = it's got none..
+ //this.iterateChildren(node, this.cleanWord);
return;
}
// clean styles
["h1"],["h2"],["h3"],["h4"],["h5"],["h6"],
["pre"],[ "code"],
["abbr"],[ "acronym"],[ "address"],[ "cite"],[ "samp"],[ "var"],
- ['div'],['span']
+ ['div'],['span'],
+ ['sup'],['sub']
],
cleanStyles : [
var c = Roo.get(editorcore.doc.body);
c.select('[class]').each(function(s) {
- s.dom.className = '';
+ s.dom.removeAttribute('class');
});
+ editorcore.cleanWord();
editorcore.syncValue();
},
tabIndex:-1
this.initEl(el);
}
Roo.form.BasicForm.superclass.constructor.call(this);
+
+ Roo.form.BasicForm.popover.apply();
};
Roo.extend(Roo.form.BasicForm, Roo.util.Observable, {
* @type Mixed
*/
waitMsgTarget : false,
+
+ /**
+ * @type Boolean
+ */
+ disableMask : false,
+
+ /**
+ * @cfg {Boolean} errorMask (true|false) default false
+ */
+ errorMask : false,
+
+ /**
+ * @cfg {Number} maskOffset Default 100
+ */
+ maskOffset : 100,
// private
initEl : function(el){
*/
isValid : function(){
var valid = true;
+ var target = false;
this.items.each(function(f){
- if(!f.validate()){
- valid = false;
- }
+ if(f.validate()){
+ return;
+ }
+
+ valid = false;
+
+ if(!target && f.el.isVisible(true)){
+ target = f;
+ }
});
+
+ if(this.errorMask && !valid){
+ Roo.form.BasicForm.popover.mask(this, target);
+ }
+
return valid;
},
beforeAction : function(action){
var o = action.options;
-
- if(this.waitMsgTarget === true){
- this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
- }else if(this.waitMsgTarget){
- this.waitMsgTarget = Roo.get(this.waitMsgTarget);
- this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
- }else {
- Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
+ if(!this.disableMask) {
+ if(this.waitMsgTarget === true){
+ this.el.mask(o.waitMsg || "Sending", 'x-mask-loading');
+ }else if(this.waitMsgTarget){
+ this.waitMsgTarget = Roo.get(this.waitMsgTarget);
+ this.waitMsgTarget.mask(o.waitMsg || "Sending", 'x-mask-loading');
+ }else {
+ Roo.MessageBox.wait(o.waitMsg || "Sending", o.waitTitle || this.waitTitle || 'Please Wait...');
+ }
}
+
},
this.activeAction = null;
var o = action.options;
- if(this.waitMsgTarget === true){
- this.el.unmask();
- }else if(this.waitMsgTarget){
- this.waitMsgTarget.unmask();
- }else{
- Roo.MessageBox.updateProgress(1);
- Roo.MessageBox.hide();
+ if(!this.disableMask) {
+ if(this.waitMsgTarget === true){
+ this.el.unmask();
+ }else if(this.waitMsgTarget){
+ this.waitMsgTarget.unmask();
+ }else{
+ Roo.MessageBox.updateProgress(1);
+ Roo.MessageBox.hide();
+ }
}
-
+
if(success){
if(o.reset){
this.reset();
return this;
},
-
+
/**
* Returns the fields in this form as an object with key/value pairs. If multiple fields exist with the same name
* they are returned as an array.
}, this);
}
+ // use formdata
+ if (typeof(FormData) != 'undefined' && asString !== true) {
+ var fd = (new FormData(this.el.dom)).entries();
+ var ret = {};
+ var ent = fd.next();
+ while (!ent.done) {
+ ret[ent.value[0]] = ent.value[1]; // not sure how this will handle duplicates..
+ ent = fd.next();
+ };
+ return ret;
+ }
var fs = Roo.lib.Ajax.serializeForm(this.el.dom);
});
// back compat
-Roo.BasicForm = Roo.form.BasicForm;/*
+Roo.BasicForm = Roo.form.BasicForm;
+
+Roo.apply(Roo.form.BasicForm, {
+
+ popover : {
+
+ padding : 5,
+
+ isApplied : false,
+
+ isMasked : false,
+
+ form : false,
+
+ target : false,
+
+ intervalID : false,
+
+ maskEl : false,
+
+ apply : function()
+ {
+ if(this.isApplied){
+ return;
+ }
+
+ this.maskEl = {
+ top : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-top-mask" }, true),
+ left : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-left-mask" }, true),
+ bottom : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-bottom-mask" }, true),
+ right : Roo.DomHelper.append(Roo.get(document.body), { tag: "div", cls:"x-dlg-mask roo-form-right-mask" }, true)
+ };
+
+ this.maskEl.top.enableDisplayMode("block");
+ this.maskEl.left.enableDisplayMode("block");
+ this.maskEl.bottom.enableDisplayMode("block");
+ this.maskEl.right.enableDisplayMode("block");
+
+ Roo.get(document.body).on('click', function(){
+ this.unmask();
+ }, this);
+
+ Roo.get(document.body).on('touchstart', function(){
+ this.unmask();
+ }, this);
+
+ this.isApplied = true
+ },
+
+ mask : function(form, target)
+ {
+ this.form = form;
+
+ this.target = target;
+
+ if(!this.form.errorMask || !target.el){
+ return;
+ }
+
+ var scrollable = this.target.el.findScrollableParent() || this.target.el.findParent('div.x-layout-active-content', 100, true) || Roo.get(document.body);
+
+ var ot = this.target.el.calcOffsetsTo(scrollable);
+
+ var scrollTo = ot[1] - this.form.maskOffset;
+
+ scrollTo = Math.min(scrollTo, scrollable.dom.scrollHeight);
+
+ scrollable.scrollTo('top', scrollTo);
+
+ var el = this.target.wrap || this.target.el;
+
+ var box = el.getBox();
+
+ this.maskEl.top.setStyle('position', 'absolute');
+ this.maskEl.top.setStyle('z-index', 10000);
+ this.maskEl.top.setSize(Roo.lib.Dom.getDocumentWidth(), box.y - this.padding);
+ this.maskEl.top.setLeft(0);
+ this.maskEl.top.setTop(0);
+ this.maskEl.top.show();
+
+ this.maskEl.left.setStyle('position', 'absolute');
+ this.maskEl.left.setStyle('z-index', 10000);
+ this.maskEl.left.setSize(box.x - this.padding, box.height + this.padding * 2);
+ this.maskEl.left.setLeft(0);
+ this.maskEl.left.setTop(box.y - this.padding);
+ this.maskEl.left.show();
+
+ this.maskEl.bottom.setStyle('position', 'absolute');
+ this.maskEl.bottom.setStyle('z-index', 10000);
+ this.maskEl.bottom.setSize(Roo.lib.Dom.getDocumentWidth(), Roo.lib.Dom.getDocumentHeight() - box.bottom - this.padding);
+ this.maskEl.bottom.setLeft(0);
+ this.maskEl.bottom.setTop(box.bottom + this.padding);
+ this.maskEl.bottom.show();
+
+ this.maskEl.right.setStyle('position', 'absolute');
+ this.maskEl.right.setStyle('z-index', 10000);
+ this.maskEl.right.setSize(Roo.lib.Dom.getDocumentWidth() - box.right - this.padding, box.height + this.padding * 2);
+ this.maskEl.right.setLeft(box.right + this.padding);
+ this.maskEl.right.setTop(box.y - this.padding);
+ this.maskEl.right.show();
+
+ this.intervalID = window.setInterval(function() {
+ Roo.form.BasicForm.popover.unmask();
+ }, 10000);
+
+ window.onwheel = function(){ return false;};
+
+ (function(){ this.isMasked = true; }).defer(500, this);
+
+ },
+
+ unmask : function()
+ {
+ if(!this.isApplied || !this.isMasked || !this.form || !this.target || !this.form.errorMask){
+ return;
+ }
+
+ this.maskEl.top.setStyle('position', 'absolute');
+ this.maskEl.top.setSize(0, 0).setXY([0, 0]);
+ this.maskEl.top.hide();
+
+ this.maskEl.left.setStyle('position', 'absolute');
+ this.maskEl.left.setSize(0, 0).setXY([0, 0]);
+ this.maskEl.left.hide();
+
+ this.maskEl.bottom.setStyle('position', 'absolute');
+ this.maskEl.bottom.setSize(0, 0).setXY([0, 0]);
+ this.maskEl.bottom.hide();
+
+ this.maskEl.right.setStyle('position', 'absolute');
+ this.maskEl.right.setSize(0, 0).setXY([0, 0]);
+ this.maskEl.right.hide();
+
+ window.onwheel = function(){ return true;};
+
+ if(this.intervalID){
+ window.clearInterval(this.intervalID);
+ this.intervalID = false;
+ }
+
+ this.isMasked = false;
+
+ }
+
+ }
+
+});/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
Roo.each(xitems, this.addxtype, this);
-
-
};
Roo.extend(Roo.form.Form, Roo.form.BasicForm, {
* Collapses this region.
* @param {Boolean} skipAnim (optional) true to collapse the element without animation (if animate is true)
*/
- collapse : function(skipAnim, skipCheck = false){
+ collapse : function(skipAnim, skipCheck){
if(this.collapsed) {
return;
}
* @param {Roo.ContentPanel} this
*/
"render" : true
-
-
+
});
}
if(this.footer){
var te = this.footer.getEl();
- Roo.log("footer:" + te.getHeight());
+ //Roo.log("footer:" + te.getHeight());
height -= te.getHeight();
te.setWidth(width);