filter word documents - add support for converting bullet points
authorAlan <alan@roojs.com>
Thu, 17 Mar 2022 09:38:23 +0000 (17:38 +0800)
committerAlan <alan@roojs.com>
Thu, 17 Mar 2022 09:38:23 +0000 (17:38 +0800)
docs/src/Roo_HtmlEditorCore.js.html
docs/src/Roo_htmleditor_FilterWord.js.html
roojs-bootstrap-debug.js
roojs-bootstrap.js

index e122395..06627fc 100644 (file)
             });
         }
         </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">this.autoClean</span><span class="jsdoc-syntax">) {
+            </span><span class="jsdoc-keyword">new </span><span class="jsdoc-var">Roo.htmleditor.FilterWord</span><span class="jsdoc-syntax">({ </span><span class="jsdoc-var">node </span><span class="jsdoc-syntax">: </span><span class="jsdoc-var">d </span><span class="jsdoc-syntax">});
+
             </span><span class="jsdoc-keyword">new </span><span class="jsdoc-var">Roo.htmleditor.FilterStyleToTag</span><span class="jsdoc-syntax">({ </span><span class="jsdoc-var">node </span><span class="jsdoc-syntax">: </span><span class="jsdoc-var">d </span><span class="jsdoc-syntax">});
             </span><span class="jsdoc-keyword">new </span><span class="jsdoc-var">Roo.htmleditor.FilterAttributes</span><span class="jsdoc-syntax">({
                 </span><span class="jsdoc-var">node </span><span class="jsdoc-syntax">: </span><span class="jsdoc-var">d</span><span class="jsdoc-syntax">,
index 0972096..068de8a 100644 (file)
                 </span><span class="jsdoc-var">node.removeChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">cn</span><span class="jsdoc-syntax">);
                 </span><span class="jsdoc-var">node.parentNode.insertBefore</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">cn</span><span class="jsdoc-syntax">, </span><span class="jsdoc-var">node</span><span class="jsdoc-syntax">);
                 </span><span class="jsdoc-comment">// move node to parent - and clean it..
-                </span><span class="jsdoc-var">this.replaceTag</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">cn</span><span class="jsdoc-syntax">);
+                </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">cn.nodeType </span><span class="jsdoc-syntax">== 1) {
+                    </span><span class="jsdoc-var">this.replaceTag</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">cn</span><span class="jsdoc-syntax">);
+                }
+
             }
             </span><span class="jsdoc-var">node.parentNode.removeChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">node</span><span class="jsdoc-syntax">);
             </span><span class="jsdoc-comment">/// no need to iterate chidlren = it's got none..
             </span><span class="jsdoc-var">doc </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">parent.ownerDocument</span><span class="jsdoc-syntax">,
             </span><span class="jsdoc-var">items </span><span class="jsdoc-syntax">= [];
         </span><span class="jsdoc-keyword">while </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">ns</span><span class="jsdoc-syntax">) {
