X-Git-Url: http://git.roojs.org/?a=blobdiff_plain;f=roojs-bootstrap-debug.js;h=87455f01732325aeed95ba567d3cca66eb2386ac;hb=refs%2Fheads%2Fwip_leon_T7605_revamp_image_managment_code;hp=8f4f9b513b33cda645198a2aa537e5b8b99d4167;hpb=a4731897f6fa72bebc326910310b0630b2ce26df;p=roojs1 diff --git a/roojs-bootstrap-debug.js b/roojs-bootstrap-debug.js index 8f4f9b513b..87455f0173 100644 --- a/roojs-bootstrap-debug.js +++ b/roojs-bootstrap-debug.js @@ -17,7 +17,10 @@ Roo.bootstrap.version = ( function() { })(); Roo.bootstrap.menu = Roo.bootstrap.menu || {}; Roo.bootstrap.nav = {}; -Roo.bootstrap.form = {};Roo.bootstrap.panel = {};Roo.bootstrap.layout = {};/* +Roo.bootstrap.form = {};Roo.bootstrap.panel = {};Roo.bootstrap.layout = {}; +Roo.htmleditor = {}; +Roo.namespace('Roo.bootstrap.form.HtmlEditorToolbar'); +/* * Based on: * Ext JS Library 1.1.1 * Copyright(c) 2006-2007, Ext JS, LLC. @@ -577,7 +580,7 @@ Roo.extend(Roo.bootstrap.Component, Roo.BoxComponent, { if (!skip_children) { for(var i =0;i < items.length;i++) { // Roo.log(['add child', items[i]]); - nitems.push(cn.addxtype(Roo.apply({}, items[i]))); + nitems.push(cn.addxtype(items[i].xns == false ? items[i] : Roo.apply({}, items[i]))); } } @@ -4545,10 +4548,16 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component, { : this.el.select('.modal-footer div',true).first(); }, + + closeClick : function() + { + this.hide(); + }, + initEvents : function() { if (this.allow_close) { - this.closeEl.on('click', this.hide, this); + this.closeEl.on('click', this.closeClick, this); } Roo.EventManager.onWindowResize(this.resize, this, true); if (this.editableTitle) { @@ -9157,6 +9166,7 @@ Currently the Table uses multiple headers to try and handle XL / Medium etc... * also adds table-responsive (see bootstrap docs for details) * @cfg {Boolean} loadMask (true|false) default false * @cfg {Boolean} footerShow (true|false) generate tfoot, default true + * @cfg {Boolean} footerRow (true|false) generate tfoot with columns of values, default false * @cfg {Boolean} headerShow (true|false) generate thead, default true * @cfg {Boolean} rowSelection (true|false) default false * @cfg {Boolean} cellSelection (true|false) default false @@ -9341,6 +9351,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { store : false, loadMask : false, footerShow : true, + footerRow : false, headerShow : true, enableColumnResize: true, disableAutoSize: false, @@ -9416,9 +9427,10 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { cfg.cn.push(this.renderBody()); - if(this.footerShow){ + if(this.footerShow || this.footerRow){ cfg.cn.push(this.renderFooter()); } + // where does this come from? //cfg.cls+= ' TableGrid'; } @@ -9979,8 +9991,6 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { return footer; }, - - onLoad : function() { // Roo.log('ds onload'); @@ -10027,7 +10037,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { var tfoot = this.el.select('tfoot', true).first(); - if(this.footerShow && this.auto_hide_footer && this.mainFoot){ + if(this.footerShow && !this.footerRow && this.auto_hide_footer && this.mainFoot){ this.mainFoot.setVisibilityMode(Roo.Element.DISPLAY).hide(); @@ -10037,6 +10047,30 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { this.mainFoot.show(); } } + + if(!this.footerShow && this.footerRow) { + + var tr = { + tag : 'tr', + cn : [] + }; + + for(var i = 0, len = cm.getColumnCount(); i < len; i++){ + var footer = typeof(cm.config[i].footer) == "function" ? cm.config[i].footer(ds, cm.config[i]) : cm.config[i].footer; + var td = { + tag: 'td', + cls : ' x-fcol-' + i, + html: footer + }; + + tr.cn.push(td); + + } + + tfoot.dom.innerHTML = ''; + + tfoot.createChild(tr); + } Roo.each(this.el.select('tbody td', true).elements, function(e){ e.on('mouseover', _this.onMouseover, _this); @@ -10304,7 +10338,7 @@ Roo.extend(Roo.bootstrap.Table, Roo.bootstrap.Component, { var id = false; if(typeof(renderer) !== 'undefined'){ - value = renderer(d.data[cm.getDataIndex(i)], false, d); + value = renderer.call(config, d.data[cm.getDataIndex(i)], false, d); } // if object are returned, then they are expected to be Roo.bootstrap.Component instances // and are rendered into the cells after the row is rendered - using the id for the element. @@ -12512,7 +12546,6 @@ Roo.extend(Roo.bootstrap.form.Input, Roo.bootstrap.Component, { getAutoCreate : function() { - var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign; var id = Roo.id(); @@ -12641,6 +12674,34 @@ Roo.extend(Roo.bootstrap.form.Input, Roo.bootstrap.Component, { inputblock.cn.push(feedback); } }; + + + + cfg = this.getAutoCreateLabel( cfg, inputblock ); + + + + + if (this.parentType === 'Navbar' && this.parent().bar) { + cfg.cls += ' navbar-form'; + } + + if (this.parentType === 'NavGroup' && !(Roo.bootstrap.version == 4 && this.parent().form)) { + // on BS4 we do this only if not form + cfg.cls += ' navbar-form'; + cfg.tag = 'li'; + } + + return cfg; + + }, + /** + * autocreate the label - also used by textara... ?? and others? + */ + getAutoCreateLabel : function( cfg, inputblock ) + { + var align = (!this.labelAlign) ? this.parentLabelAlign() : this.labelAlign; + var indicator = { tag : 'i', cls : 'roo-required-indicator ' + (this.indicatorpos == 'right' ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star', @@ -12784,20 +12845,10 @@ Roo.extend(Roo.bootstrap.form.Input, Roo.bootstrap.Component, { }; - - if (this.parentType === 'Navbar' && this.parent().bar) { - cfg.cls += ' navbar-form'; - } - - if (this.parentType === 'NavGroup' && !(Roo.bootstrap.version == 4 && this.parent().form)) { - // on BS4 we do this only if not form - cfg.cls += ' navbar-form'; - cfg.tag = 'li'; - } - return cfg; - }, + + /** * return the real input element. */ @@ -13037,9 +13088,7 @@ Roo.extend(Roo.bootstrap.form.Input, Roo.bootstrap.Component, { * @return {Mixed} value The field value */ getValue : function(){ - var v = this.inputEl().getValue(); - return v; }, /** @@ -13486,74 +13535,10 @@ Roo.extend(Roo.bootstrap.form.TextArea, Roo.bootstrap.form.Input, { } - if (align ==='left' && this.fieldLabel.length) { - cfg.cn = [ - { - tag: 'label', - 'for' : id, - cls : 'control-label', - html : this.fieldLabel - }, - { - cls : "", - cn: [ - inputblock - ] - } - - ]; - - if(this.labelWidth > 12){ - cfg.cn[0].style = "width: " + this.labelWidth + 'px'; - } - - if(this.labelWidth < 13 && this.labelmd == 0){ - this.labelmd = this.labelWidth; - } - - if(this.labellg > 0){ - cfg.cn[0].cls += ' col-lg-' + this.labellg; - cfg.cn[1].cls += ' col-lg-' + (12 - this.labellg); - } - - if(this.labelmd > 0){ - cfg.cn[0].cls += ' col-md-' + this.labelmd; - cfg.cn[1].cls += ' col-md-' + (12 - this.labelmd); - } - - if(this.labelsm > 0){ - cfg.cn[0].cls += ' col-sm-' + this.labelsm; - cfg.cn[1].cls += ' col-sm-' + (12 - this.labelsm); - } - - if(this.labelxs > 0){ - cfg.cn[0].cls += ' col-xs-' + this.labelxs; - cfg.cn[1].cls += ' col-xs-' + (12 - this.labelxs); - } - - } else if ( this.fieldLabel.length) { - cfg.cn = [ - - { - tag: 'label', - //cls : 'input-group-addon', - html : this.fieldLabel - - }, - - inputblock - - ]; - - } else { - - cfg.cn = [ - - inputblock + + cfg = this.getAutoCreateLabel( cfg, inputblock ); - ]; - - } + if (this.disabled) { input.disabled=true; @@ -13581,11 +13566,11 @@ Roo.extend(Roo.bootstrap.form.TextArea, Roo.bootstrap.form.Input, { } var label = this.el.select('label', true).first(); - var icon = this.el.select('i.fa-star', true).first(); + //var icon = this.el.select('i.fa-star', true).first(); - if(label && icon){ - icon.remove(); - } + //if(label && icon){ + // icon.remove(); + //} this.el.removeClass( this.validClass); this.inputEl().removeClass('is-invalid'); @@ -13627,9 +13612,9 @@ Roo.extend(Roo.bootstrap.form.TextArea, Roo.bootstrap.form.Input, { var label = this.el.select('label', true).first(); var icon = this.el.select('i.fa-star', true).first(); - if(label && icon){ - icon.remove(); - } + //if(label && icon){ + // icon.remove(); + //} if (Roo.bootstrap.version == 3) { this.el.addClass(this.validClass); } else { @@ -13670,21 +13655,22 @@ Roo.extend(Roo.bootstrap.form.TextArea, Roo.bootstrap.form.Input, { this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]); } - if(this.disabled || this.allowBlank){ + if(this.disabled){ return; } var label = this.el.select('label', true).first(); - var icon = this.el.select('i.fa-star', true).first(); + //var icon = this.el.select('i.fa-star', true).first(); - if(!this.getValue().length && label && !icon){ - this.el.createChild({ + //if(!this.getValue().length && label && !icon){ + /* this.el.createChild({ tag : 'i', cls : 'text-danger fa fa-lg fa-star', tooltip : 'This field is required', style : 'margin-right:5px;' }, label, true); - } + */ + //} if (Roo.bootstrap.version == 3) { this.el.addClass(this.invalidClass); @@ -13969,12 +13955,14 @@ Roo.extend(Roo.bootstrap.form.TriggerField, Roo.bootstrap.form.Input, { cls : 'roo-required-indicator ' + (this.indicatorpos == 'right' ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star', tooltip : 'This field is required' }; - if (Roo.bootstrap.version == 4) { + + if (this.allowBlank) { indicator = { tag : 'i', style : 'display:none' }; } + if (align ==='left' && this.fieldLabel.length) { @@ -15186,8 +15174,8 @@ Roo.data.Store = function(config){ * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args * * @param {Proxy} - * @param {Object} return from JsonData.reader() - success, totalRecords, records - * @param {Object} load options + * @param {Object} ret return data from JsonData.reader() - success, totalRecords, records + * @param {Object} opts - load Options * @param {Object} jsonData from your request (normally this contains the Exception) */ loadexception : true @@ -16193,24 +16181,24 @@ Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, { // thse are take from connection... /** - * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined) + * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined) */ /** - * @cfg {Object} extraParams (Optional) An object containing properties which are used as + * @cfg {Object} extraParams An object containing properties which are used as * extra parameters to each request made by this object. (defaults to undefined) */ /** - * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added + * @cfg {Object} defaultHeaders An object containing request headers which are added * to each request made by this object. (defaults to undefined) */ /** - * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET) + * @cfg {String} method (GET|POST) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET) */ /** - * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000) + * @cfg {Number} timeout The timeout in milliseconds to be used for requests. (defaults to 30000) */ /** - * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false) + * @cfg {Boolean} autoAbort Whether this request should abort any pending requests. (defaults to false) * @type Boolean */ @@ -17333,12 +17321,13 @@ Roo.extend(Roo.bootstrap.form.ComboBox, Roo.bootstrap.form.TriggerField, { cls : 'roo-required-indicator ' + (this.indicatorpos == 'right' ? 'right' : 'left') +'-indicator text-danger fa fa-lg fa-star', tooltip : 'This field is required' }; - if (Roo.bootstrap.version == 4) { + + if (this.allowBlank) { indicator = { tag : 'i', style : 'display:none' }; - } + } if (align ==='left' && this.fieldLabel.length) { cfg.cls += ' roo-form-group-label-left' + (Roo.bootstrap.version == 4 ? ' row' : ''); @@ -23948,6 +23937,7 @@ Roo.apply(Roo.bootstrap.form.DateField, { * @class Roo.bootstrap.form.TimeField * @extends Roo.bootstrap.form.Input * Bootstrap DateField class + * @cfg {Number} minuteStep the minutes is always the multiple of a fixed number, default 1 * * * @constructor @@ -23990,6 +23980,7 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input, { * valid according to {@link Date#parseDate} (defaults to 'H:i'). */ format : "H:i", + minuteStep : 1, getAutoCreate : function() { @@ -24217,7 +24208,11 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input, { update: function() { - + // default minute is a multiple of minuteStep + if(typeof(this.time) === 'undefined') { + this.time = new Date(); + this.time = this.time.add(Date.MINUTE, Math.round(parseInt(this.time.format('i')) / this.minuteStep) * this.minuteStep - parseInt(this.time.format('i'))); + } this.time = (typeof(this.time) === 'undefined') ? new Date() : this.time; this.fill(); @@ -24370,14 +24365,16 @@ Roo.extend(Roo.bootstrap.form.TimeField, Roo.bootstrap.form.Input, { onIncrementMinutes: function() { Roo.log('onIncrementMinutes'); - this.time = this.time.add(Date.MINUTE, 1); + var minutesToAdd = Math.round((parseInt(this.time.format('i')) + this.minuteStep) / this.minuteStep) * this.minuteStep - parseInt(this.time.format('i')); + this.time = this.time.add(Date.MINUTE, minutesToAdd); this.update(); }, onDecrementMinutes: function() { Roo.log('onDecrementMinutes'); - this.time = this.time.add(Date.MINUTE, -1); + var minutesToSubtract = parseInt(this.time.format('i')) - Math.round((parseInt(this.time.format('i')) - this.minuteStep) / this.minuteStep) * this.minuteStep; + this.time = this.time.add(Date.MINUTE, -1 * minutesToSubtract); this.update(); }, @@ -26005,52 +26002,544 @@ Roo.extend(Roo.bootstrap.form.SecurePass, Roo.bootstrap.form.Input, { return this.IsLongEnough(pwd, 6) || !this.IsLongEnough(pwd, 0); } +});Roo.rtf = {}; // namespace +Roo.rtf.Hex = function(hex) +{ + this.hexstr = hex; +}; +Roo.rtf.Paragraph = function(opts) +{ + this.content = []; ///??? is that used? +};Roo.rtf.Span = function(opts) +{ + this.value = opts.value; +}; + +Roo.rtf.Group = function(parent) +{ + // we dont want to acutally store parent - it will make debug a nightmare.. + this.content = []; + this.cn = []; + + + +}; + +Roo.rtf.Group.prototype = { + ignorable : false, + content: false, + cn: false, + addContent : function(node) { + // could set styles... + this.content.push(node); + }, + addChild : function(cn) + { + this.cn.push(cn); + }, + // only for images really... + toDataURL : function() + { + var mimetype = false; + switch(true) { + case this.content.filter(function(a) { return a.value == 'pngblip' } ).length > 0: + mimetype = "image/png"; + break; + case this.content.filter(function(a) { return a.value == 'jpegblip' } ).length > 0: + mimetype = "image/jpeg"; + break; + default : + return 'about:blank'; // ?? error? + } + + + var hexstring = this.content[this.content.length-1].value; + + return 'data:' + mimetype + ';base64,' + btoa(hexstring.match(/\w{2}/g).map(function(a) { + return String.fromCharCode(parseInt(a, 16)); + }).join("")); + } + +}; +// this looks like it's normally the {rtf{ .... }} +Roo.rtf.Document = function() +{ + // we dont want to acutally store parent - it will make debug a nightmare.. + this.rtlch = []; + this.content = []; + this.cn = []; + +}; +Roo.extend(Roo.rtf.Document, Roo.rtf.Group, { + addChild : function(cn) + { + this.cn.push(cn); + switch(cn.type) { + case 'rtlch': // most content seems to be inside this?? + case 'listtext': + case 'shpinst': + this.rtlch.push(cn); + return; + default: + this[cn.type] = cn; + } + + }, + + getElementsByType : function(type) + { + var ret = []; + this._getElementsByType(type, ret, this.cn, 'rtf'); + return ret; + }, + _getElementsByType : function (type, ret, search_array, path) + { + search_array.forEach(function(n,i) { + if (n.type == type) { + n.path = path + '/' + n.type + ':' + i; + ret.push(n); + } + if (n.cn.length > 0) { + this._getElementsByType(type, ret, n.cn, path + '/' + n.type+':'+i); + } + },this); + } + }); -Roo.htmleditor = {}; +Roo.rtf.Ctrl = function(opts) +{ + this.value = opts.value; + this.param = opts.param; +}; /** - * @class Roo.htmleditor.Filter - * Base Class for filtering htmleditor stuff. - do not use this directly - extend it. - * @cfg {DomElement} node The node to iterate and filter - * @cfg {boolean|String|Array} tag Tags to replace - * @constructor - * Create a new Filter. - * @param {Object} config Configuration options + * + * + * based on this https://github.com/iarna/rtf-parser + * it's really only designed to extract pict from pasted RTF + * + * usage: + * + * var images = new Roo.rtf.Parser().parse(a_string).filter(function(g) { return g.type == 'pict'; }); + * + * */ + -Roo.htmleditor.Filter = function(cfg) { - Roo.apply(this.cfg); - // this does not actually call walk as it's really just a abstract class -} - -Roo.htmleditor.Filter.prototype = { +Roo.rtf.Parser = function(text) { + //super({objectMode: true}) + this.text = ''; + this.parserState = this.parseText; - node: false, + // these are for interpeter... + this.doc = {}; + ///this.parserState = this.parseTop + this.groupStack = []; + this.hexStore = []; + this.doc = false; - tag: false, - - // overrride to do replace comments. - replaceComment : false, + this.groups = []; // where we put the return. - // overrride to do replace or do stuff with tags.. - replaceTag : false, + for (var ii = 0; ii < text.length; ++ii) { + ++this.cpos; + + if (text[ii] === '\n') { + ++this.row; + this.col = 1; + } else { + ++this.col; + } + this.parserState(text[ii]); + } - walk : function(dom) + + +}; +Roo.rtf.Parser.prototype = { + text : '', // string being parsed.. + controlWord : '', + controlWordParam : '', + hexChar : '', + doc : false, + group: false, + groupStack : false, + hexStore : false, + + + cpos : 0, + row : 1, // reportin? + col : 1, // + + + push : function (el) { - Roo.each( Array.from(dom.childNodes), function( e ) { - switch(true) { - - case e.nodeType == 8 && this.replaceComment !== false: // comment - this.replaceComment(e); - return; - - case e.nodeType != 1: //not a node. - return; - - case this.tag === true: // everything + var m = 'cmd'+ el.type; + if (typeof(this[m]) == 'undefined') { + Roo.log('invalid cmd:' + el.type); + return; + } + this[m](el); + //Roo.log(el); + }, + flushHexStore : function() + { + if (this.hexStore.length < 1) { + return; + } + var hexstr = this.hexStore.map( + function(cmd) { + return cmd.value; + }).join(''); + + this.group.addContent( new Roo.rtf.Hex( hexstr )); + + + this.hexStore.splice(0) + + }, + + cmdgroupstart : function() + { + this.flushHexStore(); + if (this.group) { + this.groupStack.push(this.group); + } + // parent.. + if (this.doc === false) { + this.group = this.doc = new Roo.rtf.Document(); + return; + + } + this.group = new Roo.rtf.Group(this.group); + }, + cmdignorable : function() + { + this.flushHexStore(); + this.group.ignorable = true; + }, + cmdendparagraph : function() + { + this.flushHexStore(); + this.group.addContent(new Roo.rtf.Paragraph()); + }, + cmdgroupend : function () + { + this.flushHexStore(); + var endingGroup = this.group; + + + this.group = this.groupStack.pop(); + if (this.group) { + this.group.addChild(endingGroup); + } + + + + var doc = this.group || this.doc; + //if (endingGroup instanceof FontTable) { + // doc.fonts = endingGroup.table + //} else if (endingGroup instanceof ColorTable) { + // doc.colors = endingGroup.table + //} else if (endingGroup !== this.doc && !endingGroup.get('ignorable')) { + if (endingGroup.ignorable === false) { + //code + this.groups.push(endingGroup); + // Roo.log( endingGroup ); + } + //Roo.each(endingGroup.content, function(item)) { + // doc.addContent(item); + //} + //process.emit('debug', 'GROUP END', endingGroup.type, endingGroup.get('ignorable')) + //} + }, + cmdtext : function (cmd) + { + this.flushHexStore(); + if (!this.group) { // an RTF fragment, missing the {\rtf1 header + //this.group = this.doc + return; // we really don't care about stray text... + } + this.group.addContent(new Roo.rtf.Span(cmd)); + }, + cmdcontrolword : function (cmd) + { + this.flushHexStore(); + if (!this.group.type) { + this.group.type = cmd.value; + return; + } + this.group.addContent(new Roo.rtf.Ctrl(cmd)); + // we actually don't care about ctrl words... + return ; + /* + var method = 'ctrl$' + cmd.value.replace(/-(.)/g, (_, char) => char.toUpperCase()) + if (this[method]) { + this[method](cmd.param) + } else { + if (!this.group.get('ignorable')) process.emit('debug', method, cmd.param) + } + */ + }, + cmdhexchar : function(cmd) { + this.hexStore.push(cmd); + }, + cmderror : function(cmd) { + throw cmd.value; + }, + + /* + _flush (done) { + if (this.text !== '\u0000') this.emitText() + done() + } + */ + + + parseText : function(c) + { + if (c === '\\') { + this.parserState = this.parseEscapes; + } else if (c === '{') { + this.emitStartGroup(); + } else if (c === '}') { + this.emitEndGroup(); + } else if (c === '\x0A' || c === '\x0D') { + // cr/lf are noise chars + } else { + this.text += c; + } + }, + + parseEscapes: function (c) + { + if (c === '\\' || c === '{' || c === '}') { + this.text += c; + this.parserState = this.parseText; + } else { + this.parserState = this.parseControlSymbol; + this.parseControlSymbol(c); + } + }, + parseControlSymbol: function(c) + { + if (c === '~') { + this.text += '\u00a0'; // nbsp + this.parserState = this.parseText + } else if (c === '-') { + this.text += '\u00ad'; // soft hyphen + } else if (c === '_') { + this.text += '\u2011'; // non-breaking hyphen + } else if (c === '*') { + this.emitIgnorable(); + this.parserState = this.parseText; + } else if (c === "'") { + this.parserState = this.parseHexChar; + } else if (c === '|') { // formula cacter + this.emitFormula(); + this.parserState = this.parseText; + } else if (c === ':') { // subentry in an index entry + this.emitIndexSubEntry(); + this.parserState = this.parseText; + } else if (c === '\x0a') { + this.emitEndParagraph(); + this.parserState = this.parseText; + } else if (c === '\x0d') { + this.emitEndParagraph(); + this.parserState = this.parseText; + } else { + this.parserState = this.parseControlWord; + this.parseControlWord(c); + } + }, + parseHexChar: function (c) + { + if (/^[A-Fa-f0-9]$/.test(c)) { + this.hexChar += c; + if (this.hexChar.length >= 2) { + this.emitHexChar(); + this.parserState = this.parseText; + } + return; + } + this.emitError("Invalid character \"" + c + "\" in hex literal."); + this.parserState = this.parseText; + + }, + parseControlWord : function(c) + { + if (c === ' ') { + this.emitControlWord(); + this.parserState = this.parseText; + } else if (/^[-\d]$/.test(c)) { + this.parserState = this.parseControlWordParam; + this.controlWordParam += c; + } else if (/^[A-Za-z]$/.test(c)) { + this.controlWord += c; + } else { + this.emitControlWord(); + this.parserState = this.parseText; + this.parseText(c); + } + }, + parseControlWordParam : function (c) { + if (/^\d$/.test(c)) { + this.controlWordParam += c; + } else if (c === ' ') { + this.emitControlWord(); + this.parserState = this.parseText; + } else { + this.emitControlWord(); + this.parserState = this.parseText; + this.parseText(c); + } + }, + + + + + emitText : function () { + if (this.text === '') { + return; + } + this.push({ + type: 'text', + value: this.text, + pos: this.cpos, + row: this.row, + col: this.col + }); + this.text = '' + }, + emitControlWord : function () + { + this.emitText(); + if (this.controlWord === '') { + // do we want to track this - it seems just to cause problems. + //this.emitError('empty control word'); + } else { + this.push({ + type: 'controlword', + value: this.controlWord, + param: this.controlWordParam !== '' && Number(this.controlWordParam), + pos: this.cpos, + row: this.row, + col: this.col + }); + } + this.controlWord = ''; + this.controlWordParam = ''; + }, + emitStartGroup : function () + { + this.emitText(); + this.push({ + type: 'groupstart', + pos: this.cpos, + row: this.row, + col: this.col + }); + }, + emitEndGroup : function () + { + this.emitText(); + this.push({ + type: 'groupend', + pos: this.cpos, + row: this.row, + col: this.col + }); + }, + emitIgnorable : function () + { + this.emitText(); + this.push({ + type: 'ignorable', + pos: this.cpos, + row: this.row, + col: this.col + }); + }, + emitHexChar : function () + { + this.emitText(); + this.push({ + type: 'hexchar', + value: this.hexChar, + pos: this.cpos, + row: this.row, + col: this.col + }); + this.hexChar = '' + }, + emitError : function (message) + { + this.emitText(); + this.push({ + type: 'error', + value: message, + row: this.row, + col: this.col, + char: this.cpos //, + //stack: new Error().stack + }); + }, + emitEndParagraph : function () { + this.emitText(); + this.push({ + type: 'endparagraph', + pos: this.cpos, + row: this.row, + col: this.col + }); + } + +} ; +/** + * @class Roo.htmleditor.Filter + * Base Class for filtering htmleditor stuff. - do not use this directly - extend it. + * @cfg {DomElement} node The node to iterate and filter + * @cfg {boolean|String|Array} tag Tags to replace + * @constructor + * Create a new Filter. + * @param {Object} config Configuration options + */ + + + +Roo.htmleditor.Filter = function(cfg) { + Roo.apply(this.cfg); + // this does not actually call walk as it's really just a abstract class +} + + +Roo.htmleditor.Filter.prototype = { + + node: false, + + tag: false, + + // overrride to do replace comments. + replaceComment : false, + + // overrride to do replace or do stuff with tags.. + replaceTag : false, + + walk : function(dom) + { + Roo.each( Array.from(dom.childNodes), function( e ) { + switch(true) { + + case e.nodeType == 8 && this.replaceComment !== false: // comment + this.replaceComment(e); + return; + + case e.nodeType != 1: //not a node. + return; + + case this.tag === true: // everything case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'object' && this.tag.indexOf(":") > -1: case e.tagName.indexOf(":") > -1 && typeof(this.tag) == 'string' && this.tag == ":": case typeof(this.tag) == 'object' && this.tag.indexOf(e.tagName) > -1: // array and it matches. @@ -26510,7 +26999,7 @@ Roo.htmleditor.FilterWord = function(cfg) this.replaceAname(cfg.node); // this is disabled as the removal is done by other filters; // this.walk(cfg.node); - + this.replaceImageTable(cfg.node); } @@ -26718,7 +27207,8 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter, parent = p.parentNode, doc = parent.ownerDocument, items = []; - + + //Roo.log("Parsing: " + p.innerText) ; var listtype = 'ul'; while (ns) { if (ns.nodeType != 1) { @@ -26726,22 +27216,38 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter, continue; } if (!ns.className.match(/(MsoListParagraph|ql-indent-1)/i)) { + //Roo.log("Missing para r q1indent - got:" + ns.className); break; } var spans = ns.getElementsByTagName('span'); + if (ns.hasAttribute('style') && ns.getAttribute('style').match(/mso-list/)) { items.push(ns); ns = ns.nextSibling; has_list = true; - if (spans.length && spans[0].hasAttribute('style')) { - var style = this.styleToObject(spans[0]); - if (typeof(style['font-family']) != 'undefined' && !style['font-family'].match(/Symbol/)) { - listtype = 'ol'; + if (!spans.length) { + continue; + } + var ff = ''; + var se = spans[0]; + for (var i = 0; i < spans.length;i++) { + se = spans[i]; + if (se.hasAttribute('style') && se.hasAttribute('style') && se.style.fontFamily != '') { + ff = se.style.fontFamily; + break; } } + + + //Roo.log("got font family: " + ff); + if (typeof(ff) != 'undefined' && !ff.match(/(Symbol|Wingdings)/) && "·o".indexOf(se.innerText.trim()) < 0) { + listtype = 'ol'; + } continue; } + //Roo.log("no mso-list?"); + var spans = ns.getElementsByTagName('span'); if (!spans.length) { break; @@ -26852,9 +27358,63 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter, - } - + }, + replaceImageTable : function(doc) + { + /* +
+ | |
+ | + |