// closure these in so they are only created once.
var alpha = /^[a-zA-Z_]+$/;
var alphanum = /^[a-zA-Z0-9_]+$/;
- var email = /^([\w-]+)(\.[\w-]+)*@([\w-]+\.){1,5}([A-Za-z]){2,24}$/;
+ var email = /^([\w'-]+)(\.[\w'-]+)*@([\w-]+\.){1,5}([A-Za-z]){2,24}$/;
var url = /^(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
var urlWeb = /^((https?):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
}
- this.el.removeClass([this.invalidClass, 'is-invalid']);
+ this.inputEl().removeClass([this.invalidClass, 'is-invalid']);
if(this.hasFeedback && this.inputType != 'hidden'){
});
-Roo.bootstrap.form.CardUploader.ID = -1;/*
+Roo.bootstrap.form.CardUploader.ID = -1;/**
+ *
+ * @class Roo.bootstrap.form.MultiLineTag
+ * @param {Object} config The config object
+ *
+ */
+
+Roo.bootstrap.form.MultiLineTag = function(config){
+ Roo.bootstrap.form.MultiLineTag.superclass.constructor.call(this, config);
+
+ this.addEvents({
+ /**
+ * @event beforeload
+ * Fires before a request is made for a new data object. If the beforeload handler returns false
+ * the load action will be canceled.
+ * @param {Roo.boostrap.form.MultiLineTag} this
+ * @param {Store} store
+ * @param {Object} options The loading options that were specified (see {@link #load} for details)
+ */
+ beforeload : true
+ });
+};
+
+Roo.extend(Roo.bootstrap.form.MultiLineTag, Roo.bootstrap.form.Input, {
+ tagRows : [],
+ minimumRow : 2,
+
+ // for combo box
+ displayField : '',
+ valueField : '',
+ placeholder : '',
+ queryParam : '',
+ listWidth : 300,
+ minChars : 2,
+
+ // for combo box store
+ url : undefined,
+ fields : [],
+
+
+
+ getAutoCreate : function()
+ {
+ var config = {
+ cls : 'roo-multi-line-tag form-group'
+ };
+
+ config = this.getAutoCreateLabel( config, {
+ cls : 'roo-multi-line-tag-container'
+ } );
+
+ return config;
+ },
+
+ initEvents : function()
+ {
+ this.tagRows = [];
+
+ for (var i = 0; i < this.minimumRow; i++) {
+ this.addTagRow();
+ }
+ },
+
+ addTagRow : function()
+ {
+ var _this = this;
+
+ var comboBox = Roo.factory({
+ xns: Roo.bootstrap.form,
+ xtype : 'ComboBox',
+ editable : true,
+ triggerAction: 'all',
+ minChars: _this.minChars,
+ displayField: _this.displayField,
+ valueField : _this.valueField,
+ listWidth: _this.listWidth,
+ placeholder : _this.placeholder,
+ queryParam : _this.queryParam,
+ store : {
+ xns : Roo.data,
+ xtype : 'Store',
+ listeners : {
+ beforeload : function(_self, options)
+ {
+ _this.fireEvent('beforeload', _this, _self, options);
+ }
+ },
+ proxy : {
+ xns : Roo.data,
+ xtype : 'HttpProxy',
+ method : 'GET',
+ url : _this.url
+ },
+ reader : {
+ xns : Roo.data,
+ xtype : 'JsonReader',
+ fields : _this.fields
+ }
+ },
+ listeners : {
+ 'render' : function (_self) {
+ _self.inputEl().on('keyup', function(e) {
+ if(_this.shouldAutoAddTagRow()) {
+ _this.addTagRow();
+ }
+ });
+ _self.inputEl().on('change', function(e) {
+ _this.fireEvent('change', _this, _this.getValue(), false);
+ _this.showHideRemoveBtn();
+
+ });
+ },
+ 'select' : function(_self, record, index) {
+ _this.fireEvent('change', _this, _this.getValue(), false);
+ }
+ }
+ });
+
+ var button = Roo.factory({
+ xns : Roo.bootstrap,
+ xtype : 'Button',
+ html : '-'
+ });
+
+ var row = {
+ xns : Roo.bootstrap,
+ xtype : 'Row',
+ items : [
+ comboBox,
+ button
+ ],
+ listeners : {
+ 'render' : function (_self) {
+ this.inputCb = comboBox;
+ this.removeBtn = button;
+
+ this.removeBtn.on('click', function() {
+ _this.removeTagRow(_self);
+ _this.fireEvent('change', _this, _this.getValue(), false);
+ });
+ }
+ }
+ };
+ this.tagRows.push(this.addxtype(row));
+
+ _this.showHideRemoveBtn();
+ },
+
+ // a new tags should be added automatically when all existing tags are not empty
+ shouldAutoAddTagRow : function()
+ {
+ var ret = true;
+
+ Roo.each(this.tagRows, function(r) {
+ if(r.inputCb.getRawValue() == '') {
+ ret = false;
+ }
+ });
+
+ return ret;
+ },
+
+ removeTagRow : function(row)
+ {
+ row.destroy();
+ this.tagRows.splice(this.tagRows.indexOf(row), 1);
+ this.showHideRemoveBtn();
+ },
+
+ // hide all remove buttons if there are {minimumRow} or less tags
+ // hide the remove button for empty tag
+ showHideRemoveBtn : function()
+ {
+ var _this = this;
+
+ Roo.each(this.tagRows, function (r) {
+
+ r.removeBtn.show();
+
+ if(_this.tagRows.length <= _this.minimumRow || r.inputCb.getRawValue() == '') {
+ r.removeBtn.hide();
+ }
+ });
+ },
+
+ getValue : function()
+ {
+ var _this = this;
+ var tags = [];
+ Roo.each(_this.tagRows, function(r) {
+ var value = r.inputCb.getRawValue();
+ if(value != '') {
+ var tag = {};
+ tag[_this.valueField] = r.inputCb.getRawValue();
+ tags.push(tag);
+ }
+ });
+
+ return JSON.stringify(tags);
+ },
+
+ setValue : function(json)
+ {
+
+ // remove all old tags
+ var oldTotal = this.tagRows.length;
+
+ for(var i = 0; i < oldTotal; i ++) {
+ this.removeTagRow(this.tagRows[0]);
+ }
+
+ // empty tag if invalid json
+ var arr = [];
+
+ try {
+ // set new tags
+ arr = JSON.parse(json);
+ }
+ catch {}
+
+ for (var i = 0; i < arr.length; i ++) {
+ this.addTagRow();
+ this.tagRows[i].inputCb.setRawValue(arr[i][this.valueField]);
+ }
+
+ // always add one extra empty tag
+ this.addTagRow();
+
+ // add empty tags until there are {minimumRow} tags
+ while(this.tagRows.length < this.minimumRow) {
+ this.addTagRow();
+ }
+
+ },
+
+ getChildContainer : function()
+ {
+ return Roo.select('.roo-multi-line-tag-container', true).elements[0];
+ }
+});/*
* Based on:
* Ext JS Library 1.1.1
* Copyright(c) 2006-2007, Ext JS, LLC.
/**
* @cfg {Number} maxHeight The maximum height in pixels of the dropdown list before scrollbars are shown (defaults to 300)
*/
- maxHeight: 300,
+ // maxHeight: 300, // not used (change maxHeight in CSS. target the list using listClass)
/**
* @cfg {String} triggerAction The action to execute when the trigger field is activated. Use 'all' to run the
* query specified by the allQuery config option (defaults to 'query')
//this.list = new Roo.Layer({
// shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
//});
+
+ this.list.addClass(this.listClass);
var _this = this;
if (!this.editable) {
Roo.get(document).on('keydown', this.listKeyPress, this);
}
+
+ this.list.setStyle('maxHeight', 'calc(100% - ' + this.list.getTop() + 'px - 50px)');
this.fireEvent('expand', this);
},
singleMode : false,
hiddenField : false,
+
+ /**
+ * @cfg {Boolean} editable False to prevent the user from typing text directly into the field (defaults to true)
+ */
+ editable: true,
UTCDate: function()
{
);
this.inputEl().dom.setAttribute('name', this.name + '____hidden___');
+ if(!this.editable) {
+ this.inputEl().dom.setAttribute('readOnly', true);
+ }
+
},
picker : function()
showPopup : function()
{
+ if(this.readOnly) {
+ return;
+ }
this.picker().show();
this.update();
this.place();
this.picker().hide();
this.viewMode = this.startViewMode;
this.showMode();
+
+ this.inputEl().blur();
this.fireEvent('hidepopup', this, this.date);
{
this.picker().hide();
this.pop.hide();
+
+ this.inputEl().blur();
this.fireEvent('hide', this, this.time);
},
}
node.parentNode.removeChild(node);
+ },
+
+ searchTag : function(dom)
+ {
+ if(this.tag === false) {
+ return;
+ }
+
+ var els = dom.getElementsByTagName(this.tag);
+
+ Roo.each(Array.from(els), function(e){
+ if(e.parentNode == null) {
+ return;
+ }
+ if(this.replaceTag) {
+ this.replaceTag(e);
+ }
+ }, this);
}
};
{
n.parentNode.removeChild(n);
}
+});/**
+ * @class Roo.htmleditor.FilterEmpty
+ * filter empty elements
+ * @constructor
+ * Run a new Empty Filter
+ * @param {Object} config Configuration options
+ */
+
+Roo.htmleditor.FilterEmpty = function(cfg)
+{
+ // no need to apply config.
+ this.walk(cfg.node);
+}
+
+Roo.extend(Roo.htmleditor.FilterEmpty, Roo.htmleditor.FilterBlack,
+{
+
+ tag : true,
+
+
+ replaceTag : function(node)
+ {
+ // start from leaf node
+ if(node.hasChildNodes()) {
+ this.walk(node);
+ }
+
+ // only filter empty leaf element with certain tags
+ if(
+ ['B', 'I', 'U', 'S'].indexOf(node.tagName) < 0
+ ||
+ node.attributes && node.attributes.length > 0
+ ||
+ node.hasChildNodes()
+ ) {
+ return false; // don't walk
+ }
+
+ Roo.htmleditor.FilterBlack.prototype.replaceTag.call(this, node);
+ return false; // don't walk
+
+ }
+
});/**
* @class Roo.htmleditor.FilterKeepChildren
* remove tags but keep children
Roo.htmleditor.FilterParagraph = function(cfg)
{
// no need to apply config.
- this.walk(cfg.node);
+ this.searchTag(cfg.node);
}
Roo.extend(Roo.htmleditor.FilterParagraph, Roo.htmleditor.Filter,
node.parentNode.replaceChild(node.ownerDocument.createElement('BR'),node);
return false; // no need to walk..
}
+
var ar = Array.from(node.childNodes);
for (var i = 0; i < ar.length; i++) {
node.removeChild(ar[i]);
}
});/**
+ * @class Roo.htmleditor.FilterHashLink
+ * remove hash link
+ * @constructor
+ * Run a new Hash Link Filter
+ * @param {Object} config Configuration options
+ */
+
+ Roo.htmleditor.FilterHashLink = function(cfg)
+ {
+ // no need to apply config.
+ // this.walk(cfg.node);
+ this.searchTag(cfg.node);
+ }
+
+ Roo.extend(Roo.htmleditor.FilterHashLink, Roo.htmleditor.Filter,
+ {
+
+ tag : 'A',
+
+
+ replaceTag : function(node)
+ {
+ for(var i = 0; i < node.attributes.length; i ++) {
+ var a = node.attributes[i];
+
+ if(a.name.toLowerCase() == 'href' && a.value.startsWith('#')) {
+ this.removeNodeKeepChildren(node);
+ }
+ }
+
+ return false;
+
+ }
+
+ });/**
* @class Roo.htmleditor.FilterSpan
* filter span's with no attributes out..
* @constructor
Roo.htmleditor.FilterSpan = function(cfg)
{
// no need to apply config.
- this.walk(cfg.node);
+ this.searchTag(cfg.node);
}
Roo.extend(Roo.htmleditor.FilterSpan, Roo.htmleditor.FilterKeepChildren,
{
this.tags = {
- B : [ 'fontWeight' , 'bold'],
- I : [ 'fontStyle' , 'italic'],
+ B : [ 'fontWeight' , 'bold', 'font-weight'],
+ I : [ 'fontStyle' , 'italic', 'font-style'],
//pre : [ 'font-style' , 'italic'],
// h1.. h6 ?? font-size?
- SUP : [ 'verticalAlign' , 'super' ],
- SUB : [ 'verticalAlign' , 'sub' ]
+ SUP : [ 'verticalAlign' , 'super', 'vertical-align'],
+ SUB : [ 'verticalAlign' , 'sub', 'vertical-align']
};
for (var k in this.tags) {
if (node.style[this.tags[k][0]] == this.tags[k][1]) {
inject.push(k);
- node.style.removeProperty(this.tags[k][0]);
+ node.style.removeProperty(this.tags[k][2]);
}
}
if (!inject.length) {
nn.appendChild(nc);
nn = nc;
});
- for(var i = 0;i < cn.length;cn++) {
+ for(var i = 0;i < cn.length;i++) {
node.removeChild(cn[i]);
nn.appendChild(cn[i]);
}
Roo.htmleditor.FilterLongBr = function(cfg)
{
// no need to apply config.
- this.walk(cfg.node);
+ this.searchTag(cfg.node);
}
Roo.extend(Roo.htmleditor.FilterLongBr, Roo.htmleditor.Filter,
-
-
if (!node.previousSibling) {
return false;
}
maxWidth : iw + ' !important', // this is not getting rendered?
margin : m
- }
+ },
+ width: this.align == 'center' ? this.width : '100%'
+
};
+
/*
'<div class="{0}" width="420" height="315" src="{1}" frameborder="0" allowfullscreen>' +
'<a href="{2}">' +
tag: 'div',
style : {
marginTop : '16px',
- textAlign : 'left'
+ textAlign : 'start'
},
align: 'left',
cn : [
if (this.colWidths[0] != false && table[r][c].colspan > 1) {
var el = Roo.htmleditor.Block.factory(table[r][c].cell);
var width = 0;
+ var lv = false;
for(var i = 0; i < table[r][c].colspan; i ++) {
+ if (typeof(this.colWidths[c + i]) != 'undefined') {
+ lv = this.colWidths[c + i];
+ } else {
+ this.colWidths[c + i] = lv;
+ }
width += Math.floor(this.colWidths[c + i]);
}
el.width = width +'%';
this.colWidths[i] = nw;
return;
}
- this.colWidths[i] += otherAdd
+ if (typeof(this.colWidths[i]) == 'undefined') {
+ this.colWidths[i] = otherAdd;
+ } else {
+ this.colWidths[i] += otherAdd;
+ }
}, this);
this.updateWidths(table);
this.colWidths[i] = nw;
return;
}
- this.colWidths[i] -= otherSub
+ if (typeof(this.colWidths[i]) == 'undefined') {
+ this.colWidths[i] = otherSub;
+ } else {
+ this.colWidths[i] -= otherSub;
+ }
+
}, this);
this.updateWidths(table);
if (this.enableBlocks) {
+ Array.from(bd.getElementsByTagName('img')).forEach(function(img) {
+ var fig = img.closest('figure');
+ if (fig) {
+ var bf = new Roo.htmleditor.BlockFigure({
+ node : fig
+ });
+ bf.updateElement();
+ }
+
+ });
new Roo.htmleditor.FilterBlock({ node : div });
}
//?? tidy?
if (this.autoClean) {
-
+ new Roo.htmleditor.FilterBlack({ node : div, tag : this.black});
new Roo.htmleditor.FilterAttributes({
node : div,
attrib_white : [
],
attrib_clean : ['href', 'src' ]
});
+ new Roo.htmleditor.FilterEmpty({ node : div});
var tidy = new Roo.htmleditor.TidySerializer({
inner: true
// should be fonts..
new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT', ':' ]} );
new Roo.htmleditor.FilterParagraph({ node : d });
+ new Roo.htmleditor.FilterHashLink({node : d});
new Roo.htmleditor.FilterSpan({ node : d });
new Roo.htmleditor.FilterLongBr({ node : d });
new Roo.htmleditor.FilterComment({ node : d });
+ new Roo.htmleditor.FilterEmpty({ node : d});
}
/**
* @event layout
* Fires when a layout is performed.
- * @param {Roo.LayoutManager} this
+ * @param {Roo.layout.Manager} this
*/
"layout" : true,
/**
* @event regionresized
* Fires when the user resizes a region.
- * @param {Roo.LayoutRegion} region The resized region
+ * @param {Roo.layout.Region} region The resized region
* @param {Number} newSize The new size (width for east/west, height for north/south)
*/
"regionresized" : true,
/**
* @event regioncollapsed
* Fires when a region is collapsed.
- * @param {Roo.LayoutRegion} region The collapsed region
+ * @param {Roo.layout.Region} region The collapsed region
*/
"regioncollapsed" : true,
/**
* @event regionexpanded
* Fires when a region is expanded.
- * @param {Roo.LayoutRegion} region The expanded region
+ * @param {Roo.layout.Region} region The expanded region
*/
"regionexpanded" : true
});
/**
* Returns the specified region.
* @param {String} target The region key ('center', 'north', 'south', 'east' or 'west')
- * @return {Roo.LayoutRegion}
+ * @return {Roo.layout.Region}
*/
getRegion : function(target){
return this.regions[target.toLowerCase()];
if(!provider){
provider = Roo.state.Manager;
}
- var sm = new Roo.LayoutStateManager();
+ var sm = new Roo.layout.StateManager();
sm.init(this, provider);
},
*/
{
// basically accepts a pannel...
// can accept a layout region..!?!?
- //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
+ //Roo.log('Roo.layout.Border add ' + cfg.xtype)
// theory? children can only be panels??
this.events = {
/**
- * @scope Roo.BasicLayoutRegion
+ * @scope Roo.layout.BasicRegion
*/
/**
* @event beforeremove
* Fires before a panel is removed (or closed). To cancel the removal set "e.cancel = true" on the event argument.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
* @param {Roo.ContentPanel} panel The panel
* @param {Object} e The cancel event object
*/
/**
* @event invalidated
* Fires when the layout for this region is changed.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
*/
"invalidated" : true,
/**
* @event visibilitychange
* Fires when this region is shown or hidden
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
* @param {Boolean} visibility true or false
*/
"visibilitychange" : true,
/**
* @event paneladded
* Fires when a panel is added.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
* @param {Roo.ContentPanel} panel The panel
*/
"paneladded" : true,
/**
* @event panelremoved
* Fires when a panel is removed.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
* @param {Roo.ContentPanel} panel The panel
*/
"panelremoved" : true,
/**
* @event beforecollapse
* Fires when this region before collapse.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
*/
"beforecollapse" : true,
/**
* @event collapsed
* Fires when this region is collapsed.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
*/
"collapsed" : true,
/**
* @event expanded
* Fires when this region is expanded.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
*/
"expanded" : true,
/**
* @event slideshow
* Fires when this region is slid into view.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
*/
"slideshow" : true,
/**
* @event slidehide
* Fires when this region slides out of view.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
*/
"slidehide" : true,
/**
* @event panelactivated
* Fires when a panel is activated.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
* @param {Roo.ContentPanel} panel The activated panel
*/
"panelactivated" : true,
/**
* @event resized
* Fires when the user resizes this region.
- * @param {Roo.LayoutRegion} this
+ * @param {Roo.layout.Region} this
* @param {Number} newSize The new size (width for east/west, height for north/south)
*/
"resized" : true
/**
- * @class Roo.SplitLayoutRegion
- * @extends Roo.LayoutRegion
- * Adds a splitbar and other (private) useful functionality to a {@link Roo.LayoutRegion}.
+ * @class Roo.layout.SplitRegion
+ * @extends Roo.layout.Region
+ * Adds a splitbar and other (private) useful functionality to a {@link Roo.layout.Region}.
*/
Roo.bootstrap.layout.Split = function(config){
this.cursor = config.cursor;
Roo.extend(Roo.bootstrap.panel.Nest, Roo.bootstrap.panel.Content, {
/**
- * @cfg {Roo.BorderLayout} layout The layout for this panel
+ * @cfg {Roo.layout.Border} layout The layout for this panel
*/
layout : false,
/**
* Returns the nested BorderLayout for this panel
- * @return {Roo.BorderLayout}
+ * @return {Roo.layout.Border}
*/
getLayout : function(){
return this.layout;