-            </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(!</span><span class="jsdoc-var">ns.className.match</span><span class="jsdoc-syntax">(/MsoListParagraph/)) {
+            </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">ns.nodeType </span><span class="jsdoc-syntax">!= 1) {
+                </span><span class="jsdoc-var">ns </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">ns.nextSibling</span><span class="jsdoc-syntax">;
+                </span><span class="jsdoc-keyword">continue</span><span class="jsdoc-syntax">;
+            }
+            </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(!</span><span class="jsdoc-var">ns.className.match</span><span class="jsdoc-syntax">(/MsoListParagraph/i)) {
                 </span><span class="jsdoc-keyword">break</span><span class="jsdoc-syntax">;
             }
             </span><span class="jsdoc-var">items.push</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">ns</span><span class="jsdoc-syntax">);
         </span><span class="jsdoc-var">items.forEach</span><span class="jsdoc-syntax">(</span><span class="jsdoc-keyword">function</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">n</span><span class="jsdoc-syntax">) {
             </span><span class="jsdoc-var">parent.removeChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">n</span><span class="jsdoc-syntax">);
             </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">spans </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">n.getElementsByTagName</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">'span'</span><span class="jsdoc-syntax">);
-            </span><span class="jsdoc-var">n.removeChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">spans.item</span><span class="jsdoc-syntax">(0)); </span><span class="jsdoc-comment">// remove the fake bullet.
+            </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(!</span><span class="jsdoc-var">spans.length </span><span class="jsdoc-syntax">|| !</span><span class="jsdoc-var">n.isEqualNode</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">spans.item</span><span class="jsdoc-syntax">(0)</span><span class="jsdoc-var">.parentNode</span><span class="jsdoc-syntax">)) {
+                </span><span class="jsdoc-keyword">return</span><span class="jsdoc-syntax">; </span><span class="jsdoc-comment">// skip it...
+            </span><span class="jsdoc-syntax">}
+
             </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">style </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">this.styleToObject</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">n</span><span class="jsdoc-syntax">);
+            </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-keyword">typeof</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">style</span><span class="jsdoc-syntax">[</span><span class="jsdoc-string">'mso-list'</span><span class="jsdoc-syntax">]) == </span><span class="jsdoc-string">'undefined'</span><span class="jsdoc-syntax">) {
+                </span><span class="jsdoc-keyword">return</span><span class="jsdoc-syntax">; </span><span class="jsdoc-comment">// skip it.
+            </span><span class="jsdoc-syntax">}
+            </span><span class="jsdoc-var">n.removeChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">spans.item</span><span class="jsdoc-syntax">(0)); </span><span class="jsdoc-comment">// remove the fake bullet.
             </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">nlvl </span><span class="jsdoc-syntax">= (</span><span class="jsdoc-var">style</span><span class="jsdoc-syntax">[</span><span class="jsdoc-string">'mso-list'</span><span class="jsdoc-syntax">]</span><span class="jsdoc-var">.split</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">' '</span><span class="jsdoc-syntax">)[1]</span><span class="jsdoc-var">.replace</span><span class="jsdoc-syntax">(/level/,</span><span class="jsdoc-string">''</span><span class="jsdoc-syntax">) *1) - 1;
             </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">nlvl </span><span class="jsdoc-syntax">&gt; </span><span class="jsdoc-var">lvl</span><span class="jsdoc-syntax">) {
-                </span><span class="jsdoc-keyword">new </span><span class="jsdoc-var">indent
+                </span><span class="jsdoc-comment">//new indent
                 </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">nul </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">doc.createElement</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">'ul'</span><span class="jsdoc-syntax">); </span><span class="jsdoc-comment">// what about number lists...
                 </span><span class="jsdoc-var">last_li.appendChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">nul</span><span class="jsdoc-syntax">);
                 </span><span class="jsdoc-var">stack</span><span class="jsdoc-syntax">[</span><span class="jsdoc-var">nlvl</span><span class="jsdoc-syntax">] = </span><span class="jsdoc-var">nul</span><span class="jsdoc-syntax">;
             }
+            </span><span class="jsdoc-var">lvl </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">nlvl</span><span class="jsdoc-syntax">;
 
-            </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">nli </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">stack</span><span class="jsdoc-syntax">[</span><span class="jsdoc-var">nlvl</span><span class="jsdoc-syntax">]</span><span class="jsdoc-var">.appendChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">'li'</span><span class="jsdoc-syntax">);
+            </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">nli </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">stack</span><span class="jsdoc-syntax">[</span><span class="jsdoc-var">nlvl</span><span class="jsdoc-syntax">]</span><span class="jsdoc-var">.appendChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">doc.createElement</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">'li'</span><span class="jsdoc-syntax">));
             </span><span class="jsdoc-var">last_li </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">nli</span><span class="jsdoc-syntax">;
             </span><span class="jsdoc-comment">// copy children of p into nli
-            </span><span class="jsdoc-keyword">while</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">p.firstChild</span><span class="jsdoc-syntax">) {
-                </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">fc </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">p.firstChild</span><span class="jsdoc-syntax">;
-                </span><span class="jsdoc-var">p.removeChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">fc</span><span class="jsdoc-syntax">);
+            </span><span class="jsdoc-keyword">while</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">n.firstChild</span><span class="jsdoc-syntax">) {
+                </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">fc </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">n.firstChild</span><span class="jsdoc-syntax">;
+                </span><span class="jsdoc-var">n.removeChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">fc</span><span class="jsdoc-syntax">);
                 </span><span class="jsdoc-var">nli.appendChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">fc</span><span class="jsdoc-syntax">);
             }
 
index 9eb90a1..d417f6c 100644 (file)
@@ -26512,7 +26512,10 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
                 node.removeChild(cn);
                 node.parentNode.insertBefore(cn, node);
                 // move node to parent - and clean it..
-                this.replaceTag(cn);
+                if (cn.nodeType == 1) {
+                    this.replaceTag(cn);
+                }
+                
             }
             node.parentNode.removeChild(node);
             /// no need to iterate chidlren = it's got none..
@@ -26580,7 +26583,7 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
             ret[kv[0]] = kv[1];
         });
         return ret;
-    }
+    },
     
     
     replaceDocBullets : function(doc)
@@ -26597,9 +26600,14 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
         // gather all the siblings.
         var ns = p,
             parent = p.parentNode,
+            doc = parent.ownerDocument,
             items = []; 
         while (ns) {
-            if (!ns.className.match(/MsoListParagraph/)) {
+            if (ns.nodeType != 1) {
+                ns = ns.nextSibling;
+                continue;
+            }
+            if (!ns.className.match(/MsoListParagraph/i)) {
                 break;
             }
             items.push(ns);
@@ -26607,13 +26615,42 @@ Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
             
         }
         var ul = parent.ownerDocument.createElement('ul'); // what about number lists...
-        
+        parent.insertBefore(ul, p);
+        var lvl = 0;
+        var stack = [ ul ];
+        var last_li = false;
         items.forEach(function(n) {
             parent.removeChild(n);
             var spans = n.getElementsByTagName('span');
+            if (!spans.length || !n.isEqualNode(spans.item(0).parentNode)) {
+                return; // skip it...
+            }
+            
+            var style = this.styleToObject(n);
+            if (typeof(style['mso-list']) == 'undefined') {
+                return; // skip it.
+            }
             n.removeChild(spans.item(0)); // remove the fake bullet.
+            var nlvl = (style['mso-list'].split(' ')[1].replace(/level/,'') *1) - 1;
+            if (nlvl > lvl) {
+                //new indent
+                var nul = doc.createElement('ul'); // what about number lists...
+                last_li.appendChild(nul);
+                stack[nlvl] = nul;
+            }
+            lvl = nlvl;
+            
+            var nli = stack[nlvl].appendChild(doc.createElement('li'));
+            last_li = nli;
+            // copy children of p into nli
+            while(n.firstChild) {
+                var fc = n.firstChild;
+                n.removeChild(fc);
+                nli.appendChild(fc);
+            }
+             
             
-        });
+        },this);
         
         
         
@@ -29312,6 +29349,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             });
         }
         if (this.autoClean) {
+            new Roo.htmleditor.FilterWord({ node : d });
+            
             new Roo.htmleditor.FilterStyleToTag({ node : d });
             new Roo.htmleditor.FilterAttributes({
                 node : d,
index 03397f1..d7469b1 100644 (file)
@@ -1146,11 +1146,13 @@ if(!C.length){A.removeAttribute('style');}}return true;}});
 Roo.htmleditor.FilterWord=function(A){this.replaceDocBullets(A.node);this.walk(A.node);};Roo.extend(Roo.htmleditor.FilterWord,Roo.htmleditor.Filter,{tag:true,replaceTag:function(A){if(A.nodeName=='SPAN'&&!A.hasAttributes()&&A.childNodes.length==1&&A.firstChild.nodeName=="#text"){var B=A.firstChild;
 A.removeChild(B);if(A.getAttribute('lang')!='zh-CN'){A.parentNode.insertBefore(A.ownerDocument.createTextNode(" "),A);}A.parentNode.insertBefore(B,A);if(A.getAttribute('lang')!='zh-CN'){A.parentNode.insertBefore(A.ownerDocument.createTextNode(" "),A);}A.parentNode.removeChild(A);
 return false;}if(A.tagName.toLowerCase().match(/^(style|script|applet|embed|noframes|noscript)$/)){A.parentNode.removeChild(A);return false;}if(A.tagName.toLowerCase().match(/^(meta|link|\\?xml:|st1:|o:|v:|font)/)){while(A.childNodes.length){var cn=A.childNodes[0];
-A.removeChild(cn);A.parentNode.insertBefore(cn,A);this.replaceTag(cn);}A.parentNode.removeChild(A);return false;}if(A.className.length){var cn=A.className.split(/\W+/);var C=[];Roo.each(cn,function(F){if(F.match(/Mso[a-zA-Z]+/)){return;}C.push(F);});A.className=C.length?C.join(' '):'';
-if(!C.length){A.removeAttribute("class");}}if(A.hasAttribute("lang")){A.removeAttribute("lang");}if(A.hasAttribute("style")){var D=A.getAttribute("style").split(";");var E=[];Roo.each(D,function(s){if(!s.match(/:/)){return;}var kv=s.split(":");if(kv[0].match(/^(mso-|line|font|background|margin|padding|color)/)){return;
-}E.push(s);});A.setAttribute("style",E.length?E.join(';'):'');if(!E.length){A.removeAttribute('style');}}return true;},styleToObject:function(A){var B=A.getAttribute("style").split(";");var C={};Roo.each(B,function(s){if(!s.match(/:/)){return;}var kv=s.split(":");
-C[kv[0]]=kv[1];});return C;}replaceDocBullets:function(doc){var listpara=doc.getElementsByClassName('MsoListParagraph');while(listpara.length){this.replaceDocBullet(listpara.item(0));}},replaceDocBullet:function(p){var ns=p,A=p.parentNode,B=[];while(ns){if(!ns.className.match(/MsoListParagraph/)){break;
-}B.push(ns);ns=ns.nextSibling;}var ul=A.ownerDocument.createElement('ul');B.forEach(function(n){A.removeChild(n);var C=n.getElementsByTagName('span');n.removeChild(C.item(0));});}});
+A.removeChild(cn);A.parentNode.insertBefore(cn,A);if(cn.nodeType==1){this.replaceTag(cn);}}A.parentNode.removeChild(A);return false;}if(A.className.length){var cn=A.className.split(/\W+/);var C=[];Roo.each(cn,function(F){if(F.match(/Mso[a-zA-Z]+/)){return;
+}C.push(F);});A.className=C.length?C.join(' '):'';if(!C.length){A.removeAttribute("class");}}if(A.hasAttribute("lang")){A.removeAttribute("lang");}if(A.hasAttribute("style")){var D=A.getAttribute("style").split(";");var E=[];Roo.each(D,function(s){if(!s.match(/:/)){return;
+}var kv=s.split(":");if(kv[0].match(/^(mso-|line|font|background|margin|padding|color)/)){return;}E.push(s);});A.setAttribute("style",E.length?E.join(';'):'');if(!E.length){A.removeAttribute('style');}}return true;},styleToObject:function(A){var B=A.getAttribute("style").split(";");
+var C={};Roo.each(B,function(s){if(!s.match(/:/)){return;}var kv=s.split(":");C[kv[0]]=kv[1];});return C;},replaceDocBullets:function(A){var B=A.getElementsByClassName('MsoListParagraph');while(B.length){this.replaceDocBullet(B.item(0));}},replaceDocBullet:function(p){var ns=p,A=p.parentNode,B=A.ownerDocument,C=[];
+while(ns){if(ns.nodeType!=1){ns=ns.nextSibling;continue;}if(!ns.className.match(/MsoListParagraph/i)){break;}C.push(ns);ns=ns.nextSibling;}var ul=A.ownerDocument.createElement('ul');A.insertBefore(ul,p);var D=0;var E=[ul];var F=false;C.forEach(function(n){A.removeChild(n);
+var G=n.getElementsByTagName('span');if(!G.length||!n.isEqualNode(G.item(0).parentNode)){return;}var H=this.styleToObject(n);if(typeof(H['mso-list'])=='undefined'){return;}n.removeChild(G.item(0));var I=(H['mso-list'].split(' ')[1].replace(/level/,'')*1)-1;
+if(I>D){var J=B.createElement('ul');F.appendChild(J);E[I]=J;}D=I;var K=E[I].appendChild(B.createElement('li'));F=K;while(n.firstChild){var fc=n.firstChild;n.removeChild(fc);K.appendChild(fc);}},this);}});
 // Roo/htmleditor/FilterStyleToTag.js
 Roo.htmleditor.FilterStyleToTag=function(A){this.tags={B:['fontWeight','bold'],I:['fontStyle','italic'],SUP:['verticalAlign','super'],SUB:['verticalAlign','sub']};Roo.apply(this,A);this.walk(A.node);};Roo.extend(Roo.htmleditor.FilterStyleToTag,Roo.htmleditor.Filter,{tag:true,tags:false,replaceTag:function(A){if(A.getAttribute("style")===null){return true;
 }var B=[];for(var k in this.tags){if(A.style[this.tags[k][0]]==this.tags[k][1]){B.push(k);A.style.removeProperty(this.tags[k][0]);}}if(!B.length){return true;}var cn=Array.from(A.childNodes);var nn=A;Roo.each(B,function(t){var nc=A.ownerDocument.createElement(t);
@@ -1267,28 +1269,29 @@ this.pushValue();},onPasteEvent:function(e,v){var cd=(e.browserEvent.clipboardDa
 this.insertAtCursor('<img src=" + url + ">');return false;}if(cd.types.indexOf('text/html')<0){return false;}var C=[];var D=cd.getData('text/html');if(cd.types.indexOf('text/rtf')>-1){var E=new Roo.rtf.Parser(cd.getData('text/rtf'));C=E.doc?E.doc.getElementsByType('pict'):[];
 }C=C.filter(function(g){return !g.path.match(/^rtf\/(head|pgdsctbl|listtable|footerf)/);}).map(function(g){return g.toDataURL();}).filter(function(g){return g!='about:blank';});D=this.cleanWordChars(D);var d=(new DOMParser().parseFromString(D,'text/html')).body;
 var sn=this.getParentElement();if(d.getElementsByTagName('table').length&&sn&&sn.closest('table')){e.preventDefault();this.insertAtCursor("You can not nest tables");return false;}if(C.length>0){Roo.each(d.getElementsByTagName('img'),function(F,i){F.setAttribute('src',C[i]);
-});}if(this.autoClean){new Roo.htmleditor.FilterStyleToTag({node:d});new Roo.htmleditor.FilterAttributes({node:d,attrib_white:['href','src','name','align','colspan','rowspan','data-display','data-width'],attrib_clean:['href','src']});new Roo.htmleditor.FilterBlack({node:d,tag:this.black}
-);new Roo.htmleditor.FilterKeepChildren({node:d,tag:['FONT','O:P']});new Roo.htmleditor.FilterParagraph({node:d});new Roo.htmleditor.FilterSpan({node:d});new Roo.htmleditor.FilterLongBr({node:d});new Roo.htmleditor.FilterComment({node:d});}if(this.enableBlocks){Array.from(d.getElementsByTagName('img')).forEach(function(F){if(F.closest('figure')){return;
-}var G=new Roo.htmleditor.BlockFigure({image_src:F.src});G.updateElement(F);});}this.insertAtCursor(d.innerHTML.replace(/&nbsp;/g,' '));if(this.enableBlocks){Roo.htmleditor.Block.initAll(this.doc.body);}e.preventDefault();return false;},onDestroy:function(){if(this.rendered){}
-},onFirstFocus:function(){this.assignDocWin();this.undoManager=new Roo.lib.UndoManager(100,(this.doc.body||this.doc.documentElement));this.activated=true;if(Roo.isGecko){this.win.focus();var s=this.win.getSelection();if(!s.focusNode||s.focusNode.nodeType!=3){var r=s.getRangeAt(0);
-r.selectNodeContents((this.doc.body||this.doc.documentElement));r.collapse(true);this.deferFocus();}try{this.execCmd('useCSS',true);this.execCmd('styleWithCSS',false);}catch(e){}}this.owner.fireEvent('activate',this);},adjustFont:function(A){var B=A.cmd=='increasefontsize'?1:-1;
-var v=parseInt(this.doc.queryCommandValue('FontSize')||3,10);if(Roo.isSafari){var sm={10:1,13:2,16:3,18:4,24:5,32:6,48:7};v=(v<10)?10:v;v=(v>48)?48:v;v=typeof(sm[v])=='undefined'?1:sm[v];}v=Math.max(1,v+B);this.execCmd('FontSize',v);},onEditorEvent:function(e){if(e&&(e.ctrlKey||e.metaKey)&&e.keyCode===90){return;
-}if(e&&e.target.nodeName=='BODY'&&e.type=="mouseup"&&this.doc.body.lastChild){var lc=this.doc.body.lastChild;while((lc.nodeType==3&&lc.nodeValue=='')||lc.id=='gtx-trans'){lc=lc.previousSibling;}if(lc.nodeType==1&&lc.nodeName!='BR'){var ns=this.doc.createElement('br');
-this.doc.body.appendChild(ns);range=this.doc.createRange();range.setStartAfter(ns);range.collapse(true);var A=this.win.getSelection();A.removeAllRanges();A.addRange(range);}}this.fireEditorEvent(e);this.syncValue();},fireEditorEvent:function(e){this.owner.fireEvent('editorevent',this,e);
-},insertTag:function(tg){if(tg.toLowerCase()=='span'||tg.toLowerCase()=='code'||tg.toLowerCase()=='sup'||tg.toLowerCase()=='sub'){range=this.createRange(this.getSelection());var A=this.doc.createElement(tg.toLowerCase());A.appendChild(range.extractContents());
-range.insertNode(A);return;}this.execCmd("formatblock",tg);this.undoManager.addEvent();},insertText:function(A){var B=this.createRange();B.deleteContents();B.insertNode(this.doc.createTextNode(A));this.undoManager.addEvent();},relayCmd:function(A,B){switch(A){case 'justifyleft':case 'justifyright':case 'justifycenter':var n=this.getParentElement();
-var td=n.closest('td');if(td){var bl=Roo.htmleditor.Block.factory(td);bl.textAlign=A.replace('justify','');bl.updateElement();this.owner.fireEvent('editorevent',this);return;}this.execCmd('styleWithCSS',true);break;case 'bold':case 'italic':this.execCmd('styleWithCSS',false);
-break;default:break;}this.win.focus();this.execCmd(A,B);this.owner.fireEvent('editorevent',this);this.owner.deferFocus();},execCmd:function(A,B){this.doc.execCommand(A,false,B===undefined?null:B);this.syncValue();},insertAtCursor:function(A){if(!this.activated){return;
-}if(Roo.isGecko||Roo.isOpera||Roo.isSafari){this.win.focus();var B,C;var D=this.win;if(D.getSelection&&D.getSelection().getRangeAt){this.createRange(this.getSelection()).deleteContents();B=D.getSelection().getRangeAt(0);C=typeof(A)=='string'?B.createContextualFragment(A):A;
-B.insertNode(C);B=B.cloneRange();B.collapse(false);D.getSelection().removeAllRanges();D.getSelection().addRange(B);}else if(D.document.selection&&D.document.selection.createRange){var E=typeof(A)=='string'?A:A.outerHTML;D.document.selection.createRange().pasteHTML(E);
-}else{var E=typeof(A)=='string'?A:A.outerHTML;this.execCmd('InsertHTML',E);}this.syncValue();this.deferFocus();}},mozKeyPress:function(e){if(e.ctrlKey){var c=e.getCharCode(),A;if(c>0){c=String.fromCharCode(c).toLowerCase();switch(c){case 'b':A='bold';break;
-case 'i':A='italic';break;case 'u':A='underline';break;}if(A){this.relayCmd(A);e.preventDefault();}}}},fixKeys:function(){if(Roo.isIE){return function(e){var k=e.getKey(),r;if(k==e.TAB){e.stopEvent();r=this.doc.selection.createRange();if(r){r.collapse(true);
-r.pasteHTML('&#160;&#160;&#160;&#160;');this.deferFocus();}return;}};}else if(Roo.isOpera){return function(e){var k=e.getKey();if(k==e.TAB){e.stopEvent();this.win.focus();this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');this.deferFocus();}};}else if(Roo.isSafari){return function(e){var k=e.getKey();
-if(k==e.TAB){e.stopEvent();this.execCmd('InsertText','\t');this.deferFocus();return;}this.mozKeyPress(e);};}}(),getAllAncestors:function(){var p=this.getSelectedNode();var a=[];if(!p){a.push(p);p=this.getParentElement();}while(p&&(p.nodeType==1)&&(p.tagName.toLowerCase()!='body')){a.push(p);
-p=p.parentNode;}a.push(this.doc.body);return a;},lastSel:false,lastSelNode:false,getSelection:function(){this.assignDocWin();return Roo.lib.Selection.wrap(Roo.isIE?this.doc.selection:this.win.getSelection(),this.doc);},selectNode:function(A,B){var C=A.ownerDocument.createRange();
-try{C.selectNode(A);}catch(e){C.selectNodeContents(A);}if(B===true){C.collapse(true);}var s=this.win.getSelection();s.removeAllRanges();s.addRange(C);},getSelectedNode:function(){var A=this.createRange(this.getSelection()).cloneRange();if(Roo.isIE){var B=A.parentElement();
-while(true){var C=A.duplicate();C.moveToElementText(B);if(C.inRange(A)){break;}if((B.nodeType!=1)||(B.tagName.toLowerCase()=='body')){break;}B=B.parentElement;}return B;}var ac=A.commonAncestorContainer;if(ac.nodeType==3){ac=ac.parentNode;}var ar=ac.childNodes;
-var D=[];var E=[];var F=false;for(var i=0;i<ar.length;i++){if((ar[i].nodeType==3)&&(!ar[i].data.length)){continue;}if(this.rangeIntersectsNode(A,ar[i])&&this.rangeCompareNode(A,ar[i])==3){D.push(ar[i]);continue;}if((ar[i].nodeType==1)&&this.rangeIntersectsNode(A,ar[i])&&(this.rangeCompareNode(A,ar[i])>0)){E.push(ar[i]);
+});}if(this.autoClean){new Roo.htmleditor.FilterWord({node:d});new Roo.htmleditor.FilterStyleToTag({node:d});new Roo.htmleditor.FilterAttributes({node:d,attrib_white:['href','src','name','align','colspan','rowspan','data-display','data-width'],attrib_clean:['href','src']}
+);new Roo.htmleditor.FilterBlack({node:d,tag:this.black});new Roo.htmleditor.FilterKeepChildren({node:d,tag:['FONT','O:P']});new Roo.htmleditor.FilterParagraph({node:d});new Roo.htmleditor.FilterSpan({node:d});new Roo.htmleditor.FilterLongBr({node:d});new Roo.htmleditor.FilterComment({node:d}
+);}if(this.enableBlocks){Array.from(d.getElementsByTagName('img')).forEach(function(F){if(F.closest('figure')){return;}var G=new Roo.htmleditor.BlockFigure({image_src:F.src});G.updateElement(F);});}this.insertAtCursor(d.innerHTML.replace(/&nbsp;/g,' '));if(this.enableBlocks){Roo.htmleditor.Block.initAll(this.doc.body);
+}e.preventDefault();return false;},onDestroy:function(){if(this.rendered){}},onFirstFocus:function(){this.assignDocWin();this.undoManager=new Roo.lib.UndoManager(100,(this.doc.body||this.doc.documentElement));this.activated=true;if(Roo.isGecko){this.win.focus();
+var s=this.win.getSelection();if(!s.focusNode||s.focusNode.nodeType!=3){var r=s.getRangeAt(0);r.selectNodeContents((this.doc.body||this.doc.documentElement));r.collapse(true);this.deferFocus();}try{this.execCmd('useCSS',true);this.execCmd('styleWithCSS',false);
+}catch(e){}}this.owner.fireEvent('activate',this);},adjustFont:function(A){var B=A.cmd=='increasefontsize'?1:-1;var v=parseInt(this.doc.queryCommandValue('FontSize')||3,10);if(Roo.isSafari){var sm={10:1,13:2,16:3,18:4,24:5,32:6,48:7};v=(v<10)?10:v;v=(v>48)?48:v;
+v=typeof(sm[v])=='undefined'?1:sm[v];}v=Math.max(1,v+B);this.execCmd('FontSize',v);},onEditorEvent:function(e){if(e&&(e.ctrlKey||e.metaKey)&&e.keyCode===90){return;}if(e&&e.target.nodeName=='BODY'&&e.type=="mouseup"&&this.doc.body.lastChild){var lc=this.doc.body.lastChild;
+while((lc.nodeType==3&&lc.nodeValue=='')||lc.id=='gtx-trans'){lc=lc.previousSibling;}if(lc.nodeType==1&&lc.nodeName!='BR'){var ns=this.doc.createElement('br');this.doc.body.appendChild(ns);range=this.doc.createRange();range.setStartAfter(ns);range.collapse(true);
+var A=this.win.getSelection();A.removeAllRanges();A.addRange(range);}}this.fireEditorEvent(e);this.syncValue();},fireEditorEvent:function(e){this.owner.fireEvent('editorevent',this,e);},insertTag:function(tg){if(tg.toLowerCase()=='span'||tg.toLowerCase()=='code'||tg.toLowerCase()=='sup'||tg.toLowerCase()=='sub'){range=this.createRange(this.getSelection());
+var A=this.doc.createElement(tg.toLowerCase());A.appendChild(range.extractContents());range.insertNode(A);return;}this.execCmd("formatblock",tg);this.undoManager.addEvent();},insertText:function(A){var B=this.createRange();B.deleteContents();B.insertNode(this.doc.createTextNode(A));
+this.undoManager.addEvent();},relayCmd:function(A,B){switch(A){case 'justifyleft':case 'justifyright':case 'justifycenter':var n=this.getParentElement();var td=n.closest('td');if(td){var bl=Roo.htmleditor.Block.factory(td);bl.textAlign=A.replace('justify','');
+bl.updateElement();this.owner.fireEvent('editorevent',this);return;}this.execCmd('styleWithCSS',true);break;case 'bold':case 'italic':this.execCmd('styleWithCSS',false);break;default:break;}this.win.focus();this.execCmd(A,B);this.owner.fireEvent('editorevent',this);
+this.owner.deferFocus();},execCmd:function(A,B){this.doc.execCommand(A,false,B===undefined?null:B);this.syncValue();},insertAtCursor:function(A){if(!this.activated){return;}if(Roo.isGecko||Roo.isOpera||Roo.isSafari){this.win.focus();var B,C;var D=this.win;
+if(D.getSelection&&D.getSelection().getRangeAt){this.createRange(this.getSelection()).deleteContents();B=D.getSelection().getRangeAt(0);C=typeof(A)=='string'?B.createContextualFragment(A):A;B.insertNode(C);B=B.cloneRange();B.collapse(false);D.getSelection().removeAllRanges();
+D.getSelection().addRange(B);}else if(D.document.selection&&D.document.selection.createRange){var E=typeof(A)=='string'?A:A.outerHTML;D.document.selection.createRange().pasteHTML(E);}else{var E=typeof(A)=='string'?A:A.outerHTML;this.execCmd('InsertHTML',E);
+}this.syncValue();this.deferFocus();}},mozKeyPress:function(e){if(e.ctrlKey){var c=e.getCharCode(),A;if(c>0){c=String.fromCharCode(c).toLowerCase();switch(c){case 'b':A='bold';break;case 'i':A='italic';break;case 'u':A='underline';break;}if(A){this.relayCmd(A);
+e.preventDefault();}}}},fixKeys:function(){if(Roo.isIE){return function(e){var k=e.getKey(),r;if(k==e.TAB){e.stopEvent();r=this.doc.selection.createRange();if(r){r.collapse(true);r.pasteHTML('&#160;&#160;&#160;&#160;');this.deferFocus();}return;}};}else if(Roo.isOpera){return function(e){var k=e.getKey();
+if(k==e.TAB){e.stopEvent();this.win.focus();this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');this.deferFocus();}};}else if(Roo.isSafari){return function(e){var k=e.getKey();if(k==e.TAB){e.stopEvent();this.execCmd('InsertText','\t');this.deferFocus();
+return;}this.mozKeyPress(e);};}}(),getAllAncestors:function(){var p=this.getSelectedNode();var a=[];if(!p){a.push(p);p=this.getParentElement();}while(p&&(p.nodeType==1)&&(p.tagName.toLowerCase()!='body')){a.push(p);p=p.parentNode;}a.push(this.doc.body);return a;
+},lastSel:false,lastSelNode:false,getSelection:function(){this.assignDocWin();return Roo.lib.Selection.wrap(Roo.isIE?this.doc.selection:this.win.getSelection(),this.doc);},selectNode:function(A,B){var C=A.ownerDocument.createRange();try{C.selectNode(A);}catch(e){C.selectNodeContents(A);
+}if(B===true){C.collapse(true);}var s=this.win.getSelection();s.removeAllRanges();s.addRange(C);},getSelectedNode:function(){var A=this.createRange(this.getSelection()).cloneRange();if(Roo.isIE){var B=A.parentElement();while(true){var C=A.duplicate();C.moveToElementText(B);
+if(C.inRange(A)){break;}if((B.nodeType!=1)||(B.tagName.toLowerCase()=='body')){break;}B=B.parentElement;}return B;}var ac=A.commonAncestorContainer;if(ac.nodeType==3){ac=ac.parentNode;}var ar=ac.childNodes;var D=[];var E=[];var F=false;for(var i=0;i<ar.length;
+i++){if((ar[i].nodeType==3)&&(!ar[i].data.length)){continue;}if(this.rangeIntersectsNode(A,ar[i])&&this.rangeCompareNode(A,ar[i])==3){D.push(ar[i]);continue;}if((ar[i].nodeType==1)&&this.rangeIntersectsNode(A,ar[i])&&(this.rangeCompareNode(A,ar[i])>0)){E.push(ar[i]);
 continue;}if(!this.rangeIntersectsNode(A,ar[i])||(this.rangeCompareNode(A,ar[i])==0)){continue;}F=true;}if(!D.length&&E.length){D=E;}if(F||!D.length||(D.length>1)){return false;}return D[0];},createRange:function(A){if(typeof A!="undefined"){try{return A.getRangeAt?A.getRangeAt(0):A.createRange();
 }catch(e){return this.doc.createRange();}}else{return this.doc.createRange();}},getParentElement:function(){this.assignDocWin();var A=Roo.isIE?this.doc.selection:this.win.getSelection();var B=this.createRange(A);try{var p=B.commonAncestorContainer;while(p.nodeType==3){p=p.parentNode;
 }return p;}catch(e){return null;}},rangeIntersectsNode:function(A,B){var C=B.ownerDocument.createRange();try{C.selectNode(B);}catch(e){C.selectNodeContents(B);}var D=A.cloneRange();D.collapse(true);var E=A.cloneRange();E.collapse(false);var F=C.cloneRange();