sync
authorAlan <alan@roojs.com>
Fri, 31 Dec 2021 07:29:00 +0000 (15:29 +0800)
committerAlan <alan@roojs.com>
Fri, 31 Dec 2021 07:29:00 +0000 (15:29 +0800)
19 files changed:
Roo/HtmlEditorCore.js
Roo/form/HtmlEditor.js
Roo/form/HtmlEditor/ToolbarContext.js
Roo/htmleditor/Block.js
Roo/htmleditor/BlockFigure.js
Roo/htmleditor/BlockTd.js
Roo/lib/Range.js
buildSDK/dependancy_core.txt
docs/src/Roo_HtmlEditorCore.js.html
docs/src/Roo_htmleditor_Block.js.html
docs/src/Roo_htmleditor_FilterStyleToTag.js.html
examples/form/htmledit.html
examples/form/htmledit.js
roojs-all.js
roojs-core-debug.js
roojs-core.js
roojs-debug.js
roojs-ui-debug.js
roojs-ui.js

index 03d9997..9689931 100644 (file)
@@ -1048,8 +1048,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         // should we cache this!!!!
         
-        
-        
+         
          
         var range = this.createRange(this.getSelection()).cloneRange();
         
@@ -1113,6 +1112,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         return nodes[0];
     },
+    
+    
     createRange: function(sel)
     {
         // this has strange effects when using with 
index 514f12b..ba10aa8 100644 (file)
@@ -246,8 +246,19 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
          
         
     },
-
-     
+    /**
+     * get the Context selected node
+     * @returns {DomElement|boolean} selected node if active or false if none
+     * 
+     */
+    getSelectedNode : function()
+    {
+        if (this.toolbars.length < 2 || !this.toolbars[1].tb) {
+            return false;
+        }
+        return this.toolbars[1].tb.selectedNode;
+    
+    },
     // private
     onRender : function(ct, position)
     {
index d08f024..e2413dc 100644 (file)
@@ -324,7 +324,7 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         // this forces an id..
         Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e) {
              e.classList.remove('roo-ed-selection');
-        })
+        });
         //Roo.select('.roo-ed-selection', false, this.editorcore.doc).removeClass('roo-ed-selection');
         //Roo.get(node).addClass('roo-ed-selection');
       
index de9727e..7e3c164 100644 (file)
@@ -107,14 +107,17 @@ Roo.htmleditor.Block.prototype = {
             // but kiss for now.
             n = node.getElementsByTagName(tag).item(0);
         }
+        if (!n) {
+            return '';
+        }
         if (attr == 'html') {
             return n.innerHTML;
         }
         if (attr == 'style') {
-            return n.style[style]
+            return n.style[style]
         }
         
-        return Roo.get(n).attr(attr);
+        return n.hasAttribute(attr) ? n.getAttribute(attr) : '';
             
     },
     /**
index 2c64369..c52c260 100644 (file)
@@ -175,7 +175,7 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                     {
                         var b  = block();
                         b.caption_display = b.caption_display == 'block' ? 'none' : 'block';
-                        this.setText(b.caption_display == 'block' ? "Hide Caption" : "Show Caption")
+                        this.setText(b.caption_display == 'block' ? "Hide Caption" : "Show Caption");
                         b.updateElement();
                         syncValue();
                         toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
@@ -183,7 +183,7 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                     }
                 },
                 xns : rooui.Toolbar
-            },
+            }
         ];
         
     },
@@ -206,7 +206,7 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
                 'max-width':  this.width,
                 width : 'auto',
                 margin:  0,
-                padding: '10px',
+                padding: '10px'
                 
             },
             align : this.align,
index 9e432a9..b6022ca 100644 (file)
@@ -315,10 +315,10 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                                 }
                             },
                             xns : rooui.menu
-                        },
+                        }
                     ]
                 }
-            },
+            }
             
             // align... << fixme
             
index f71b2ba..513f9fc 100644 (file)
@@ -29,8 +29,8 @@ Roo.apply(Roo.lib.Range.prototype,
     {
         if (typeof(str) != 'string') {
             // assume it's a array.
-            for(var k of str) {
-                var r = this.closest(k);
+            for(var i = 0;i < str.length;i++) {
+                var r = this.closest(str[i]);
                 if (r !== false) {
                     return r;
                 }
index 13a62f2..1f805bc 100644 (file)
@@ -30,6 +30,7 @@ Roo.lib.Motion
 Roo.lib.Scroll
 Roo.lib.UndoManager
 Roo.lib.Range
+Roo.lib.Selection
 // --- end if base ---
 
 
index 36541d9..3db7cdc 100644 (file)
@@ -73,6 +73,7 @@
          */
         </span><span class="jsdoc-var">editorevent</span><span class="jsdoc-syntax">: </span><span class="jsdoc-keyword">true
 
+
     </span><span class="jsdoc-syntax">});
 
     </span><span class="jsdoc-comment">// at this point this.owner is set, so we can start working out the whitelisted / blacklisted elements
         }
         </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">this.enableBlocks</span><span class="jsdoc-syntax">) {
 
-            </span><span class="jsdoc-var">Array.from</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">d.getElementByTagType</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">'img'</span><span class="jsdoc-syntax">))</span><span class="jsdoc-var">.forEach</span><span class="jsdoc-syntax">(</span><span class="jsdoc-keyword">function</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">img</span><span class="jsdoc-syntax">) {
+            </span><span class="jsdoc-var">Array.from</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">d.getElementsByTagName</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">'img'</span><span class="jsdoc-syntax">))</span><span class="jsdoc-var">.forEach</span><span class="jsdoc-syntax">(</span><span class="jsdoc-keyword">function</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">img</span><span class="jsdoc-syntax">) {
                 </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">img.closest</span><span class="jsdoc-syntax">(</span><span class="jsdoc-string">'figure'</span><span class="jsdoc-syntax">)) { </span><span class="jsdoc-comment">// assume!! that it's aready
                     </span><span class="jsdoc-keyword">return</span><span class="jsdoc-syntax">;
                 }
-                </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">fig  </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">Roo.htmleditor.BlockFigure</span><span class="jsdoc-syntax">({
+                </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">fig  </span><span class="jsdoc-syntax">= </span><span class="jsdoc-keyword">new </span><span class="jsdoc-var">Roo.htmleditor.BlockFigure</span><span class="jsdoc-syntax">({
                     </span><span class="jsdoc-var">image_src  </span><span class="jsdoc-syntax">: </span><span class="jsdoc-var">img.src
                 </span><span class="jsdoc-syntax">});
                 </span><span class="jsdoc-var">fig.updateElement</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">img</span><span class="jsdoc-syntax">); </span><span class="jsdoc-comment">// replace it..
         }
 
 
-        </span><span class="jsdoc-var">this.insertAtCursor</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">d.innerHTML</span><span class="jsdoc-syntax">);
+        </span><span class="jsdoc-var">this.insertAtCursor</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">d.innerHTML.replace</span><span class="jsdoc-syntax">(/&amp;nbsp;/g,</span><span class="jsdoc-string">' '</span><span class="jsdoc-syntax">));
         </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">this.enableBlocks</span><span class="jsdoc-syntax">) {
             </span><span class="jsdoc-var">Roo.htmleditor.Block.initAll</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">this.doc.body</span><span class="jsdoc-syntax">);
         }
index 36b723b..0a202ec 100644 (file)
             // but kiss for now.
             </span><span class="jsdoc-var">n </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">node.getElementsByTagName</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">tag</span><span class="jsdoc-syntax">)</span><span class="jsdoc-var">.item</span><span class="jsdoc-syntax">(0);
         }
+        </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(!</span><span class="jsdoc-var">n</span><span class="jsdoc-syntax">) {
+            </span><span class="jsdoc-keyword">return </span><span class="jsdoc-string">''</span><span class="jsdoc-syntax">;
+        }
         </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">attr </span><span class="jsdoc-syntax">== </span><span class="jsdoc-string">'html'</span><span class="jsdoc-syntax">) {
             </span><span class="jsdoc-keyword">return </span><span class="jsdoc-var">n.innerHTML</span><span class="jsdoc-syntax">;
         }
         </span><span class="jsdoc-keyword">if </span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">attr </span><span class="jsdoc-syntax">== </span><span class="jsdoc-string">'style'</span><span class="jsdoc-syntax">) {
-            </span><span class="jsdoc-keyword">return </span><span class="jsdoc-var">n.style</span><span class="jsdoc-syntax">[</span><span class="jsdoc-var">style</span><span class="jsdoc-syntax">]
+            </span><span class="jsdoc-keyword">return </span><span class="jsdoc-var">n.style</span><span class="jsdoc-syntax">[</span><span class="jsdoc-var">style</span><span class="jsdoc-syntax">];
         }
 
-        </span><span class="jsdoc-keyword">return </span><span class="jsdoc-var">Roo.get</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">n</span><span class="jsdoc-syntax">)</span><span class="jsdoc-var">.attr</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">attr</span><span class="jsdoc-syntax">);
+        </span><span class="jsdoc-keyword">return </span><span class="jsdoc-var">n.hasAttribute</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">attr</span><span class="jsdoc-syntax">) ? </span><span class="jsdoc-var">n.getAttribute</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">attr</span><span class="jsdoc-syntax">) : </span><span class="jsdoc-string">''</span><span class="jsdoc-syntax">;
 
     },
     </span><span class="jsdoc-comment">/**
index cc953b1..9e9ae4f 100644 (file)
@@ -61,7 +61,7 @@
         </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">cn </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">Array.from</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">node.childNodes</span><span class="jsdoc-syntax">);
         </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">nn </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">node</span><span class="jsdoc-syntax">;
         </span><span class="jsdoc-var">Roo.each</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">inject</span><span class="jsdoc-syntax">, </span><span class="jsdoc-keyword">function</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">t</span><span class="jsdoc-syntax">) {
-            </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">nc </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">node.ownerDocument.createelement</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">t</span><span class="jsdoc-syntax">);
+            </span><span class="jsdoc-keyword">var </span><span class="jsdoc-var">nc </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">node.ownerDocument.createElement</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">t</span><span class="jsdoc-syntax">);
             </span><span class="jsdoc-var">nn.appendChild</span><span class="jsdoc-syntax">(</span><span class="jsdoc-var">nc</span><span class="jsdoc-syntax">);
             </span><span class="jsdoc-var">nn </span><span class="jsdoc-syntax">= </span><span class="jsdoc-var">nc</span><span class="jsdoc-syntax">;
         });
index a5afcd3..1897677 100644 (file)
@@ -76,7 +76,8 @@
         <script type="text/javascript" src="../../Roo/htmleditor/BlockTable.js"></script>
         <script type="text/javascript" src="../../Roo/htmleditor/BlockFigure.js"></script>
         <script type="text/javascript" src="../../Roo/htmleditor/BlockTd.js"></script>
-                <script type="text/javascript" src="../../Roo/htmleditor/FilterBlock.js"></script>
+        <script type="text/javascript" src="../../Roo/htmleditor/FilterBlock.js"></script>
+        <script type="text/javascript" src="../../Roo/htmleditor/FilterStyleToTag.js"></script>
 
         <script type="text/javascript" src="../../Roo/form/HtmlEditor/ToolbarContext.js"></script>
         <script type="text/javascript" src="../../Roo/menu/Item.js"></script>        
index 77bacda..d68ee73 100644 (file)
@@ -29,8 +29,9 @@ Roo.onReady(function(){
                 autoClean : true,
                 bodyCls : 'undoreset pressrelease mo-grey',
                 stylesheets : [ 
-                    '/web.MediaOutreach/Pman/PressRelease/templates/images/css/editor.css',
-                    '../../css/undoreset.css'
+                    '../../css/undoreset.css',
+                    '/web.MediaOutreach/Pman/PressRelease/templates/images/css/editor.css'
+                    
                     
                 ],
                 toolbars : [    
@@ -127,7 +128,7 @@ Roo.onReady(function(){
                 id:'bio',
                 name : 'bio',
                 fieldLabel:'Biography',
-                width:1000,
+                width:1100,
                 height:600,
                 resizable: 's' /// where the handles should got..
 
index d1dcbe7..1147e62 100644 (file)
@@ -220,6 +220,15 @@ if(this.timer!==false){clearTimeout(this.timer);}this.timer=false;this.merge=fal
 }else{el.undoManager.undo();}e.preventDefault();}});this.scope.addEventListener('keyup',function(e){if((e.ctrlKey||e.metaKey)&&e.keyCode===90){e.preventDefault();}});var t=this;el.addEventListener('input',function(e){if(el.innerHTML==t.current_html){return;
 }if(t.timer!==false){clearTimeout(t.timer);t.timer=false;}t.timer=setTimeout(function(){t.merge=false;},1000);t.addEvent(t.merge);t.merge=true;});},addEvent:function(A){A=typeof(A)=='undefined'?false:A;this.scope.undoManager.transact({scope:this.scope,oldHTML:this.current_html,newHTML:this.scope.innerHTML,execute:function(){}
 ,undo:function(){this.scope.innerHTML=this.current_html=this.oldHTML;},redo:function(){this.scope.innerHTML=this.current_html=this.newHTML;}},false);this.merge=A;this.current_html=this.scope.innerHTML;}};
+// Roo/lib/Range.js
+Roo.lib.Range=function(){};Roo.lib.Range.wrap=function(r){return Roo.apply(r,Roo.lib.Range.prototype);};Roo.apply(Roo.lib.Range.prototype,{closest:function(A){if(typeof(A)!='string'){for(var i=0;i<A.length;i++){var r=this.closest(A[i]);if(r!==false){return r;
+}}return false;}A=A.toLowerCase();var n=this.commonAncestorContainer;while(n.nodeType!=1){n=n.parentNode;}if(n.nodeName.toLowerCase()==A){return n;}if(n.nodeName.toLowerCase()=='body'){return false;}return n.closest(A)||false;},cloneRange:function(){return Roo.lib.Range.wrap(Range.prototype.cloneRange.call(this));
+}});
+// Roo/lib/Selection.js
+Roo.lib.Selection=function(){};Roo.lib.Selection.wrap=function(r,A){Roo.apply(r,Roo.lib.Selection.prototype);r.ownerDocument=A;return r;};Roo.apply(Roo.lib.Selection.prototype,{ownerDocument:false,getRangeAt:function(n){return Roo.lib.Range.wrap(Selection.prototype.getRangeAt.call(this,n));
+},insertNode:function(A,B){if(typeof(A)=='string'){A=this.ownerDocument.createElement(A);if(B=='in'){A.innerHTML='&nbsp;';}}var C=this.getRangeAt(0);if(this.type!='Caret'){C.deleteContents();}var sn=A.childNodes[0];C.insertNode(A);if(B=='after'){A.insertAdjacentHTML('afterend','&nbsp;');
+sn=A.nextSibling;}if(B=='none'){return;}this.cursorText(sn);},cursorText:function(n){range=Roo.lib.Range.wrap(new Range());var ix=Array.from(n.parentNode.childNodes).indexOf(n);range.setStart(n.parentNode,ix);range.setEnd(n.parentNode,ix+1);this.removeAllRanges();
+this.addRange(range);Roo.log([n,range,this,this.baseOffset,this.extentOffset,this.type]);},cursorAfter:function(n){if(!n.nextSibling||n.nextSibling.nodeValue!='&nbsp;'){n.insertAdjacentHTML('afterend','&nbsp;');}this.cursorText(n.nextSibling);}});
 // Roo/DomHelper.js
 if(typeof Range!="undefined"&&typeof Range.prototype.createContextualFragment=="undefined"){Range.prototype.createContextualFragment=function(A){var B=window.document;var C=B.createElement("div");C.innerHTML=A;var D=B.createDocumentFragment(),n;while((n=C.firstChild)){D.appendChild(n);
 }return D;};}Roo.DomHelper=function(){var A=null;var B=/^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;var C=/^table|tbody|tr|td$/i;var D={};var E=function(o){if(typeof o=='string'){return o;}var b="";if(!o.tag){o.tag="div";}b+="<"+o.tag;
@@ -233,9 +242,9 @@ var i=-1,el=A;while(++i<N&&el.firstChild){el=el.firstChild;}return el;};var ts='
 }if(O=='beforebegin'){R=el;el=el.parentNode;}else{R=el.nextSibling;el=el.parentNode;}Q=G(4,J,P,K);}else if(N=='tr'){if(O=='beforebegin'){R=el;el=el.parentNode;Q=G(3,H,P,I);}else if(O=='afterend'){R=el.nextSibling;el=el.parentNode;Q=G(3,H,P,I);}else{if(O=='afterbegin'){R=el.firstChild;
 }Q=G(4,J,P,K);}}else if(N=='tbody'){if(O=='beforebegin'){R=el;el=el.parentNode;Q=G(2,ts,P,te);}else if(O=='afterend'){R=el.nextSibling;el=el.parentNode;Q=G(2,ts,P,te);}else{if(O=='afterbegin'){R=el.firstChild;}Q=G(3,H,P,I);}}else{if(O=='beforebegin'||O=='afterend'){return;
 }if(O=='afterbegin'){R=el.firstChild;}Q=G(2,ts,P,te);}el.insertBefore(Q,R);return Q;};var M=function(N,to){Roo.log(["UpdateNode",N,to]);if(N.nodeType!=to.nodeType){Roo.log(["ReplaceChild - mismatch notType",to,N]);N.parentNode.replaceChild(to,N);}if(N.nodeType==3){if(N.data==to.data){return;
-}N.data=to.data;return;}if(N.nodeType!=1||N.tagName!=to.tagName){Roo.log(["ReplaceChild",N,to]);N.parentNode.replaceChild(to,N);return;}var ar=Array.from(N.attributes);for(var i=0;i<ar.length;i++){if(to.hasAttribute(ar[i].name)){continue;}if(ar[i].name=='id'){continue;
-}Roo.log("removeAttribute"+ar[i].name);N.removeAttribute(ar[i].name);}ar=to.attributes;for(var i=0;i<ar.length;i++){if(N.getAttribute(ar[i].name)==to.getAttribute(ar[i].name)){Roo.log("skipAttribute "+ar[i].name+'='+to.getAttribute(ar[i].name));continue;}
-Roo.log("updateAttribute "+ar[i].name+'=>'+to.getAttribute(ar[i].name));N.setAttribute(ar[i].name,to.getAttribute(ar[i].name));}var O=Array.from(N.childNodes);var P=Array.from(to.childNodes);for(var i=0;i<Math.max(P.length,O.length);i++){if(i>=O.length){N.appendChild(P[i]);
+}N.data=to.data;return;}if(!N.parentNode){return;}if(N.nodeType!=1||N.tagName!=to.tagName){Roo.log(["ReplaceChild",N,to]);N.parentNode.replaceChild(to,N);return;}var ar=Array.from(N.attributes);for(var i=0;i<ar.length;i++){if(to.hasAttribute(ar[i].name)){continue;
+}if(ar[i].name=='id'){continue;}Roo.log("removeAttribute"+ar[i].name);N.removeAttribute(ar[i].name);}ar=to.attributes;for(var i=0;i<ar.length;i++){if(N.getAttribute(ar[i].name)==to.getAttribute(ar[i].name)){Roo.log("skipAttribute "+ar[i].name+'='+to.getAttribute(ar[i].name));
+continue;}Roo.log("updateAttribute "+ar[i].name+'=>'+to.getAttribute(ar[i].name));N.setAttribute(ar[i].name,to.getAttribute(ar[i].name));}var O=Array.from(N.childNodes);var P=Array.from(to.childNodes);for(var i=0;i<Math.max(P.length,O.length);i++){if(i>=O.length){N.appendChild(P[i]);
 Roo.log(["add",P[i]]);}else if(i>=P.length){N.removeChild(O[i]);Roo.log(["remove",O[i]]);}else{M(O[i],P[i]);}}};return {useDom:false,markup:function(o){return E(o);},applyStyles:function(el,N){if(N){el=Roo.fly(el);if(typeof N=="string"){var re=/\s?([a-z\-]*)\:\s?([^;]*);?/gi;
 var O;while((O=re.exec(N))!=null){el.setStyle(O[1],O[2]);}}else if(typeof N=="object"){for(var P in N){el.setStyle(P,N[P]);}}else if(typeof N=="function"){Roo.DomHelper.applyStyles(el,N.call());}}},insertHtml:function(N,el,O){N=N.toLowerCase();if(el.insertAdjacentHTML){if(C.test(el.tagName)){var rs;
 if(rs=L(el.tagName.toLowerCase(),N,el,O)){return rs;}}switch(N){case "beforebegin":el.insertAdjacentHTML('BeforeBegin',O);return el.previousSibling;case "afterbegin":el.insertAdjacentHTML('AfterBegin',O);return el.firstChild;case "beforeend":el.insertAdjacentHTML('BeforeEnd',O);
@@ -1921,7 +1930,7 @@ if(!C.length){A.removeAttribute("class");}}if(A.hasAttribute("lang")){A.removeAt
 }E.push(s);});A.setAttribute("style",E.length?E.join(';'):'');if(!E.length){A.removeAttribute('style');}}return true;}});
 // 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);
+}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);
 nn.appendChild(nc);nn=nc;});for(var i=0;i<cn.length;cn++){A.removeChild(cn[i]);nn.appendChild(cn[i]);}return true}})
 // Roo/htmleditor/FilterLongBr.js
 Roo.htmleditor.FilterLongBr=function(A){this.walk(A.node);};Roo.extend(Roo.htmleditor.FilterLongBr,Roo.htmleditor.Filter,{tag:'BR',replaceTag:function(A){var ps=A.nextSibling;while(ps&&ps.nodeType==3&&ps.nodeValue.trim().length<1){ps=ps.nextSibling;}if(!ps&&['TD','TH','LI','H1','H2','H3','H4','H5','H6'].indexOf(A.parentNode.tagName)>-1){A.parentNode.removeChild(A);
@@ -1937,69 +1946,82 @@ Roo.htmleditor.Tidy=function(A){Roo.apply(this,A);this.core.doc.body.innerHTML=t
 }C.push(" ");}if(B!==false&&ar[i].nodeType==1){C.push("\n"+B);}C.push(this.tidy(ar[i],B));if(B!==false&&ar[i].nodeType==3&&ar[i].nodeValue.length>0&&ar[i].nodeValue.match(/\s+$/)){C.push("\n"+B);}}return C.join('');},attr:function(A){var B=[];for(i=0;i<A.attributes.length;
 i++){if(!A.attributes.item(i).value.length){continue;}B.push(A.attributes.item(i).name+'="'+Roo.util.Format.htmlEncode(A.attributes.item(i).value)+'"');}return B.length?(' '+B.join(' ')):'';}}
 // Roo/htmleditor/KeyEnter.js
-Roo.htmleditor.KeyEnter=function(A){Roo.apply(this,A);Roo.get(this.core.doc.body).on('keypress',this.keypress,this);};Roo.htmleditor.KeyEnter.prototype={core:false,keypress:function(e){if(e.charCode!=13){return true;}e.preventDefault();var A=this.core.doc;
-var B=A.createDocumentFragment();var C=this.core.win.getSelection().getRangeAt(0);var n=C.commonAncestorContainer;while(n&&n.nodeType!=1){n=n.parentNode;}var li=false;if(n&&n.tagName=='UL'){li=A.createElement('LI');n.appendChild(li);}if(n&&n.tagName=='LI'){li=A.createElement('LI');
-if(n.nextSibling){n.parentNode.insertBefore(li,n.firstSibling);}else{n.parentNode.appendChild(li);}}if(li){C=A.createRange();C.setStartAfter(li);C.collapse(true);var D=this.core.win.getSelection();D.removeAllRanges();D.addRange(C);this.core.undoManager.addEvent();
-return false;}var E=A.createTextNode('\n');B.appendChild(E);E=A.createElement('br');B.appendChild(E);A.createTextNode('\n');B.appendChild(E);C.deleteContents();C.insertNode(B);var ns=E.nextSibling;while(ns&&ns.nodeType==3){ns=ns.nextSibling;}if(!ns){ns=A.createElement('br');
-E.parentNode.appendChild(ns);}C=A.createRange();C.setStartAfter(E);C.collapse(true);var D=this.core.win.getSelection();D.removeAllRanges();D.addRange(C);return false;}};
+Roo.htmleditor.KeyEnter=function(A){Roo.apply(this,A);Roo.get(this.core.doc.body).on('keypress',this.keypress,this);};Roo.htmleditor.KeyEnter.prototype={core:false,keypress:function(e){if(e.charCode!=13&&e.charCode!=10){Roo.log([e.charCode,e]);return true;
+}e.preventDefault();var A=this.core.doc;var B=this.core.getSelection();var C=B.getRangeAt(0);var n=C.commonAncestorContainer;var pc=C.closest(['ol','ul']);var D=C.closest('li');if(!pc||e.ctrlKey){B.insertNode('br','after');this.core.undoManager.addEvent();
+this.core.fireEditorEvent(e);return false;}if(D.innerText.trim()==''&&D.previousSibling&&D.previousSibling.nodeName=='LI'&&D.previousSibling.innerText.trim()==''){D.parentNode.removeChild(D.previousSibling);B.cursorAfter(pc);this.core.undoManager.addEvent();
+this.core.fireEditorEvent(e);return false;}var li=A.createElement('LI');li.innerHTML='&nbsp;';if(!D||!D.firstSibling){pc.appendChild(li);}else{D.parentNode.insertBefore(li,D.firstSibling);}B.cursorText(li.firstChild);this.core.undoManager.addEvent();this.core.fireEditorEvent(e);
+return false;}};
 // Roo/htmleditor/Block.js
-Roo.htmleditor.Block=function(A){};Roo.htmleditor.Block.factory=function(A){var cc=Roo.htmleditor.Block.cache;var id=Roo.get(A).id;if(typeof(cc[id])!='undefined'&&(!cc[id].node||cc[id].node.closest('body'))){Roo.htmleditor.Block.cache[id].readElement();return Roo.htmleditor.Block.cache[id];
+Roo.htmleditor.Block=function(A){};Roo.htmleditor.Block.factory=function(A){var cc=Roo.htmleditor.Block.cache;var id=Roo.get(A).id;if(typeof(cc[id])!='undefined'&&(!cc[id].node||cc[id].node.closest('body'))){Roo.htmleditor.Block.cache[id].readElement(A);return Roo.htmleditor.Block.cache[id];
 }var db=A.getAttribute('data-block');if(!db){db=A.nodeName.toLowerCase().toUpperCaseFirst();}var B=Roo.htmleditor['Block'+db];if(typeof(B)=='undefined'){Roo.log("OOps missing block : "+'Block'+db);return false;}Roo.htmleditor.Block.cache[id]=new B({node:A}
 );return Roo.htmleditor.Block.cache[id];};Roo.htmleditor.Block.initAll=function(A,B){if(typeof(B)=='undefined'){var ia=Roo.htmleditor.Block.initAll;ia(A,'table');ia(A,'td');ia(A,'figure');return;}Roo.each(Roo.get(A).query(B),function(e){Roo.htmleditor.Block.factory(e);
 },this);};Roo.htmleditor.Block.cache={};Roo.htmleditor.Block.prototype={node:false,friendly_name:'Based Block',deleteTitle:false,context:false,updateElement:function(A){Roo.DomHelper.update(A===undefined?this.node:A,this.toObject());},toHTML:function(){return Roo.DomHelper.markup(this.toObject());
-},getVal:function(A,B,C,D){var n=A;if(B!==true&&n.tagName!=B.toUpperCase()){n=A.getElementsByTagName(B).item(0);}if(C=='html'){return n.innerHTML;}if(C=='style'){return n.style[D]}return Roo.get(n).attr(C);},toObject:function(){return {};},readElement:function(A){}
-};
+},getVal:function(A,B,C,D){var n=A;if(B!==true&&n.tagName!=B.toUpperCase()){n=A.getElementsByTagName(B).item(0);}if(!n){return '';}if(C=='html'){return n.innerHTML;}if(C=='style'){return n.style[D];}return n.hasAttribute(C)?n.getAttribute(C):'';},toObject:function(){return {}
+;},readElement:function(A){}};
 // Roo/htmleditor/BlockFigure.js
-Roo.htmleditor.BlockFigure=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockFigure,Roo.htmleditor.Block,{image_src:'',align:'left',caption:'',text_align:'left',width:'46%',margin:'2%',friendly_name:'Image with caption',deleteTitle:"Delete Image and Caption",context:{width:{title:"Width",width:40}
-,margin:{title:"Margin",width:40},align:{title:"Align",opts:[["left"],["right"]],width:80},text_align:{title:"Caption Align",opts:[["left"],["right"],["center"]],width:80},image_src:{title:"Src",width:220}},toObject:function(){var d=document.createElement('div');
-d.innerHTML=this.caption;return {tag:'figure','data-block':'Figure',contenteditable:'false',style:{display:'table',float:this.align,width:this.width,margin:this.margin},cn:[{tag:'img',src:this.image_src,alt:d.innerText.replace(/\n/g," "),style:{width:'100%'}
-},{tag:'figcaption',contenteditable:true,style:{'text-align':this.text_align},html:this.caption}]};},readElement:function(A){this.image_src=this.getVal(A,'img','src');this.align=this.getVal(A,'figure','style','float');this.caption=this.getVal(A,'figcaption','html');
-this.text_align=this.getVal(A,'figcaption','style','text-align');this.width=this.getVal(A,'figure','style','width');this.margin=this.getVal(A,'figure','style','margin');}})
+Roo.htmleditor.BlockFigure=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockFigure,Roo.htmleditor.Block,{image_src:'',align:'center',caption:'',caption_display:'block',width:'100%',text_align:'left',friendly_name:'Image with caption',deleteTitle:"Delete Image and Caption",contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);
+};var C=typeof(Roo.bootstrap)=='undefined'?Roo:Roo.bootstrap;var D=A.editorcore.syncValue;var E={};return [{xtype:'TextItem',text:"Source: ",xns:C.Toolbar},{xtype:'TextField',allowBlank:false,width:150,name:'image_src',listeners:{keyup:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.image_src=this.getValue();b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form},{xtype:'TextItem',text:"Width: ",xns:C.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:70,name:'width',listeners:{select:function(F,r,G){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.width=r.get('val');b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form,store:{xtype:'SimpleStore',data:[['auto'],['50%'],['100%']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Align: ",xns:C.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:70,name:'align',listeners:{select:function(F,r,G){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.align=r.get('val');b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form,store:{xtype:'SimpleStore',data:[['left'],['right'],['center']],fields:['val'],xns:Roo.data}},{xtype:'Button',text:'Hide Caption',name:'caption_display',pressed:false,enableToggle:true,setValue:function(v){this.toggle(v=='block'?false:true);
+},listeners:{toggle:function(F,G){var b=B();b.caption_display=b.caption_display=='block'?'none':'block';this.setText(b.caption_display=='block'?"Hide Caption":"Show Caption");b.updateElement();D();A.editorcore.selectNode(A.tb.selectedNode);A.editorcore.onEditorEvent();
+}},xns:C.Toolbar}];},toObject:function(){var d=document.createElement('div');d.innerHTML=this.caption;return {tag:'figure','data-block':'Figure',contenteditable:'false',style:{display:'block',float:this.align,'max-width':this.width,width:'auto',margin:0,padding:'10px'}
+,align:this.align,cn:[{tag:'img',src:this.image_src,alt:d.innerText.replace(/\n/g," "),style:{width:'auto','max-width':'100%',margin:'0px'}},{tag:'figcaption',contenteditable:true,style:{'text-align':'left','margin-top':'16px','font-size':'16px','line-height':'24px','font-style':'italic',display:this.caption_display}
+,html:this.caption}]};},readElement:function(A){this.image_src=this.getVal(A,'img','src');this.align=this.getVal(A,'figure','align');this.caption=this.getVal(A,'figcaption','html');this.width=this.getVal(A,'figure','style','max-width');},removeNode:function(){return this.node;
+}})
 // Roo/htmleditor/BlockTable.js
 Roo.htmleditor.BlockTable=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);if(!A.node){this.rows=[];for(var r=0;r<this.no_row;r++){this.rows[r]=[];for(var c=0;c<this.no_col;c++){this.rows[r][c]=this.emptyCell();
 }}}};Roo.extend(Roo.htmleditor.BlockTable,Roo.htmleditor.Block,{rows:false,no_col:1,no_row:1,width:'100%',friendly_name:'Table',deleteTitle:'Delete Table',contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);};var C=typeof(Roo.bootstrap)=='undefined'?Roo:Roo.bootstrap;
-var D=A.editorcore.syncValue;var E={};return [{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:100,name:'width',listeners:{select:function(F,r,G){var b=B();b.width=r.get('val');
-b.updateElement();D();}},xns:C.form,store:{xtype:'SimpleStore',data:[['100%'],['auto']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Columns: ",xns:C.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(F,e){B().removeColumn();D();}},xns:C.Toolbar}
-,{xtype:'Button',text:'+',listeners:{click:function(F,e){B().addColumn();D();}},xns:C.Toolbar},{xtype:'TextItem',text:"Rows: ",xns:C.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(F,e){B().removeRow();D();}},xns:C.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(F,e){B().addRow();
-D();}},xns:C.Toolbar},{xtype:'Button',text:'Reset Column Widths',listeners:{click:function(F,e){B().resetWidths();D();}},xns:C.Toolbar}];},toObject:function(){var A={tag:'table',contenteditable:'false','data-block':'Table',style:{width:this.width,border:'solid 1px #000','border-collapse':'collapse'}
+var D=A.editorcore.syncValue;var E={};return [{xtype:'TextItem',text:"Width: ",xns:C.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:100,name:'width',listeners:{select:function(F,r,G){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.width=r.get('val');b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form,store:{xtype:'SimpleStore',data:[['100%'],['auto']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Columns: ",xns:C.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);
+B().removeColumn();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);B().addColumn();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar},{xtype:'TextItem',text:"Rows: ",xns:C.Toolbar}
+,{xtype:'Button',text:'-',listeners:{click:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);B().removeRow();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(F,e){B().addRow();D();A.editorcore.onEditorEvent();
+}},xns:C.Toolbar},{xtype:'Button',text:'Reset Column Widths',listeners:{click:function(F,e){B().resetWidths();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar}];},toObject:function(){var A={tag:'table',contenteditable:'false','data-block':'Table',style:{width:this.width,border:'solid 1px #000','border-collapse':'collapse'}
 ,cn:[{tag:'tbody',cn:[]}]};var B=0;Roo.each(this.rows,function(C){var tr={tag:'tr',style:{margin:'6px',border:'solid 1px #000',textAlign:'left'},cn:[]};A.cn[0].cn.push(tr);var nc=0;Roo.each(C,function(D){var td={tag:'td',contenteditable:'true','data-block':'Td',html:D.html,style:D.style}
 ;if(D.colspan>1){td.colspan=D.colspan;nc+=D.colspan;}else{nc++;}if(D.rowspan>1){td.rowspan=D.rowspan;}tr.cn.push(td);},this);B=Math.max(nc,B);},this);B++;return A;},readElement:function(A){A=A?A:this.node;this.width=this.getVal(A,true,'style','width')||'100%';
-this.rows=[];this.no_row=0;var B=Array.from(A.getElementsByTagName('tr'));B.forEach(function(tr){var C=[];this.rows.push(C);if(Roo.get(tr).hasClass('roo-html-editor-el')){return;}this.no_row++;var D=0;Array.from(tr.getElementsByTagName('td')).forEach(function(td){if(Roo.get(td).hasClass('roo-html-editor-el')){return;
-}var E={colspan:td.hasAttribute('colspan')?td.getAttribute('colspan'):1,rowspan:td.hasAttribute('rowspan')?td.getAttribute('rowspan'):1,style:td.hasAttribute('style')?td.getAttribute('style'):'',html:td.innerHTML};D+=E.colspan;C.push(E);},this);this.no_col=Math.max(this.no_col,D);
-},this);},normalizeRows:function(){var A=[];var B=-1;this.rows.forEach(function(C){B++;A[B]=[];C=this.normalizeRow(C);var D=0;C.forEach(function(c){while(typeof(A[B][D])!='undefined'){D++;}if(typeof(A[B])=='undefined'){A[B]=[];}A[B][D]=c;c.row=B;c.col=D;if(c.rowspan<2){return;
-}for(var i=1;i<c.rowspan;i++){if(typeof(A[B+i])=='undefined'){A[B+i]=[];}A[B+i][D]=c;}});},this);return A;},normalizeRow:function(A){var B=[];A.forEach(function(c){if(c.colspan<2){B.push(c);return;}for(var i=0;i<c.colspan;i++){B.push(c);}});return B;},deleteColumn:function(A){if(!A||A.type!='col'){return;
-}if(this.no_col<2){return;}this.rows.forEach(function(B){var C=this.normalizeRow(B);var D=C[A.col];if(D.colspan>1){D.colspan--;}else{B.remove(D);}},this);this.no_col--;},removeColumn:function(){this.deleteColumn({type:'col',col:this.no_col-1});this.updateElement();
-},addColumn:function(){this.rows.forEach(function(A){A.push(this.emptyCell());},this);this.updateElement();},deleteRow:function(A){if(!A||A.type!='row'){return;}if(this.no_row<2){return;}var B=this.normalizeRows();B[A.row].forEach(function(D){if(D.rowspan>1){D.rowspan--;
-}else{D.remove=1;}},this);var C=[];this.rows.forEach(function(D){newrow=[];D.forEach(function(c){if(typeof(c.remove)=='undefined'){newrow.push(c);}});if(newrow.length>0){C.push(D);}});this.rows=C;this.no_row--;this.updateElement();},removeRow:function(){this.deleteRow({type:'row',row:this.no_row-1}
-);},addRow:function(){row=[];for(var i=0;i<this.no_col;i++){row.push(this.emptyCell());}this.rows.push(row);this.updateElement();},emptyCell:function(){return (new Roo.htmleditor.BlockTd({})).toObject();},removeNode:function(){return this.node;},resetWidths:function(){Array.from(this.node.getElementsByTagName('td')).forEach(function(n){var nn=Roo.htmleditor.Block.factory(n);
+this.rows=[];this.no_row=0;var B=Array.from(A.rows);B.forEach(function(tr){var C=[];this.rows.push(C);this.no_row++;var D=0;Array.from(tr.cells).forEach(function(td){var E={colspan:td.hasAttribute('colspan')?td.getAttribute('colspan')*1:1,rowspan:td.hasAttribute('rowspan')?td.getAttribute('rowspan')*1:1,style:td.hasAttribute('style')?td.getAttribute('style'):'',html:td.innerHTML}
+;D+=E.colspan;C.push(E);},this);this.no_col=Math.max(this.no_col,D);},this);},normalizeRows:function(){var A=[];var B=-1;this.rows.forEach(function(C){B++;A[B]=[];C=this.normalizeRow(C);var D=0;C.forEach(function(c){while(typeof(A[B][D])!='undefined'){D++;
+}if(typeof(A[B])=='undefined'){A[B]=[];}A[B][D]=c;c.row=B;c.col=D;if(c.rowspan<2){return;}for(var i=1;i<c.rowspan;i++){if(typeof(A[B+i])=='undefined'){A[B+i]=[];}A[B+i][D]=c;}});},this);return A;},normalizeRow:function(A){var B=[];A.forEach(function(c){if(c.colspan<2){B.push(c);
+return;}for(var i=0;i<c.colspan;i++){B.push(c);}});return B;},deleteColumn:function(A){if(!A||A.type!='col'){return;}if(this.no_col<2){return;}this.rows.forEach(function(B){var C=this.normalizeRow(B);var D=C[A.col];if(D.colspan>1){D.colspan--;}else{B.remove(D);
+}},this);this.no_col--;},removeColumn:function(){this.deleteColumn({type:'col',col:this.no_col-1});this.updateElement();},addColumn:function(){this.rows.forEach(function(A){A.push(this.emptyCell());},this);this.updateElement();},deleteRow:function(A){if(!A||A.type!='row'){return;
+}if(this.no_row<2){return;}var B=this.normalizeRows();B[A.row].forEach(function(D){if(D.rowspan>1){D.rowspan--;}else{D.remove=1;}},this);var C=[];this.rows.forEach(function(D){newrow=[];D.forEach(function(c){if(typeof(c.remove)=='undefined'){newrow.push(c);
+}});if(newrow.length>0){C.push(D);}});this.rows=C;this.no_row--;this.updateElement();},removeRow:function(){this.deleteRow({type:'row',row:this.no_row-1});},addRow:function(){var A=[];for(var i=0;i<this.no_col;i++){A.push(this.emptyCell());}this.rows.push(A);
+this.updateElement();},emptyCell:function(){return (new Roo.htmleditor.BlockTd({})).toObject();},removeNode:function(){return this.node;},resetWidths:function(){Array.from(this.node.getElementsByTagName('td')).forEach(function(n){var nn=Roo.htmleditor.Block.factory(n);
 nn.width='';nn.updateElement(n);});}})
 // Roo/htmleditor/BlockTd.js
-Roo.htmleditor.BlockTd=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockTd,Roo.htmleditor.Block,{node:false,width:'',textAlign:'left',colspan:1,rowspan:1,friendly_name:'Table Cell',deleteTitle:'Delete Table',contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);
+Roo.htmleditor.BlockTd=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockTd,Roo.htmleditor.Block,{node:false,width:'',textAlign:'left',valign:'top',colspan:1,rowspan:1,friendly_name:'Table Cell',deleteTitle:false,contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);
 };var C=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode.closest('table'));};var lr=false;var D=function(){lr=A.editorcore.getSelection().getRangeAt(0);};var restoreSel=function(){if(lr){(function(){A.editorcore.focus();var cr=A.editorcore.getSelection();
 cr.removeAllRanges();cr.addRange(lr);A.editorcore.onEditorEvent();}).defer(10,this);}};var rooui=typeof(Roo.bootstrap)=='undefined'?Roo:Roo.bootstrap;var E=A.editorcore.syncValue;var F={};return [{xtype:'Button',text:'Edit Table',listeners:{click:function(){var t=A.tb.selectedNode.closest('table');
-A.editorcore.selectNode(t);A.editorcore.onEditorEvent();}}},{xtype:'TextItem',text:"Column Width: ",xns:rooui.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(G,e){D();B().shrinkColumn();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(G,e){D();
-B().growColumn();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"Merge Cells: ",xns:rooui.Toolbar},{xtype:'Button',text:'Right',listeners:{click:function(G,e){D();B().mergeRight();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'Button',text:'Below',listeners:{click:function(G,e){D();
-B().mergeBelow();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"| ",xns:rooui.Toolbar},{xtype:'Button',text:'Split',listeners:{click:function(G,e){D();B().split();E();restoreSel();}},xns:rooui.Toolbar}];},toObject:function(){var A={tag:'td',contenteditable:'true','data-block':'Td',width:this.width,style:{width:this.width,'text-align':this.textAlign,border:'solid 1px rgb(0, 0, 0)','border-collapse':'collapse'}
-,html:this.html};if(this.colspan>1){A.colspan=cell.colspan;}if(A.rowspan>1){this.rowspan=cell.rowspan;}return A;},readElement:function(A){A=A?A:this.node;this.width=A.style.width;this.html=A.innerHTML;},emptyCell:function(){return {colspan:1,rowspan:1,textAlign:'left',html:"&nbsp;"}
-;},removeNode:function(){return this.node.closest('table');},cellData:false,colWidths:false,toTableArray:function(){var A=[];var B=this.node.closest('tr').closest('table');Array.from(B.rows).forEach(function(r,ri){A[ri]=[];});var rn=0;this.colWidths=[];var C=true;
-Array.from(B.rows).forEach(function(r,ri){var cn=0;Array.from(r.cells).forEach(function(ce,ci){var c={cell:ce,row:rn,col:cn,colspan:ce.colSpan,rowspan:ce.rowSpan};if(ce.isEqualNode(this.node)){this.cellData=c;}if(typeof(A[rn][cn])!='undefined'){while(typeof(A[rn][cn])!='undefined'){cn++;
-}c.col=cn;}if(typeof(this.colWidths[cn])=='undefined'){this.colWidths[cn]=ce.style.width;if(this.colWidths[cn]!=''){C=false;}}if(c.colspan<2&&c.rowspan<2){A[rn][cn]=c;cn++;return;}for(var j=0;j<c.rowspan;j++){if(typeof(A[rn+j])=='undefined'){continue;}A[rn+j][cn]=c;
-for(var i=0;i<c.colspan;i++){A[rn+j][cn+i]=c;}}cn+=c.colspan;},this);rn++;},this);if(C){this.colWidths[0]=false;}return A;},mergeRight:function(){var tr=this.node.closest('tr');var i=Array.prototype.indexOf.call(tr.childNodes,this.node);if(i>=tr.childNodes.length-1){return;
-}var A=this.toTableArray();if(typeof(A[this.cellData.row][this.cellData.col+this.cellData.colspan])=='undefined'){return;}var rc=A[this.cellData.row][this.cellData.col+this.cellData.colspan];if(rc.rowspan!=this.cellData.rowspan||rc.row!=this.cellData.row){return;
-}this.node.innerHTML+=' '+rc.cell.innerHTML;tr.removeChild(rc.cell);this.colspan+=rc.colspan;this.node.setAttribute('colspan',this.colspan);},mergeBelow:function(){var A=this.toTableArray();if(typeof(A[this.cellData.row+this.cellData.rowspan])=='undefined'){return;
-}if(typeof(A[this.cellData.row+this.cellData.rowspan][this.cellData.col])=='undefined'){return;}var rc=A[this.cellData.row+this.cellData.rowspan][this.cellData.col];if(rc.colspan!=this.cellData.colspan||rc.col!=this.cellData.col){return;}this.node.innerHTML=this.node.innerHTML+rc.cell.innerHTML;
-rc.cell.parentNode.removeChild(rc.cell);this.rowspan+=rc.rowspan;this.node.setAttribute('rowspan',this.rowspan);},split:function(){if(this.node.rowSpan<2&&this.node.colSpan<2){return;}var A=this.toTableArray();var cd=this.cellData;this.rowspan=1;this.colspan=1;
-for(var r=cd.row;r<cd.row+cd.rowspan;r++){for(var c=cd.col;c<cd.col+cd.colspan;c++){if(r==cd.row&&c==cd.col){this.node.removeAttribute('rowspan');this.node.removeAttribute('colspan');continue;}var B=this.node.cloneNode();B.removeAttribute('id');B.innerHTML='';
-A[r][c]={cell:B,col:c,row:r,colspan:1,rowspan:1};}}this.redrawAllCells(A);},redrawAllCells:function(A){var B=this.node.closest('tr').closest('table');Array.from(B.rows).forEach(function(r,ri){Array.from(r.cells).forEach(function(ce,ci){ce.parentNode.removeChild(ce);
-});});for(var r=0;r<A.length;r++){var re=B.rows[r];for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;}re.appendChild(A[r][c].cell);A[r][c].cell=false;}}},updateWidths:function(A){for(var r=0;r<A.length;r++){for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;
-}if(this.colWidths[0]!=false&&A[r][c].colspan<2){var el=Roo.htmleditor.Block.factory(A[r][c].cell);el.width=Math.floor(this.colWidths[c])+'%';el.updateElement(el.node);}A[r][c].cell=false;}}},normalizeWidths:function(A){if(this.colWidths[0]===false){var nw=100.0/this.colWidths.length;
-this.colWidths.forEach(function(w,i){this.colWidths[i]=nw;},this);return;}var t=0,B=[];this.colWidths.forEach(function(w,i){this.colWidths[i]=this.colWidths[i]==''?0:(this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;var D=this.colWidths[i];if(D>0){t+=D;return;
-}B.push(i);},this);var nc=this.colWidths.length;if(B.length){var C=(nc-B.length)/(1.0*nc);var t=C*t;var ew=(100-t)/(1.0*B.length);this.colWidths.forEach(function(w,i){if(w>0){this.colWidths[i]=w*C;return;}this.colWidths[i]=ew;},this);}},shrinkColumn:function(){var A=this.toTableArray();
-this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*0.8;if(nw<5){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;return;}this.colWidths[i]+=C},this);this.updateWidths(A);
-},growColumn:function(){var A=this.toTableArray();this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*1.2;if(nw>90){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;
-return;}this.colWidths[i]-=C},this);this.updateWidths(A);}})
+A.editorcore.selectNode(t);A.editorcore.onEditorEvent();}}},{xtype:'TextItem',text:"Column Width: ",xns:rooui.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);B().shrinkColumn();E();A.editorcore.onEditorEvent();
+}},xns:rooui.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);B().growColumn();E();A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"Vertical Align: ",xns:rooui.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:100,name:'valign',listeners:{select:function(G,r,H){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.valign=r.get('val');b.updateElement();E();A.editorcore.onEditorEvent();}},xns:rooui.form,store:{xtype:'SimpleStore',data:[['top'],['middle'],['bottom']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Merge Cells: ",xns:rooui.Toolbar},{xtype:'Button',text:'Right',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);
+B().mergeRight();E();A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'Button',text:'Below',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);B().mergeBelow();E();A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"| ",xns:rooui.Toolbar}
+,{xtype:'Button',text:'Split',listeners:{click:function(G,e){B().split();E();A.editorcore.selectNode(A.tb.selectedNode);A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'Fill',xns:rooui.Toolbar},{xtype:'Button',text:'Delete',xns:rooui.Toolbar,menu:{xtype:'Menu',xns:rooui.menu,items:[{xtype:'Item',html:'Column',listeners:{click:function(G,e){var t=C();
+B().deleteColumn();E();A.editorcore.selectNode(t.node);A.editorcore.onEditorEvent();}},xns:rooui.menu},{xtype:'Item',html:'Row',listeners:{click:function(G,e){var t=C();B().deleteRow();E();A.editorcore.selectNode(t.node);A.editorcore.onEditorEvent();}},xns:rooui.menu}
+,{xtype:'Separator',xns:rooui.menu},{xtype:'Item',html:'Table',listeners:{click:function(G,e){var t=C();var nn=t.node.nextSibling||t.node.previousSibling;t.node.parentNode.removeChild(t.node);if(nn){A.editorcore.selectNode(nn,true);}A.editorcore.onEditorEvent();
+}},xns:rooui.menu}]}}];},toObject:function(){var A={tag:'td',contenteditable:'true','data-block':'Td',valign:this.valign,style:{'text-align':this.textAlign,border:'solid 1px rgb(0, 0, 0)','border-collapse':'collapse',padding:'6px','vertical-align':this.valign}
+,html:this.html};if(this.width!=''){A.width=this.width;A.style.width=this.width;}if(this.colspan>1){A.colspan=this.colspan;}if(this.rowspan>1){A.rowspan=this.rowspan;}return A;},readElement:function(A){A=A?A:this.node;this.width=A.style.width;this.colspan=Math.max(1,1*A.getAttribute('colspan'));
+this.rowspan=Math.max(1,1*A.getAttribute('rowspan'));this.html=A.innerHTML;},emptyCell:function(){return {colspan:1,rowspan:1,textAlign:'left',html:"&nbsp;"};},removeNode:function(){return this.node.closest('table');},cellData:false,colWidths:false,toTableArray:function(){var A=[];
+var B=this.node.closest('tr').closest('table');Array.from(B.rows).forEach(function(r,ri){A[ri]=[];});var rn=0;this.colWidths=[];var C=true;Array.from(B.rows).forEach(function(r,ri){var cn=0;Array.from(r.cells).forEach(function(ce,ci){var c={cell:ce,row:rn,col:cn,colspan:ce.colSpan,rowspan:ce.rowSpan}
+;if(ce.isEqualNode(this.node)){this.cellData=c;}if(typeof(A[rn][cn])!='undefined'){while(typeof(A[rn][cn])!='undefined'){cn++;}c.col=cn;}if(typeof(this.colWidths[cn])=='undefined'){this.colWidths[cn]=ce.style.width;if(this.colWidths[cn]!=''){C=false;}}if(c.colspan<2&&c.rowspan<2){A[rn][cn]=c;
+cn++;return;}for(var j=0;j<c.rowspan;j++){if(typeof(A[rn+j])=='undefined'){continue;}A[rn+j][cn]=c;for(var i=0;i<c.colspan;i++){A[rn+j][cn+i]=c;}}cn+=c.colspan;},this);rn++;},this);if(C){this.colWidths[0]=false;}return A;},mergeRight:function(){var tr=this.node.closest('tr');
+var i=Array.prototype.indexOf.call(tr.childNodes,this.node);if(i>=tr.childNodes.length-1){return;}var A=this.toTableArray();if(typeof(A[this.cellData.row][this.cellData.col+this.cellData.colspan])=='undefined'){return;}var rc=A[this.cellData.row][this.cellData.col+this.cellData.colspan];
+if(rc.rowspan!=this.cellData.rowspan||rc.row!=this.cellData.row){return;}this.node.innerHTML+=' '+rc.cell.innerHTML;tr.removeChild(rc.cell);this.colspan+=rc.colspan;this.node.setAttribute('colspan',this.colspan);},mergeBelow:function(){var A=this.toTableArray();
+if(typeof(A[this.cellData.row+this.cellData.rowspan])=='undefined'){return;}if(typeof(A[this.cellData.row+this.cellData.rowspan][this.cellData.col])=='undefined'){return;}var rc=A[this.cellData.row+this.cellData.rowspan][this.cellData.col];if(rc.colspan!=this.cellData.colspan||rc.col!=this.cellData.col){return;
+}this.node.innerHTML=this.node.innerHTML+rc.cell.innerHTML;rc.cell.parentNode.removeChild(rc.cell);this.rowspan+=rc.rowspan;this.node.setAttribute('rowspan',this.rowspan);},split:function(){if(this.node.rowSpan<2&&this.node.colSpan<2){return;}var A=this.toTableArray();
+var cd=this.cellData;this.rowspan=1;this.colspan=1;for(var r=cd.row;r<cd.row+cd.rowspan;r++){for(var c=cd.col;c<cd.col+cd.colspan;c++){if(r==cd.row&&c==cd.col){this.node.removeAttribute('rowspan');this.node.removeAttribute('colspan');continue;}var B=this.node.cloneNode();
+B.removeAttribute('id');B.innerHTML='';A[r][c]={cell:B,col:c,row:r,colspan:1,rowspan:1};}}this.redrawAllCells(A);},redrawAllCells:function(A){var B=this.node.closest('tr').closest('table');var C=B.rows[0].parentNode;Array.from(B.rows).forEach(function(r,ri){Array.from(r.cells).forEach(function(ce,ci){ce.parentNode.removeChild(ce);
+});r.parentNode.removeChild(r);});for(var r=0;r<A.length;r++){var re=B.rows[r];var re=B.ownerDocument.createElement('tr');C.appendChild(re);for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;}re.appendChild(A[r][c].cell);A[r][c].cell=false;}
+}},updateWidths:function(A){for(var r=0;r<A.length;r++){for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;}if(this.colWidths[0]!=false&&A[r][c].colspan<2){var el=Roo.htmleditor.Block.factory(A[r][c].cell);el.width=Math.floor(this.colWidths[c])+'%';
+el.updateElement(el.node);}A[r][c].cell=false;}}},normalizeWidths:function(A){if(this.colWidths[0]===false){var nw=100.0/this.colWidths.length;this.colWidths.forEach(function(w,i){this.colWidths[i]=nw;},this);return;}var t=0,B=[];this.colWidths.forEach(function(w,i){this.colWidths[i]=this.colWidths[i]==''?0:(this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;
+var D=this.colWidths[i];if(D>0){t+=D;return;}B.push(i);},this);var nc=this.colWidths.length;if(B.length){var C=(nc-B.length)/(1.0*nc);var t=C*t;var ew=(100-t)/(1.0*B.length);this.colWidths.forEach(function(w,i){if(w>0){this.colWidths[i]=w*C;return;}this.colWidths[i]=ew;
+},this);}},shrinkColumn:function(){var A=this.toTableArray();this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*0.8;if(nw<5){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;
+return;}this.colWidths[i]+=C},this);this.updateWidths(A);},growColumn:function(){var A=this.toTableArray();this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*1.2;if(nw>90){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);
+this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;return;}this.colWidths[i]-=C},this);this.updateWidths(A);},deleteRow:function(){var A=this.toTableArray();for(var i=0;i<A[this.cellData.row].length;i++){var c=A[this.cellData.row][i];if(c.row!=this.cellData.row){c.rowspan--;
+c.cell.setAttribute('rowspan',c.rowspan);continue;}if(c.rowspan>1){c.rowspan--;c.cell.setAttribute('rowspan',c.rowspan);}}A.splice(this.cellData.row,1);this.redrawAllCells(A);},deleteColumn:function(){var A=this.toTableArray();for(var i=0;i<A.length;i++){var c=A[i][this.cellData.col];
+if(c.col!=this.cellData.col){A[i][this.cellData.col].colspan--;}else if(c.colspan>1){c.colspan--;c.cell.setAttribute('colspan',c.colspan);}A[i].splice(this.cellData.col,1);}this.redrawAllCells(A);}})
 // Roo/HtmlEditorCore.js
-Roo.HtmlEditorCore=function(A){Roo.HtmlEditorCore.superclass.constructor.call(this,A);this.addEvents({initialize:true,activate:true,beforesync:true,beforepush:true,sync:true,push:true,editorevent:true});this.applyBlacklists();};Roo.extend(Roo.HtmlEditorCore,Roo.Component,{owner:false,resizable:false,height:300,width:500,stylesheets:false,allowComments:false,frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,sourceEditMode:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',clearUp:true,black:false,white:false,bodyCls:'',undoManager:false,getDocMarkup:function(){var st='';
+Roo.HtmlEditorCore=function(A){Roo.HtmlEditorCore.superclass.constructor.call(this,A);this.addEvents({initialize:true,activate:true,beforesync:true,beforepush:true,sync:true,push:true,editorevent:true});this.applyBlacklists();};Roo.extend(Roo.HtmlEditorCore,Roo.Component,{owner:false,resizable:false,height:300,width:500,autoClean:true,enableBlocks:true,stylesheets:false,allowComments:false,frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,sourceEditMode:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',clearUp:true,black:false,white:false,bodyCls:'',undoManager:false,getDocMarkup:function(){var st='';
 if(this.stylesheets===false){Roo.get(document.head).select('style').each(function(B){st+=B.dom.outerHTML||new XMLSerializer().serializeToString(B.dom);});Roo.get(document.head).select('link').each(function(B){st+=B.dom.outerHTML||new XMLSerializer().serializeToString(B.dom);
 });}else if(!this.stylesheets.length){st='<style type="text/css">'+'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}'+'</style>';}else{for(var i in this.stylesheets){if(typeof(this.stylesheets[i])!='string'){continue;}st+='<link rel="stylesheet" href="'+this.stylesheets[i]+'" type="text/css">';
 }}st+='<style type="text/css">'+'IMG { cursor: pointer } '+'</style>';var A='roo-htmleditor-body';if(this.bodyCls.length){A+=' '+this.bodyCls;}return '<html><head>'+st+' </head><body contenteditable="true" data-enable-grammerly="true" class="'+A+'"></body></html>';
@@ -2009,37 +2031,39 @@ this.doc.open();this.doc.write(this.getDocMarkup());this.doc.close();var C={run:
 }},interval:10,duration:10000,scope:this};Roo.TaskMgr.start(C);},onResize:function(w,h){Roo.log('resize: '+w+','+h);if(!this.iframe){return;}if(typeof w=='number'){this.iframe.style.width=w+'px';}if(typeof h=='number'){this.iframe.style.height=h+'px';if(this.doc){(this.doc.body||this.doc.documentElement).style.height=(h-(this.iframePad*2))+'px';
 }}},toggleSourceEdit:function(A){this.sourceEditMode=A===true;if(this.sourceEditMode){Roo.get(this.iframe).addClass(['x-hidden','hide','d-none']);}else{Roo.get(this.iframe).removeClass(['x-hidden','hide','d-none']);this.deferFocus();}},cleanHtml:function(A){A=String(A);
 if(A.length>5){if(Roo.isSafari){A=A.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi,'');}}if(A=='&nbsp;'){A='';}return A;},syncValue:function(){if(this.initialized){this.undoManager.addEvent();var bd=(this.doc.body||this.doc.documentElement);
-var A=document.createElement('div');A.innerHTML=bd.innerHTML;new Roo.htmleditor.FilterBlock({node:A});var B=A.innerHTML;if(Roo.isSafari){var bs=bd.getAttribute('style');var m=bs?bs.match(/text-align:(.*?);/i):false;if(m&&m[1]){B='<div style="'+m[0]+'">'+B+'</div>';
+var A=document.createElement('div');A.innerHTML=bd.innerHTML;if(this.enableBlocks){new Roo.htmleditor.FilterBlock({node:A});}var B=A.innerHTML;if(Roo.isSafari){var bs=bd.getAttribute('style');var m=bs?bs.match(/text-align:(.*?);/i):false;if(m&&m[1]){B='<div style="'+m[0]+'">'+B+'</div>';
 }}B=this.cleanHtml(B);B=B.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0080-\uFFFF]/g,function(C){var cc=C.charCodeAt();if(C.length==2){var D=C.charCodeAt(0)-0xD800;var E=C.charCodeAt(1)-0xDC00;cc=(D*0x400)+E+0x10000;}else if((cc>=0x4E00&&cc<0xA000)||(cc>=0x3400&&cc<0x4E00)||(cc>=0xf900&&cc<0xfb00)){return C;
 }return "&#"+cc+";";});if(this.owner.fireEvent('beforesync',this,B)!==false){this.el.dom.value=B;this.owner.fireEvent('sync',this,B);}}},pushValue:function(){if(this.initialized){var v=this.el.dom.value.trim();if(this.owner.fireEvent('beforepush',this,v)!==false){var d=(this.doc.body||this.doc.documentElement);
-d.innerHTML=v;this.el.dom.value=d.innerHTML;this.owner.fireEvent('push',this,v);}Roo.htmleditor.Block.initAll(this.doc.body);var lc=this.doc.body.lastChild;if(lc&&lc.nodeType==1&&lc.getAttribute("contenteditable")=="false"){this.doc.body.appendChild(this.doc.createElement('br'));
-}}},deferFocus:function(){this.focus.defer(10,this);},focus:function(){if(this.win&&!this.sourceEditMode){this.win.focus();}else{this.el.focus();}},assignDocWin:function(){var A=this.iframe;if(Roo.isIE){this.doc=A.contentWindow.document;this.win=A.contentWindow;
-}else{if(!Roo.get(this.frameId)&&!A.contentDocument){return;}this.doc=(A.contentDocument||Roo.get(this.frameId).dom.document);this.win=(A.contentWindow||Roo.get(this.frameId).dom.contentWindow);}},initEditor:function(){this.assignDocWin();this.doc.designMode="on";
-this.doc.open();this.doc.write(this.getDocMarkup());this.doc.close();var A=(this.doc.body||this.doc.documentElement);A.bgProperties='fixed';Roo.EventManager.on(this.doc,{'mouseup':this.onEditorEvent,'dblclick':this.onEditorEvent,'click':this.onEditorEvent,'keyup':this.onEditorEvent,buffer:100,scope:this}
+d.innerHTML=v;this.el.dom.value=d.innerHTML;this.owner.fireEvent('push',this,v);}if(this.autoClean){new Roo.htmleditor.FilterParagraph({node:this.doc.body});new Roo.htmleditor.FilterSpan({node:this.doc.body});}Roo.htmleditor.Block.initAll(this.doc.body);var lc=this.doc.body.lastChild;
+if(lc&&lc.nodeType==1&&lc.getAttribute("contenteditable")=="false"){this.doc.body.appendChild(this.doc.createElement('br'));}}},deferFocus:function(){this.focus.defer(10,this);},focus:function(){if(this.win&&!this.sourceEditMode){this.win.focus();}else{this.el.focus();
+}},assignDocWin:function(){var A=this.iframe;if(Roo.isIE){this.doc=A.contentWindow.document;this.win=A.contentWindow;}else{if(!Roo.get(this.frameId)&&!A.contentDocument){return;}this.doc=(A.contentDocument||Roo.get(this.frameId).dom.document);this.win=(A.contentWindow||Roo.get(this.frameId).dom.contentWindow);
+}},initEditor:function(){this.assignDocWin();this.doc.designMode="on";this.doc.open();this.doc.write(this.getDocMarkup());this.doc.close();var A=(this.doc.body||this.doc.documentElement);A.bgProperties='fixed';Roo.EventManager.on(this.doc,{'mouseup':this.onEditorEvent,'dblclick':this.onEditorEvent,'click':this.onEditorEvent,'keyup':this.onEditorEvent,buffer:100,scope:this}
 );Roo.EventManager.on(this.doc,{'paste':this.onPasteEvent,scope:this});if(Roo.isGecko){Roo.EventManager.on(this.doc,'keypress',this.mozKeyPress,this);}if(Roo.isIE||Roo.isSafari||Roo.isOpera){Roo.EventManager.on(this.doc,'keydown',this.fixKeys,this);}this.initialized=true;
 new Roo.htmleditor.KeyEnter({core:this});this.owner.fireEvent('initialize',this);this.pushValue();},onPasteEvent:function(e,v){var cd=(e.browserEvent.clipboardData||window.clipboardData);if(cd.files.length>0){var A=(window.createObjectURL&&window)||(window.URL&&URL.revokeObjectURL&&URL)||(window.webkitURL&&webkitURL);
 var B=A.createObjectURL(cd.files[0]);this.insertAtCursor('<img src=" + url + ">');return false;}var C=cd.getData('text/html');var D=new Roo.rtf.Parser(cd.getData('text/rtf'));var E=D.doc?D.doc.getElementsByType('pict'):[];Roo.log(E);E=E.filter(function(g){return !g.path.match(/^rtf\/(head|pgdsctbl|listtable)/);
 }).map(function(g){return g.toDataURL();});C=this.cleanWordChars(C);var d=(new DOMParser().parseFromString(C,'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(E.length>0){Roo.each(d.getElementsByTagName('img'),function(F,i){F.setAttribute('src',E[i]);});}new Roo.htmleditor.FilterStyleToTag({node:d});new Roo.htmleditor.FilterAttributes({node:d,attrib_white:['href','src','name','align'],attrib_clean:['href','src']}
-);new Roo.htmleditor.FilterBlack({node:d,tag:this.black});new Roo.htmleditor.FilterKeepChildren({node:d,tag:['FONT']});new Roo.htmleditor.FilterParagraph({node:d});new Roo.htmleditor.FilterSpan({node:d});new Roo.htmleditor.FilterLongBr({node:d});this.insertAtCursor(d.innerHTML);
-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=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.owner.fireEvent('editorevent',this,e);this.syncValue();},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){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;
+return false;}if(E.length>0){Roo.each(d.getElementsByTagName('img'),function(F,i){F.setAttribute('src',E[i]);});}if(this.autoClean){new Roo.htmleditor.FilterStyleToTag({node:d});new Roo.htmleditor.FilterAttributes({node:d,attrib_white:['href','src','name','align'],attrib_clean:['href','src']}
+);new Roo.htmleditor.FilterBlack({node:d,tag:this.black});new Roo.htmleditor.FilterKeepChildren({node:d,tag:['FONT']});new Roo.htmleditor.FilterParagraph({node:d});new Roo.htmleditor.FilterSpan({node:d});new Roo.htmleditor.FilterLongBr({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.win.focus();this.execCmd(A);this.deferFocus();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;}};}}(),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.isIE?this.doc.selection:this.win.getSelection();
-},selectNode:function(A){var B=A.ownerDocument.createRange();try{B.selectNode(A);}catch(e){B.selectNodeContents(A);}var s=this.win.getSelection();s.removeAllRanges();s.addRange(B);},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]);
+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();
@@ -2060,24 +2084,25 @@ Roo.HtmlEditorCore.black=['APPLET','BASE','BASEFONT','BGSOUND','BLINK','BODY','F
 Roo.HtmlEditorCore.tag_remove=['FONT','TBODY'];Roo.HtmlEditorCore.ablack=['on'];Roo.HtmlEditorCore.aclean=['action','background','codebase','dynsrc','href','lowsrc'];Roo.HtmlEditorCore.pwhite=['http','https','mailto'];Roo.HtmlEditorCore.cwhite=[];Roo.HtmlEditorCore.cblack=[];
 
 // Roo/form/HtmlEditor.js
-Roo.form.HtmlEditor=function(A){Roo.form.HtmlEditor.superclass.constructor.call(this,A);if(!this.toolbars){this.toolbars=[];}this.editorcore=new Roo.HtmlEditorCore(Roo.apply({owner:this},A));};Roo.extend(Roo.form.HtmlEditor,Roo.form.Field,{clearUp:true,toolbars:false,resizable:false,height:300,width:500,stylesheets:false,cblack:false,cwhite:false,black:false,white:false,allowComments:false,bodyCls:'',frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',actionMode:'container',defaultAutoCreate:{tag:"textarea",style:"width:500px;height:300px;",autocomplete:"new-password"}
+Roo.form.HtmlEditor=function(A){Roo.form.HtmlEditor.superclass.constructor.call(this,A);if(!this.toolbars){this.toolbars=[];}this.editorcore=new Roo.HtmlEditorCore(Roo.apply({owner:this},A));};Roo.extend(Roo.form.HtmlEditor,Roo.form.Field,{clearUp:true,toolbars:false,resizable:false,height:300,width:500,stylesheets:false,cblack:false,cwhite:false,black:false,white:false,allowComments:false,enableBlocks:true,autoClean:true,bodyCls:'',frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',actionMode:'container',defaultAutoCreate:{tag:"textarea",style:"width:500px;height:300px;",autocomplete:"new-password"}
 ,initComponent:function(){this.addEvents({initialize:true,activate:true,beforesync:true,beforepush:true,sync:true,push:true,editmodechange:true,editorevent:true,firstfocus:true,autosave:true,savedpreview:true,stylesheetsclick:true,paste:true});this.defaultAutoCreate={tag:"textarea",style:'width: '+this.width+'px;height: '+this.height+'px;',autocomplete:"new-password"}
 ;},createToolbar:function(A){Roo.log("create toolbars");if(!A.toolbars||!A.toolbars.length){A.toolbars=[new Roo.form.HtmlEditor.ToolbarStandard()];}for(var i=0;i<A.toolbars.length;i++){A.toolbars[i]=Roo.factory(typeof(A.toolbars[i])=='string'?{xtype:A.toolbars[i]}
-:A.toolbars[i],Roo.form.HtmlEditor);A.toolbars[i].init(A);}},onRender:function(ct,A){var _t=this;Roo.form.HtmlEditor.superclass.onRender.call(this,ct,A);this.wrap=this.el.wrap({cls:'x-html-editor-wrap',cn:{cls:'x-html-editor-tb'}});this.editorcore.onRender(ct,A);
-if(this.resizable){this.resizeEl=new Roo.Resizable(this.wrap,{pinned:true,wrap:true,dynamic:true,minHeight:this.height,height:this.height,handles:this.resizable,width:this.width,listeners:{resize:function(r,w,h){_t.onResize(w,h);}}});}this.createToolbar(this);
-if(!this.width){this.setSize(this.wrap.getSize());}if(this.resizeEl){this.resizeEl.resizeTo.defer(100,this.resizeEl,[this.width,this.height]);}this.keyNav=new Roo.KeyNav(this.el,{"tab":function(e){e.preventDefault();var B=this.getValue();var C=this.el.dom.selectionStart;
-var D=this.el.dom.selectionEnd;if(!e.shiftKey){this.setValue(B.substring(0,C)+"\t"+B.substring(D));this.el.dom.setSelectionRange(D+1,D+1);return;}var f=B.substring(0,C).split("\t");if(f.pop().length!=0){return;}this.setValue(f.join("\t")+B.substring(D));this.el.dom.setSelectionRange(C-1,C-1);
-},"home":function(e){e.preventDefault();var B=this.el.dom.selectionStart;var C=this.getValue().split("\n");if(!C.length){return;}if(e.ctrlKey){this.el.dom.setSelectionRange(0,0);return;}var D=0;for(var i=0;i<C.length;i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;
-}D-=C[i].length;break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);return;}this.el.dom.selectionStart=D;this.el.dom.selectionEnd=B;},"end":function(e){e.preventDefault();var B=this.el.dom.selectionStart;var C=this.getValue().split("\n");if(!C.length){return;
-}if(e.ctrlKey){this.el.dom.setSelectionRange(this.getValue().length,this.getValue().length);return;}var D=0;for(var i=0;i<C.length;i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;}break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);return;}this.el.dom.selectionStart=B;
-this.el.dom.selectionEnd=D;},scope:this,doRelay:function(B,C,D){return Roo.KeyNav.prototype.doRelay.apply(this,arguments);},forceKeyDown:true});},onResize:function(w,h){Roo.form.HtmlEditor.superclass.onResize.apply(this,arguments);var ew=false;var eh=false;
-if(this.el){if(typeof w=='number'){var aw=w-this.wrap.getFrameWidth('lr');this.el.setWidth(this.adjustWidth('textarea',aw));ew=aw;}if(typeof h=='number'){var A=0;for(var i=0;i<this.toolbars.length;i++){A+=this.toolbars[i].tb.el.getHeight();if(this.toolbars[i].footer){A+=this.toolbars[i].footer.el.getHeight();
-}}var ah=h-this.wrap.getFrameWidth('tb')-A;ah-=5;this.el.setHeight(this.adjustWidth('textarea',ah));var eh=ah;}}Roo.log('onResize:'+[w,h,ew,eh].join(','));this.editorcore.onResize(ew,eh);},toggleSourceEdit:function(A){this.editorcore.toggleSourceEdit(A);if(this.editorcore.sourceEditMode){Roo.log('editor - showing textarea');
-this.editorcore.syncValue();this.el.removeClass('x-hidden');this.el.dom.removeAttribute('tabIndex');this.el.focus();this.el.dom.scrollTop=0;for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.hide();
-this.toolbars[i].footer.hide();}}}else{Roo.log('editor - hiding textarea');this.editorcore.pushValue();this.el.addClass('x-hidden');this.el.dom.setAttribute('tabIndex',-1);for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.show();
-this.toolbars[i].footer.show();}}}this.setSize(this.wrap.getSize());this.onResize(this.wrap.getSize().width,this.wrap.getSize().height);this.fireEvent('editmodechange',this,this.editorcore.sourceEditMode);},adjustSize:Roo.BoxComponent.prototype.adjustSize,getResizeEl:function(){return this.wrap;
-},getPositionEl:function(){return this.wrap;},initEvents:function(){this.originalValue=this.getValue();},markInvalid:Roo.emptyFn,clearInvalid:Roo.emptyFn,setValue:function(v){Roo.form.HtmlEditor.superclass.setValue.call(this,v);this.editorcore.pushValue();
-},deferFocus:function(){this.focus.defer(10,this);},focus:function(){this.editorcore.focus();},onDestroy:function(){if(this.rendered){for(var i=0;i<this.toolbars.length;i++){this.toolbars[i].onDestroy();}this.wrap.dom.innerHTML='';this.wrap.remove();}},onFirstFocus:function(){this.editorcore.onFirstFocus();
+:A.toolbars[i],Roo.form.HtmlEditor);A.toolbars[i].init(A);}},getSelectedNode:function(){if(this.toolbars.length<2||!this.toolbars[1].tb){return false;}return this.toolbars[1].tb.selectedNode;},onRender:function(ct,A){var _t=this;Roo.form.HtmlEditor.superclass.onRender.call(this,ct,A);
+this.wrap=this.el.wrap({cls:'x-html-editor-wrap',cn:{cls:'x-html-editor-tb'}});this.editorcore.onRender(ct,A);if(this.resizable){this.resizeEl=new Roo.Resizable(this.wrap,{pinned:true,wrap:true,dynamic:true,minHeight:this.height,height:this.height,handles:this.resizable,width:this.width,listeners:{resize:function(r,w,h){_t.onResize(w,h);
+}}});}this.createToolbar(this);if(!this.width){this.setSize(this.wrap.getSize());}if(this.resizeEl){this.resizeEl.resizeTo.defer(100,this.resizeEl,[this.width,this.height]);}this.keyNav=new Roo.KeyNav(this.el,{"tab":function(e){e.preventDefault();var B=this.getValue();
+var C=this.el.dom.selectionStart;var D=this.el.dom.selectionEnd;if(!e.shiftKey){this.setValue(B.substring(0,C)+"\t"+B.substring(D));this.el.dom.setSelectionRange(D+1,D+1);return;}var f=B.substring(0,C).split("\t");if(f.pop().length!=0){return;}this.setValue(f.join("\t")+B.substring(D));
+this.el.dom.setSelectionRange(C-1,C-1);},"home":function(e){e.preventDefault();var B=this.el.dom.selectionStart;var C=this.getValue().split("\n");if(!C.length){return;}if(e.ctrlKey){this.el.dom.setSelectionRange(0,0);return;}var D=0;for(var i=0;i<C.length;
+i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;}D-=C[i].length;break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);return;}this.el.dom.selectionStart=D;this.el.dom.selectionEnd=B;},"end":function(e){e.preventDefault();var B=this.el.dom.selectionStart;
+var C=this.getValue().split("\n");if(!C.length){return;}if(e.ctrlKey){this.el.dom.setSelectionRange(this.getValue().length,this.getValue().length);return;}var D=0;for(var i=0;i<C.length;i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;}break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);
+return;}this.el.dom.selectionStart=B;this.el.dom.selectionEnd=D;},scope:this,doRelay:function(B,C,D){return Roo.KeyNav.prototype.doRelay.apply(this,arguments);},forceKeyDown:true});},onResize:function(w,h){Roo.form.HtmlEditor.superclass.onResize.apply(this,arguments);
+var ew=false;var eh=false;if(this.el){if(typeof w=='number'){var aw=w-this.wrap.getFrameWidth('lr');this.el.setWidth(this.adjustWidth('textarea',aw));ew=aw;}if(typeof h=='number'){var A=0;for(var i=0;i<this.toolbars.length;i++){A+=this.toolbars[i].tb.el.getHeight();
+if(this.toolbars[i].footer){A+=this.toolbars[i].footer.el.getHeight();}}var ah=h-this.wrap.getFrameWidth('tb')-A;ah-=5;this.el.setHeight(this.adjustWidth('textarea',ah));var eh=ah;}}Roo.log('onResize:'+[w,h,ew,eh].join(','));this.editorcore.onResize(ew,eh);
+},toggleSourceEdit:function(A){this.editorcore.toggleSourceEdit(A);if(this.editorcore.sourceEditMode){Roo.log('editor - showing textarea');this.editorcore.syncValue();this.el.removeClass('x-hidden');this.el.dom.removeAttribute('tabIndex');this.el.focus();
+this.el.dom.scrollTop=0;for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.hide();this.toolbars[i].footer.hide();}}}else{Roo.log('editor - hiding textarea');this.editorcore.pushValue();
+this.el.addClass('x-hidden');this.el.dom.setAttribute('tabIndex',-1);for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.show();this.toolbars[i].footer.show();}}}this.setSize(this.wrap.getSize());
+this.onResize(this.wrap.getSize().width,this.wrap.getSize().height);this.fireEvent('editmodechange',this,this.editorcore.sourceEditMode);},adjustSize:Roo.BoxComponent.prototype.adjustSize,getResizeEl:function(){return this.wrap;},getPositionEl:function(){return this.wrap;
+},initEvents:function(){this.originalValue=this.getValue();},markInvalid:Roo.emptyFn,clearInvalid:Roo.emptyFn,setValue:function(v){Roo.form.HtmlEditor.superclass.setValue.call(this,v);this.editorcore.pushValue();},deferFocus:function(){this.focus.defer(10,this);
+},focus:function(){this.editorcore.focus();},onDestroy:function(){if(this.rendered){for(var i=0;i<this.toolbars.length;i++){this.toolbars[i].onDestroy();}this.wrap.dom.innerHTML='';this.wrap.remove();}},onFirstFocus:function(){this.editorcore.onFirstFocus();
 for(var i=0;i<this.toolbars.length;i++){this.toolbars[i].onFirstFocus();}},syncValue:function(){this.editorcore.syncValue();},pushValue:function(){this.editorcore.pushValue();},setStylesheets:function(A){this.editorcore.setStylesheets(A);},removeStylesheets:function(){this.editorcore.removeStylesheets();
 }});
 // Roo/form/HtmlEditor/ToolbarStandard.js
@@ -2122,11 +2147,11 @@ Roo.form.HtmlEditor.ToolbarContext.options={'font-family':[['Helvetica,Arial,san
 this.editorcore=A.editorcore?A.editorcore:A;var B=this.editorcore;var C=B.frameId;var D=this;function btn(id,F,G){var H=C+'-'+id;return {id:H,cmd:id,cls:'x-btn-icon x-edit-'+id,enableToggle:F!==false,scope:B,handler:G||B.relayBtnCmd,clickEvent:'mousedown',tooltip:D.buttonTips[id]||undefined,tabIndex:-1}
 ;}var E=A.wrap.createChild({tag:'div'},A.wrap.dom.firstChild.nextSibling,true);var ty=Roo.form.HtmlEditor.ToolbarContext.types;this.toolbars={};for(var i in ty){this.toolbars[i]=this.buildToolbar(ty[i],i);}this.tb=this.toolbars.BODY;this.tb.el.show();this.buildFooter();
 this.footer.show();A.on('hide',function(){this.footer.hide()},this);A.on('show',function(){this.footer.show()},this);this.rendered=true;A.on('editorevent',this.updateToolbar,this);},updateToolbar:function(A,ev,B){if(ev){ev.stopEvent();}if(!this.editorcore.activated){this.editor.onFirstFocus();
-return;}if(ev&&(ev.type=='mouseup'||ev.type=='click')&&ev.target&&ev.target.tagName!='BODY'){B=ev.target;}Roo.select('.roo-ed-selection',false,this.editorcore.doc).removeClass('roo-ed-selection');var C=this.editorcore.getAllAncestors();var ty=Roo.form.HtmlEditor.ToolbarContext.types;
-if(!B){B=C.length?(C[0]?C[0]:C[1]):this.editorcore.doc.body;B=B?B:this.editorcore.doc.body;B=B.tagName.length?B:this.editorcore.doc.body;}var tn=B.tagName.toUpperCase();var D=this.tb.selectedNode;this.tb.selectedNode=B;var E=tn;var db=false;if(B&&B.hasAttribute('data-block')){db=B;
-}else if(B&&!B.hasAttribute('contenteditable')){var F=Roo.get(B);db=F.findParent('[data-block]');var G=F.findParent('[contenteditable=true]');if(db&&G&&G.tagName!='BODY'){db=false;}}var H=false;if(db){H=Roo.htmleditor.Block.factory(db);if(H){db.className+=' roo-ed-selection';
-tn='BLOCK.'+db.getAttribute('data-block');if(typeof(this.toolbars[tn])=='undefined'){this.toolbars[tn]=this.buildToolbar(false,tn,H.friendly_name,H);}this.toolbars[tn].selectedNode=db;E=H.friendly_name;C=this.editorcore.getAllAncestors();}}if(this.tb.name==tn&&D==this.tb.selectedNode&&ev!==false){return;
-}this.tb.el.hide();this.tb=typeof(this.toolbars[tn])!='undefined'?this.toolbars[tn]:this.toolbars['*'];this.tb.el.show();this.tb.items.first().el.innerHTML=E+':&nbsp;';if(H&&this.tb.fields){this.tb.fields.each(function(e){e.setValue(H[e.name]);});}else if(this.tb.fields&&this.tb.selectedNode){this.tb.fields.each(function(e){if(e.stylename){e.setValue(this.tb.selectedNode.style[e.stylename]);
+return;}if(ev&&(ev.type=='mouseup'||ev.type=='click')&&ev.target&&ev.target.tagName!='BODY'){B=ev.target;}Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e){e.classList.remove('roo-ed-selection');});var C=this.editorcore.getAllAncestors();
+var ty=Roo.form.HtmlEditor.ToolbarContext.types;if(!B){B=C.length?(C[0]?C[0]:C[1]):this.editorcore.doc.body;B=B?B:this.editorcore.doc.body;B=B.tagName.length?B:this.editorcore.doc.body;}var tn=B.tagName.toUpperCase();var D=this.tb.selectedNode;this.tb.selectedNode=B;
+var E=tn;var db=false;if(B&&B.hasAttribute('data-block')){db=B;}else if(B&&B.closest('[data-block]')){db=B.closest('[data-block]');}var F=false;if(db&&this.editorcore.enableBlocks){F=Roo.htmleditor.Block.factory(db);if(F){db.className=(db.classList.length>0?db.className+' ':'')+'roo-ed-selection';
+tn='BLOCK.'+db.getAttribute('data-block');if(typeof(this.toolbars[tn])=='undefined'){this.toolbars[tn]=this.buildToolbar(false,tn,F.friendly_name,F);}this.toolbars[tn].selectedNode=db;E=F.friendly_name;C=this.editorcore.getAllAncestors();}}if(this.tb.name==tn&&D==this.tb.selectedNode&&ev!==false){return;
+}this.tb.el.hide();this.tb=typeof(this.toolbars[tn])!='undefined'?this.toolbars[tn]:this.toolbars['*'];this.tb.el.show();this.tb.items.first().el.innerHTML=E+':&nbsp;';if(F&&this.tb.fields){this.tb.fields.each(function(e){e.setValue(F[e.name]);});}else if(this.tb.fields&&this.tb.selectedNode){this.tb.fields.each(function(e){if(e.stylename){e.setValue(this.tb.selectedNode.style[e.stylename]);
 return;}e.setValue(this.tb.selectedNode.getAttribute(e.attrname));},this);this.updateToolbarStyles(this.tb.selectedNode);}Roo.menu.MenuMgr.hideAll();this.updateFooter(C);},updateToolbarStyles:function(A){var B=false;for(var i in this.styles){B=true;break;
 }if(B&&this.tb.hasStyles){var st=this.tb.fields.item(0);st.store.removeAll();var cn=A.className.split(/\s+/);var C=[];if(this.styles['*']){Roo.each(this.styles['*'],function(v){C.push([v,cn.indexOf(v)>-1?1:0]);});}if(this.styles[tn]){Roo.each(this.styles[tn],function(v){C.push([v,cn.indexOf(v)>-1?1:0]);
 });}st.store.loadData(C);st.collapse();st.setValue(cn);}},updateFooter:function(A){var B='';if(A===false){this.footDisp.dom.innerHTML='';return;}this.footerEls=A.reverse();Roo.each(this.footerEls,function(a,i){if(!a){return;}B+=B.length?' &gt; ':'';B+='<span class="x-ed-loc-'+i+'">'+a.tagName+'</span>';
@@ -2135,15 +2160,14 @@ if(A.menu.el){A.menu.el.destroy();}}A.destroy();});}},onFirstFocus:function(){th
 var tb=new Roo.Toolbar(F);if(A===false&&C){A=C.contextMenu(this);}tb.hasStyles=false;tb.name=nm;tb.add((typeof(B)=='undefined'?nm:B)+":&nbsp;");var G=Array.from(this.styles);if(G&&G.length){tb.hasStyles=true;tb.addField(new Roo.form.ComboBox({store:new Roo.data.SimpleStore({id:'val',fields:['val','selected'],data:[]}
 ),name:'-roo-edit-className',attrname:'className',displayField:'val',typeAhead:false,mode:'local',editable:false,triggerAction:'all',emptyText:'Select Style',selectOnFocus:true,width:130,listeners:{'select':function(c,r,i){tb.selectedNode.className=r?r.get('val'):'';
 E.syncValue();}}}));}var H=Roo.form.HtmlEditor.ToolbarContext;for(var i=0;i<A.length;i++){if(typeof(A[i].xtype)!='undefined'){tb[typeof(A[i].name)=='undefined'?'add':'addField'](Roo.factory(A[i]));continue;}var I=A[i];tb.add(I.title+":&nbsp;");var J=I.opts?I.opts:false;
-if(I.optname){J=Roo.form.HtmlEditor.ToolbarContext.options[I.optname];}if(J){tb.addField(new Roo.form.ComboBox({store:typeof(H.stores[i])!='undefined'?Roo.factory(H.stores[i],Roo.data):new Roo.data.SimpleStore({id:'val',fields:['val','display'],data:J}),name:'-roo-edit-'+A[i].name,attrname:A[i].name,stylename:I.style?I.style:false,displayField:I.displayField?I.displayField:'val',valueField:'val',typeAhead:false,mode:typeof(H.stores[A[i].name])!='undefined'?'remote':'local',editable:false,triggerAction:'all',emptyText:'Select',selectOnFocus:true,width:I.width?I.width:130,listeners:{'select':function(c,r,i){if(tb.selectedNode.hasAttribute('data-block')){var b=Roo.htmleditor.Block.factory(tb.selectedNode);
-b[c.attrname]=r.get('val');b.updateElement(tb.selectedNode);E.syncValue();return;}if(c.stylename){tb.selectedNode.style[c.stylename]=r.get('val');E.syncValue();return;}if(r===false){tb.selectedNode.removeAttribute(c.attrname);E.syncValue();return;}tb.selectedNode.setAttribute(c.attrname,r.get('val'));
-E.syncValue();}}}));continue;}tb.addField(new Roo.form.TextField({name:'-roo-edit-'+A[i].name,attrname:A[i].name,width:I.width,value:'',listeners:{'change':function(f,nv,ov){if(tb.selectedNode.hasAttribute('data-block')){var b=Roo.htmleditor.Block.factory(tb.selectedNode);
-b[f.attrname]=nv;b.updateElement(tb.selectedNode);E.syncValue();return;}tb.selectedNode.setAttribute(f.attrname,nv);E.syncValue();}}}));}var K=this;if(nm=='BODY'){tb.addSeparator();tb.addButton({text:'Stylesheets',listeners:{click:function(){K.editor.fireEvent('stylesheetsclick',K.editor);
-}}});}tb.addFill();tb.addButton({text:C&&C.deleteTitle?C.deleteTitle:'Remove Block or Formating',listeners:{click:function(){var sn=tb.selectedNode;if(C){sn=Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();}if(!sn){return;}var L=sn.childNodes[0]||sn.nextSibling||sn.previousSibling||sn.parentNode;
-if(sn.hasAttribute('data-block')){L=sn.nextSibling||sn.previousSibling||sn.parentNode;sn.parentNode.removeChild(sn);}else if(sn&&sn.tagName!='BODY'){a=new Roo.htmleditor.FilterKeepChildren({tag:false});a.removeTag(sn);}var M=E.createRange();M.setStart(L,0);
-M.setEnd(L,0);var N=E.getSelection();N.removeAllRanges();N.addRange(M);K.updateToolbar(null,null,null);K.updateFooter(false);}}});tb.el.on('click',function(e){e.preventDefault();});tb.el.setVisibilityMode(Roo.Element.DISPLAY);tb.el.hide();return tb;},buildFooter:function(){var A=this.editor.wrap.createChild();
-this.footer=new Roo.Toolbar(A);var B=new Roo.Toolbar.Fill();var _t=this;this.footer.add({text:'&lt;',xtype:'Button',handler:function(){_t.footDisp.scrollTo('left',0,true)}});this.footer.add(B);this.footer.add({text:'&gt;',xtype:'Button',handler:function(){_t.footDisp.select('span').last().scrollIntoView(_t.footDisp,true);
-}});var A=Roo.get(B.el);A.addClass('x-editor-context');this.footDispWrap=A;this.footDispWrap.overflow='hidden';this.footDisp=A.createChild();this.footDispWrap.on('click',this.onContextClick,this)},onContextClick:function(ev,A){ev.preventDefault();var cn=A.className;
+if(I.optname){J=Roo.form.HtmlEditor.ToolbarContext.options[I.optname];}if(J){tb.addField(new Roo.form.ComboBox({store:typeof(H.stores[i])!='undefined'?Roo.factory(H.stores[i],Roo.data):new Roo.data.SimpleStore({id:'val',fields:['val','display'],data:J}),name:'-roo-edit-'+A[i].name,attrname:A[i].name,stylename:I.style?I.style:false,displayField:I.displayField?I.displayField:'val',valueField:'val',typeAhead:false,mode:typeof(H.stores[A[i].name])!='undefined'?'remote':'local',editable:false,triggerAction:'all',emptyText:'Select',selectOnFocus:true,width:I.width?I.width:130,listeners:{'select':function(c,r,i){if(c.stylename){tb.selectedNode.style[c.stylename]=r.get('val');
+E.syncValue();return;}if(r===false){tb.selectedNode.removeAttribute(c.attrname);E.syncValue();return;}tb.selectedNode.setAttribute(c.attrname,r.get('val'));E.syncValue();}}}));continue;}tb.addField(new Roo.form.TextField({name:'-roo-edit-'+A[i].name,attrname:A[i].name,width:I.width,value:'',listeners:{'change':function(f,nv,ov){tb.selectedNode.setAttribute(f.attrname,nv);
+E.syncValue();}}}));}var K=this;var L=!C||C.deleteTitle!==false;if(nm=='BODY'){L=false;tb.addSeparator();tb.addButton({text:'Stylesheets',listeners:{click:function(){K.editor.fireEvent('stylesheetsclick',K.editor);}}});}tb.addFill();if(L){tb.addButton({text:C&&C.deleteTitle?C.deleteTitle:'Remove Block or Formating',listeners:{click:function(){var sn=tb.selectedNode;
+if(C){sn=Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();}if(!sn){return;}var M=sn.childNodes[0]||sn.nextSibling||sn.previousSibling||sn.parentNode;if(sn.hasAttribute('data-block')){M=sn.nextSibling||sn.previousSibling||sn.parentNode;sn.parentNode.removeChild(sn);
+}else if(sn&&sn.tagName!='BODY'){a=new Roo.htmleditor.FilterKeepChildren({tag:false});a.replaceTag(sn);}var N=E.createRange();N.setStart(M,0);N.setEnd(M,0);var O=E.getSelection();O.removeAllRanges();O.addRange(N);K.updateToolbar(null,null,null);K.updateFooter(false);
+}}});}tb.el.on('click',function(e){e.preventDefault();});tb.el.setVisibilityMode(Roo.Element.DISPLAY);tb.el.hide();return tb;},buildFooter:function(){var A=this.editor.wrap.createChild();this.footer=new Roo.Toolbar(A);var B=new Roo.Toolbar.Fill();var _t=this;
+this.footer.add({text:'&lt;',xtype:'Button',handler:function(){_t.footDisp.scrollTo('left',0,true)}});this.footer.add(B);this.footer.add({text:'&gt;',xtype:'Button',handler:function(){_t.footDisp.select('span').last().scrollIntoView(_t.footDisp,true);}});
+var A=Roo.get(B.el);A.addClass('x-editor-context');this.footDispWrap=A;this.footDispWrap.overflow='hidden';this.footDisp=A.createChild();this.footDispWrap.on('click',this.onContextClick,this)},onContextClick:function(ev,A){ev.preventDefault();var cn=A.className;
 if(!cn.match(/x-ed-loc-/)){return;}var n=cn.split('-').pop();var B=this.footerEls;var C=B[n];this.editorcore.selectNode(C);this.updateToolbar(null,null,C);}});
 // Roo/form/BasicForm.js
 Roo.form.BasicForm=function(el,A){this.allItems=[];this.childForms=[];Roo.apply(this,A);this.items=new Roo.util.MixedCollection(false,function(o){return o.id||(o.id=Roo.id());});this.addEvents({beforeaction:true,actionfailed:true,actioncomplete:true});if(el){this.initEl(el);
index 5ed4b3a..5eac5f8 100644 (file)
@@ -5208,7 +5208,167 @@ undoManager.transact({
     
     
 };
-/*
+/**
+ * @class Roo.lib.Range
+ * @constructor
+ * This is a toolkit, normally used to copy features into a Dom Range element
+ * Roo.lib.Range.wrap(x);
+ *
+ *
+ *
+ */
+Roo.lib.Range = function() { };
+
+/**
+ * Wrap a Dom Range object, to give it new features...
+ * @static
+ * @param {Range} the range to wrap
+ */
+Roo.lib.Range.wrap = function(r) {
+    return Roo.apply(r, Roo.lib.Range.prototype);
+};
+/**
+ * find a parent node eg. LI / OL
+ * @param {string|Array} node name or array of nodenames
+ * @return {DomElement|false}
+ */
+Roo.apply(Roo.lib.Range.prototype,
+{
+    
+    closest : function(str)
+    {
+        if (typeof(str) != 'string') {
+            // assume it's a array.
+            for(var i = 0;i < str.length;i++) {
+                var r = this.closest(str[i]);
+                if (r !== false) {
+                    return r;
+                }
+                
+            }
+            return false;
+        }
+        str = str.toLowerCase();
+        var n = this.commonAncestorContainer; // might not be a node
+        while (n.nodeType != 1) {
+            n = n.parentNode;
+        }
+        
+        if (n.nodeName.toLowerCase() == str ) {
+            return n;
+        }
+        if (n.nodeName.toLowerCase() == 'body') {
+            return false;
+        }
+            
+        return n.closest(str) || false;
+        
+    },
+    cloneRange : function()
+    {
+        return Roo.lib.Range.wrap(Range.prototype.cloneRange.call(this));
+    }
+});/**
+ * @class Roo.lib.Selection
+ * @constructor
+ * This is a toolkit, normally used to copy features into a Dom Selection element
+ * Roo.lib.Selection.wrap(x);
+ *
+ *
+ *
+ */
+Roo.lib.Selection = function() { };
+
+/**
+ * Wrap a Dom Range object, to give it new features...
+ * @static
+ * @param {Range} the range to wrap
+ */
+Roo.lib.Selection.wrap = function(r, doc) {
+    Roo.apply(r, Roo.lib.Selection.prototype);
+    r.ownerDocument = doc; // usefull so we dont have to keep referening to it.
+    return r;
+};
+/**
+ * find a parent node eg. LI / OL
+ * @param {string|Array} node name or array of nodenames
+ * @return {DomElement|false}
+ */
+Roo.apply(Roo.lib.Selection.prototype,
+{
+    /**
+     * the owner document
+     */
+    ownerDocument : false,
+    
+    getRangeAt : function(n)
+    {
+        return Roo.lib.Range.wrap(Selection.prototype.getRangeAt.call(this,n));
+    },
+    
+    /**
+     * insert node at selection 
+     * @param {DomElement|string} node
+     * @param {string} cursor (after|in|none) where to place the cursor after inserting.
+     */
+    insertNode: function(node, cursor)
+    {
+        if (typeof(node) == 'string') {
+            node = this.ownerDocument.createElement(node);
+            if (cursor == 'in') {
+                node.innerHTML = '&nbsp;';
+            }
+        }
+        
+        var range = this.getRangeAt(0);
+        
+        if (this.type != 'Caret') {
+            range.deleteContents();
+        }
+        var sn = node.childNodes[0]; // select the contents.
+
+        
+        
+        range.insertNode(node);
+        if (cursor == 'after') {
+            node.insertAdjacentHTML('afterend', '&nbsp;');
+            sn = node.nextSibling;
+        }
+        
+        if (cursor == 'none') {
+            return;
+        }
+        
+        this.cursorText(sn);
+    },
+    
+    cursorText : function(n)
+    {
+       
+        //var range = this.getRangeAt(0);
+        range = Roo.lib.Range.wrap(new Range());
+        //range.selectNode(n);
+        
+        var ix = Array.from(n.parentNode.childNodes).indexOf(n);
+        range.setStart(n.parentNode,ix);
+        range.setEnd(n.parentNode,ix+1);
+        //range.collapse(false);
+         
+        this.removeAllRanges();
+        this.addRange(range);
+        
+        Roo.log([n, range, this,this.baseOffset,this.extentOffset, this.type]);
+    },
+    cursorAfter : function(n)
+    {
+        if (!n.nextSibling || n.nextSibling.nodeValue != '&nbsp;') {
+            n.insertAdjacentHTML('afterend', '&nbsp;');
+        }
+        this.cursorText (n.nextSibling);
+    }
+        
+    
+});/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -5476,10 +5636,15 @@ Roo.DomHelper = function(){
             from.data = to.data;
             return;
         }
-        
+        if (!from.parentNode) {
+            // not sure why this is happening?
+            return;
+        }
         // assume 'to' doesnt have '1/3 nodetypes!
+        // not sure why, by from, parent node might not exist?
         if (from.nodeType !=1 || from.tagName != to.tagName) {
             Roo.log(["ReplaceChild" , from, to ]);
+            
             from.parentNode.replaceChild(to, from);
             return;
         }
index 3ff5f5d..051147b 100644 (file)
@@ -220,6 +220,15 @@ if(this.timer!==false){clearTimeout(this.timer);}this.timer=false;this.merge=fal
 }else{el.undoManager.undo();}e.preventDefault();}});this.scope.addEventListener('keyup',function(e){if((e.ctrlKey||e.metaKey)&&e.keyCode===90){e.preventDefault();}});var t=this;el.addEventListener('input',function(e){if(el.innerHTML==t.current_html){return;
 }if(t.timer!==false){clearTimeout(t.timer);t.timer=false;}t.timer=setTimeout(function(){t.merge=false;},1000);t.addEvent(t.merge);t.merge=true;});},addEvent:function(A){A=typeof(A)=='undefined'?false:A;this.scope.undoManager.transact({scope:this.scope,oldHTML:this.current_html,newHTML:this.scope.innerHTML,execute:function(){}
 ,undo:function(){this.scope.innerHTML=this.current_html=this.oldHTML;},redo:function(){this.scope.innerHTML=this.current_html=this.newHTML;}},false);this.merge=A;this.current_html=this.scope.innerHTML;}};
+// Roo/lib/Range.js
+Roo.lib.Range=function(){};Roo.lib.Range.wrap=function(r){return Roo.apply(r,Roo.lib.Range.prototype);};Roo.apply(Roo.lib.Range.prototype,{closest:function(A){if(typeof(A)!='string'){for(var i=0;i<A.length;i++){var r=this.closest(A[i]);if(r!==false){return r;
+}}return false;}A=A.toLowerCase();var n=this.commonAncestorContainer;while(n.nodeType!=1){n=n.parentNode;}if(n.nodeName.toLowerCase()==A){return n;}if(n.nodeName.toLowerCase()=='body'){return false;}return n.closest(A)||false;},cloneRange:function(){return Roo.lib.Range.wrap(Range.prototype.cloneRange.call(this));
+}});
+// Roo/lib/Selection.js
+Roo.lib.Selection=function(){};Roo.lib.Selection.wrap=function(r,A){Roo.apply(r,Roo.lib.Selection.prototype);r.ownerDocument=A;return r;};Roo.apply(Roo.lib.Selection.prototype,{ownerDocument:false,getRangeAt:function(n){return Roo.lib.Range.wrap(Selection.prototype.getRangeAt.call(this,n));
+},insertNode:function(A,B){if(typeof(A)=='string'){A=this.ownerDocument.createElement(A);if(B=='in'){A.innerHTML='&nbsp;';}}var C=this.getRangeAt(0);if(this.type!='Caret'){C.deleteContents();}var sn=A.childNodes[0];C.insertNode(A);if(B=='after'){A.insertAdjacentHTML('afterend','&nbsp;');
+sn=A.nextSibling;}if(B=='none'){return;}this.cursorText(sn);},cursorText:function(n){range=Roo.lib.Range.wrap(new Range());var ix=Array.from(n.parentNode.childNodes).indexOf(n);range.setStart(n.parentNode,ix);range.setEnd(n.parentNode,ix+1);this.removeAllRanges();
+this.addRange(range);Roo.log([n,range,this,this.baseOffset,this.extentOffset,this.type]);},cursorAfter:function(n){if(!n.nextSibling||n.nextSibling.nodeValue!='&nbsp;'){n.insertAdjacentHTML('afterend','&nbsp;');}this.cursorText(n.nextSibling);}});
 // Roo/DomHelper.js
 if(typeof Range!="undefined"&&typeof Range.prototype.createContextualFragment=="undefined"){Range.prototype.createContextualFragment=function(A){var B=window.document;var C=B.createElement("div");C.innerHTML=A;var D=B.createDocumentFragment(),n;while((n=C.firstChild)){D.appendChild(n);
 }return D;};}Roo.DomHelper=function(){var A=null;var B=/^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;var C=/^table|tbody|tr|td$/i;var D={};var E=function(o){if(typeof o=='string'){return o;}var b="";if(!o.tag){o.tag="div";}b+="<"+o.tag;
@@ -233,9 +242,9 @@ var i=-1,el=A;while(++i<N&&el.firstChild){el=el.firstChild;}return el;};var ts='
 }if(O=='beforebegin'){R=el;el=el.parentNode;}else{R=el.nextSibling;el=el.parentNode;}Q=G(4,J,P,K);}else if(N=='tr'){if(O=='beforebegin'){R=el;el=el.parentNode;Q=G(3,H,P,I);}else if(O=='afterend'){R=el.nextSibling;el=el.parentNode;Q=G(3,H,P,I);}else{if(O=='afterbegin'){R=el.firstChild;
 }Q=G(4,J,P,K);}}else if(N=='tbody'){if(O=='beforebegin'){R=el;el=el.parentNode;Q=G(2,ts,P,te);}else if(O=='afterend'){R=el.nextSibling;el=el.parentNode;Q=G(2,ts,P,te);}else{if(O=='afterbegin'){R=el.firstChild;}Q=G(3,H,P,I);}}else{if(O=='beforebegin'||O=='afterend'){return;
 }if(O=='afterbegin'){R=el.firstChild;}Q=G(2,ts,P,te);}el.insertBefore(Q,R);return Q;};var M=function(N,to){Roo.log(["UpdateNode",N,to]);if(N.nodeType!=to.nodeType){Roo.log(["ReplaceChild - mismatch notType",to,N]);N.parentNode.replaceChild(to,N);}if(N.nodeType==3){if(N.data==to.data){return;
-}N.data=to.data;return;}if(N.nodeType!=1||N.tagName!=to.tagName){Roo.log(["ReplaceChild",N,to]);N.parentNode.replaceChild(to,N);return;}var ar=Array.from(N.attributes);for(var i=0;i<ar.length;i++){if(to.hasAttribute(ar[i].name)){continue;}if(ar[i].name=='id'){continue;
-}Roo.log("removeAttribute"+ar[i].name);N.removeAttribute(ar[i].name);}ar=to.attributes;for(var i=0;i<ar.length;i++){if(N.getAttribute(ar[i].name)==to.getAttribute(ar[i].name)){Roo.log("skipAttribute "+ar[i].name+'='+to.getAttribute(ar[i].name));continue;}
-Roo.log("updateAttribute "+ar[i].name+'=>'+to.getAttribute(ar[i].name));N.setAttribute(ar[i].name,to.getAttribute(ar[i].name));}var O=Array.from(N.childNodes);var P=Array.from(to.childNodes);for(var i=0;i<Math.max(P.length,O.length);i++){if(i>=O.length){N.appendChild(P[i]);
+}N.data=to.data;return;}if(!N.parentNode){return;}if(N.nodeType!=1||N.tagName!=to.tagName){Roo.log(["ReplaceChild",N,to]);N.parentNode.replaceChild(to,N);return;}var ar=Array.from(N.attributes);for(var i=0;i<ar.length;i++){if(to.hasAttribute(ar[i].name)){continue;
+}if(ar[i].name=='id'){continue;}Roo.log("removeAttribute"+ar[i].name);N.removeAttribute(ar[i].name);}ar=to.attributes;for(var i=0;i<ar.length;i++){if(N.getAttribute(ar[i].name)==to.getAttribute(ar[i].name)){Roo.log("skipAttribute "+ar[i].name+'='+to.getAttribute(ar[i].name));
+continue;}Roo.log("updateAttribute "+ar[i].name+'=>'+to.getAttribute(ar[i].name));N.setAttribute(ar[i].name,to.getAttribute(ar[i].name));}var O=Array.from(N.childNodes);var P=Array.from(to.childNodes);for(var i=0;i<Math.max(P.length,O.length);i++){if(i>=O.length){N.appendChild(P[i]);
 Roo.log(["add",P[i]]);}else if(i>=P.length){N.removeChild(O[i]);Roo.log(["remove",O[i]]);}else{M(O[i],P[i]);}}};return {useDom:false,markup:function(o){return E(o);},applyStyles:function(el,N){if(N){el=Roo.fly(el);if(typeof N=="string"){var re=/\s?([a-z\-]*)\:\s?([^;]*);?/gi;
 var O;while((O=re.exec(N))!=null){el.setStyle(O[1],O[2]);}}else if(typeof N=="object"){for(var P in N){el.setStyle(P,N[P]);}}else if(typeof N=="function"){Roo.DomHelper.applyStyles(el,N.call());}}},insertHtml:function(N,el,O){N=N.toLowerCase();if(el.insertAdjacentHTML){if(C.test(el.tagName)){var rs;
 if(rs=L(el.tagName.toLowerCase(),N,el,O)){return rs;}}switch(N){case "beforebegin":el.insertAdjacentHTML('BeforeBegin',O);return el.previousSibling;case "afterbegin":el.insertAdjacentHTML('AfterBegin',O);return el.firstChild;case "beforeend":el.insertAdjacentHTML('BeforeEnd',O);
index 0a30601..c96dc16 100644 (file)
@@ -5208,7 +5208,167 @@ undoManager.transact({
     
     
 };
-/*
+/**
+ * @class Roo.lib.Range
+ * @constructor
+ * This is a toolkit, normally used to copy features into a Dom Range element
+ * Roo.lib.Range.wrap(x);
+ *
+ *
+ *
+ */
+Roo.lib.Range = function() { };
+
+/**
+ * Wrap a Dom Range object, to give it new features...
+ * @static
+ * @param {Range} the range to wrap
+ */
+Roo.lib.Range.wrap = function(r) {
+    return Roo.apply(r, Roo.lib.Range.prototype);
+};
+/**
+ * find a parent node eg. LI / OL
+ * @param {string|Array} node name or array of nodenames
+ * @return {DomElement|false}
+ */
+Roo.apply(Roo.lib.Range.prototype,
+{
+    
+    closest : function(str)
+    {
+        if (typeof(str) != 'string') {
+            // assume it's a array.
+            for(var i = 0;i < str.length;i++) {
+                var r = this.closest(str[i]);
+                if (r !== false) {
+                    return r;
+                }
+                
+            }
+            return false;
+        }
+        str = str.toLowerCase();
+        var n = this.commonAncestorContainer; // might not be a node
+        while (n.nodeType != 1) {
+            n = n.parentNode;
+        }
+        
+        if (n.nodeName.toLowerCase() == str ) {
+            return n;
+        }
+        if (n.nodeName.toLowerCase() == 'body') {
+            return false;
+        }
+            
+        return n.closest(str) || false;
+        
+    },
+    cloneRange : function()
+    {
+        return Roo.lib.Range.wrap(Range.prototype.cloneRange.call(this));
+    }
+});/**
+ * @class Roo.lib.Selection
+ * @constructor
+ * This is a toolkit, normally used to copy features into a Dom Selection element
+ * Roo.lib.Selection.wrap(x);
+ *
+ *
+ *
+ */
+Roo.lib.Selection = function() { };
+
+/**
+ * Wrap a Dom Range object, to give it new features...
+ * @static
+ * @param {Range} the range to wrap
+ */
+Roo.lib.Selection.wrap = function(r, doc) {
+    Roo.apply(r, Roo.lib.Selection.prototype);
+    r.ownerDocument = doc; // usefull so we dont have to keep referening to it.
+    return r;
+};
+/**
+ * find a parent node eg. LI / OL
+ * @param {string|Array} node name or array of nodenames
+ * @return {DomElement|false}
+ */
+Roo.apply(Roo.lib.Selection.prototype,
+{
+    /**
+     * the owner document
+     */
+    ownerDocument : false,
+    
+    getRangeAt : function(n)
+    {
+        return Roo.lib.Range.wrap(Selection.prototype.getRangeAt.call(this,n));
+    },
+    
+    /**
+     * insert node at selection 
+     * @param {DomElement|string} node
+     * @param {string} cursor (after|in|none) where to place the cursor after inserting.
+     */
+    insertNode: function(node, cursor)
+    {
+        if (typeof(node) == 'string') {
+            node = this.ownerDocument.createElement(node);
+            if (cursor == 'in') {
+                node.innerHTML = '&nbsp;';
+            }
+        }
+        
+        var range = this.getRangeAt(0);
+        
+        if (this.type != 'Caret') {
+            range.deleteContents();
+        }
+        var sn = node.childNodes[0]; // select the contents.
+
+        
+        
+        range.insertNode(node);
+        if (cursor == 'after') {
+            node.insertAdjacentHTML('afterend', '&nbsp;');
+            sn = node.nextSibling;
+        }
+        
+        if (cursor == 'none') {
+            return;
+        }
+        
+        this.cursorText(sn);
+    },
+    
+    cursorText : function(n)
+    {
+       
+        //var range = this.getRangeAt(0);
+        range = Roo.lib.Range.wrap(new Range());
+        //range.selectNode(n);
+        
+        var ix = Array.from(n.parentNode.childNodes).indexOf(n);
+        range.setStart(n.parentNode,ix);
+        range.setEnd(n.parentNode,ix+1);
+        //range.collapse(false);
+         
+        this.removeAllRanges();
+        this.addRange(range);
+        
+        Roo.log([n, range, this,this.baseOffset,this.extentOffset, this.type]);
+    },
+    cursorAfter : function(n)
+    {
+        if (!n.nextSibling || n.nextSibling.nodeValue != '&nbsp;') {
+            n.insertAdjacentHTML('afterend', '&nbsp;');
+        }
+        this.cursorText (n.nextSibling);
+    }
+        
+    
+});/*
  * Based on:
  * Ext JS Library 1.1.1
  * Copyright(c) 2006-2007, Ext JS, LLC.
@@ -5476,10 +5636,15 @@ Roo.DomHelper = function(){
             from.data = to.data;
             return;
         }
-        
+        if (!from.parentNode) {
+            // not sure why this is happening?
+            return;
+        }
         // assume 'to' doesnt have '1/3 nodetypes!
+        // not sure why, by from, parent node might not exist?
         if (from.nodeType !=1 || from.tagName != to.tagName) {
             Roo.log(["ReplaceChild" , from, to ]);
+            
             from.parentNode.replaceChild(to, from);
             return;
         }
@@ -39824,7 +39989,7 @@ Roo.extend(Roo.menu.Item, Roo.menu.BaseItem, {
      */
     text: '',
      /**
-     * @cfg {String} HTML to render in menu
+     * @cfg {String} html to render in menu
      * The text to show on the menu item (HTML version).
      */
     html: '',
@@ -46023,7 +46188,7 @@ Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
         var cn = Array.from(node.childNodes);
         var nn = node;
         Roo.each(inject, function(t) {
-            var nc = node.ownerDocument.createelement(t);
+            var nc = node.ownerDocument.createElement(t);
             nn.appendChild(nc);
             nn = nc;
         });
@@ -46295,6 +46460,8 @@ Roo.htmleditor.Tidy.prototype = {
 
 
 
+
+
 Roo.htmleditor.KeyEnter = function(cfg) {
     Roo.apply(this, cfg);
     // this does not actually call walk as it's really just a abstract class
@@ -46311,89 +46478,58 @@ Roo.htmleditor.KeyEnter.prototype = {
     
     keypress : function(e)
     {
-        if (e.charCode != 13) {
+        if (e.charCode != 13 && e.charCode != 10) {
+            Roo.log([e.charCode,e]);
             return true;
         }
         e.preventDefault();
         // https://stackoverflow.com/questions/18552336/prevent-contenteditable-adding-div-on-enter-chrome
         var doc = this.core.doc;
-        
-        var docFragment = doc.createDocumentFragment();
-    
-        //add a new line
+          //add a new line
        
     
-    
-        var range = this.core.win.getSelection().getRangeAt(0);
-        var n = range.commonAncestorContainer ;
-        while (n && n.nodeType != 1) {
-            n  = n.parentNode;
-        }
-        var li = false;
-        if (n && n.tagName == 'UL') {
-            li = doc.createElement('LI');
-            n.appendChild(li);
-            
-        }
-        if (n && n.tagName == 'LI') {
-            li = doc.createElement('LI');
-            if (n.nextSibling) {
-                n.parentNode.insertBefore(li, n.firstSibling);
-                
-            } else {
-                n.parentNode.appendChild(li);
-            }
-        }
-        if (li) {   
-            range = doc.createRange();
-            range.setStartAfter(li);
-            range.collapse(true);
-        
-            //make the cursor there
-            var sel = this.core.win.getSelection();
-            sel.removeAllRanges();
-            sel.addRange(range);
+        var sel = this.core.getSelection();
+        var range = sel.getRangeAt(0);
+        var n = range.commonAncestorContainer;
+        var pc = range.closest([ 'ol', 'ul']);
+        var pli = range.closest('li');
+        if (!pc || e.ctrlKey) {
+            sel.insertNode('br', 'after'); 
+         
             this.core.undoManager.addEvent();
+            this.core.fireEditorEvent(e);
             return false;
-            
-            
         }
-        var newEle = doc.createTextNode('\n');
-        docFragment.appendChild(newEle);
         
-        //add the br, or p, or something else
-        newEle = doc.createElement('br');
-        //newEle.setAttribute('data-id', Roo.htmleditor.KeyEnter.i++);
-        docFragment.appendChild(newEle);
-        doc.createTextNode('\n');
-        docFragment.appendChild(newEle);
-        
-        range.deleteContents();
-        range.insertNode(docFragment);  //<< inseting here...
-         
-        var ns = newEle.nextSibling;
-        while (ns && ns.nodeType == 3) { 
-            ns = ns.nextSibling;
+        // deal with <li> insetion
+        if (pli.innerText.trim() == '' &&
+            pli.previousSibling &&
+            pli.previousSibling.nodeName == 'LI' &&
+            pli.previousSibling.innerText.trim() ==  '') {
+            pli.parentNode.removeChild(pli.previousSibling);
+            sel.cursorAfter(pc);
+            this.core.undoManager.addEvent();
+            this.core.fireEditorEvent(e);
+            return false;
         }
-        
-        if (!ns) {
-            //Roo.log('add extra');
-            ns = doc.createElement('br');
-            //ns.setAttribute('data-id', 'x' +  Roo.htmleditor.KeyEnter.i++);
-            newEle.parentNode.appendChild(ns);
+    
+        var li = doc.createElement('LI');
+        li.innerHTML = '&nbsp;';
+        if (!pli || !pli.firstSibling) {
+            pc.appendChild(li);
+        } else {
+            pli.parentNode.insertBefore(li, pli.firstSibling);
         }
+        sel.cursorText (li.firstChild);
+      
+        this.core.undoManager.addEvent();
+        this.core.fireEditorEvent(e);
+
+        return false;
         
+    
         
         
-        range = doc.createRange();
-        range.setStartAfter(newEle);
-        range.collapse(true);
-        
-        var sel = this.core.win.getSelection();
-        sel.removeAllRanges();
-        sel.addRange(range);
-        //this.core.undoManager.addEvent();
-        return false;
          
     }
 };
@@ -46424,7 +46560,7 @@ Roo.htmleditor.Block.factory = function(node)
     var cc = Roo.htmleditor.Block.cache;
     var id = Roo.get(node).id;
     if (typeof(cc[id]) != 'undefined' && (!cc[id].node || cc[id].node.closest('body'))) {
-        Roo.htmleditor.Block.cache[id].readElement();
+        Roo.htmleditor.Block.cache[id].readElement(node);
         return Roo.htmleditor.Block.cache[id];
     }
     var db  = node.getAttribute('data-block');
@@ -46506,14 +46642,17 @@ Roo.htmleditor.Block.prototype = {
             // but kiss for now.
             n = node.getElementsByTagName(tag).item(0);
         }
+        if (!n) {
+            return '';
+        }
         if (attr == 'html') {
             return n.innerHTML;
         }
         if (attr == 'style') {
-            return n.style[style]
+            return n.style[style]
         }
         
-        return Roo.get(n).attr(attr);
+        return n.hasAttribute(attr) ? n.getAttribute(attr) : '';
             
     },
     /**
@@ -46544,8 +46683,8 @@ Roo.htmleditor.Block.prototype = {
  * Block that has an image and a figcaption
  * @cfg {String} image_src the url for the image
  * @cfg {String} align (left|right) alignment for the block default left
- * @cfg {String} text_align (left|right) alignment for the text caption default left.
  * @cfg {String} caption the text to appear below  (and in the alt tag)
+ * @cfg {String} caption_display (block|none) display or not the caption
  * @cfg {String|number} image_width the width of the image number or %?
  * @cfg {String|number} image_height the height of the image number or %?
  * 
@@ -46567,46 +46706,164 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
     
     // setable values.
     image_src: '',
-    
-    align: 'left',
+    align: 'center',
     caption : '',
-    text_align: 'left',
+    caption_display : 'block',
+    width : '100%',
     
-    width : '46%',
-    margin: '2%',
+    // margin: '2%', not used
+    
+    text_align: 'left', //   (left|right) alignment for the text caption default left. - not used at present
+
     
     // used by context menu
     friendly_name : 'Image with caption',
     deleteTitle : "Delete Image and Caption",
     
-    context : { // ?? static really
-        width : {
-            title: "Width",
-            width: 40
-            // ?? number
-        },
-        margin : {
-            title: "Margin",
-            width: 40
-            // ?? number
-        },
-        align: {
-            title: "Align",
-            opts : [[ "left"],[ "right"]],
-            width : 80
+    contextMenu : function(toolbar)
+    {
+        
+        var block = function() {
+            return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+        };
+        
+        
+        var rooui =  typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+        
+        var syncValue = toolbar.editorcore.syncValue;
+        
+        var fields = {};
+        
+        return [
+             {
+                xtype : 'TextItem',
+                text : "Source: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'TextField',
+                allowBlank : false,
+                width : 150,
+                name : 'image_src',
+                listeners : {
+                    keyup : function (combo, e)
+                    { 
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.image_src = this.getValue();
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form
+                
+            },
+            {
+                xtype : 'TextItem',
+                text : "Width: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'width',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.width = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['auto'],
+                        ['50%'],
+                        ['100%']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            {
+                xtype : 'TextItem',
+                text : "Align: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'align',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.align = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['left'],
+                        ['right'],
+                        ['center']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
             
-        },
-        text_align: {
-            title: "Caption Align",
-            opts : [ [ "left"],[ "right"],[ "center"]],
-            width : 80
-        },
+            
+            {
+                xtype : 'Button',
+                text: 'Hide Caption',
+                name : 'caption_display',
+                pressed : false,
+                enableToggle : true,
+                setValue : function(v) {
+                    this.toggle(v == 'block' ? false : true);
+                },
+                listeners : {
+                    toggle: function (btn, state)
+                    {
+                        var b  = block();
+                        b.caption_display = b.caption_display == 'block' ? 'none' : 'block';
+                        this.setText(b.caption_display == 'block' ? "Hide Caption" : "Show Caption");
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            }
+        ];
         
-       
-        image_src : {
-            title: "Src",
-            width: 220
-        }
     },
     /**
      * create a DomHelper friendly object - for use with
@@ -46617,48 +46874,66 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
         var d = document.createElement('div');
         d.innerHTML = this.caption;
         
-        return {
+        return  {
             tag: 'figure',
             'data-block' : 'Figure',
             contenteditable : 'false',
             style : {
-                display: 'table',
+                display: 'block',
                 float :  this.align ,
-                width :  this.width,
-                margin:  this.margin
+                'max-width':  this.width,
+                width : 'auto',
+                margin:  0,
+                padding: '10px'
+                
             },
+            align : this.align,
             cn : [
                 {
                     tag : 'img',
                     src : this.image_src,
                     alt : d.innerText.replace(/\n/g, " "), // removeHTML..
                     style: {
-                        width: '100%'
+                        width : 'auto',
+                        'max-width': '100%',
+                        margin : '0px' 
+                        
+                        
                     }
                 },
                 {
                     tag: 'figcaption',
                     contenteditable : true,
                     style : {
-                        'text-align': this.text_align
+                        'text-align': 'left',
+                        'margin-top' : '16px',
+                        'font-size' : '16px',
+                        'line-height' : '24px',
+                        'font-style': 'italic',
+                        display : this.caption_display
                     },
                     html : this.caption
                     
                 }
             ]
         };
+         
     },
     
     readElement : function(node)
     {
         this.image_src = this.getVal(node, 'img', 'src');
-        this.align = this.getVal(node, 'figure', 'style', 'float');
+        this.align = this.getVal(node, 'figure', 'align');
         this.caption = this.getVal(node, 'figcaption', 'html');
-        this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
-        this.width = this.getVal(node, 'figure', 'style', 'width');
-        this.margin = this.getVal(node, 'figure', 'style', 'margin');
+        //this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
+        this.width = this.getVal(node, 'figure', 'style', 'max-width');
+        //this.margin = this.getVal(node, 'figure', 'style', 'margin');
         
-    } 
+    },
+    removeNode : function()
+    {
+        return this.node;
+    }
     
   
    
@@ -46728,6 +47003,11 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
         var fields = {};
         
         return [
+            {
+                xtype : 'TextItem',
+                text : "Width: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
             {
                 xtype : 'ComboBox',
                 allowBlank : false,
@@ -46742,11 +47022,12 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     select : function (combo, r, index)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         var b = block();
                         b.width = r.get('val');
                         b.updateElement();
                         syncValue();
-                        
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.form,
@@ -46774,8 +47055,10 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         block().removeColumn();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -46786,8 +47069,10 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         block().addColumn();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -46805,8 +47090,10 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         block().removeRow();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -46819,6 +47106,7 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                     {
                         block().addRow();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -46833,6 +47121,7 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                     {
                         block().resetWidths();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -46928,22 +47217,18 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
         
         this.rows = [];
         this.no_row = 0;
-        var trs = Array.from(node.getElementsByTagName('tr'));
+        var trs = Array.from(node.rows);
         trs.forEach(function(tr) {
             var row =  [];
             this.rows.push(row);
-            if (Roo.get(tr).hasClass('roo-html-editor-el')) { // ??? this is for our 'row' selection'
-                return;
-            }
+            
             this.no_row++;
             var no_column = 0;
-            Array.from(tr.getElementsByTagName('td')).forEach(function(td) {
-                if (Roo.get(td).hasClass('roo-html-editor-el')) { // ??? this is for our 'row' selection'
-                    return;
-                }
+            Array.from(tr.cells).forEach(function(td) {
+                
                 var add = {
-                    colspan : td.hasAttribute('colspan') ? td.getAttribute('colspan') : 1,
-                    rowspan : td.hasAttribute('rowspan') ? td.getAttribute('rowspan') : 1,
+                    colspan : td.hasAttribute('colspan') ? td.getAttribute('colspan')*1 : 1,
+                    rowspan : td.hasAttribute('rowspan') ? td.getAttribute('rowspan')*1 : 1,
                     style : td.hasAttribute('style') ? td.getAttribute('style') : '',
                     html : td.innerHTML
                 };
@@ -47109,7 +47394,7 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
     addRow : function()
     {
         
-        row = [];
+        var row = [];
         for (var i = 0; i < this.no_col; i++ ) {
             
             row.push(this.emptyCell());
@@ -47193,6 +47478,7 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     
     width: '',
     textAlign : 'left',
+    valign : 'top',
     
     colspan : 1,
     rowspan : 1,
@@ -47200,7 +47486,7 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     
     // used by context menu
     friendly_name : 'Table Cell',
-    deleteTitle : 'Delete Table',
+    deleteTitle : false, // use our customer delete
     
     // context menu is drawn once..
     
@@ -47269,10 +47555,10 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().shrinkColumn();
                         syncValue();
-                        restoreSel();
+                         toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -47283,14 +47569,55 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().growColumn();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
             },
+            
+            {
+                xtype : 'TextItem',
+                text : "Vertical Align: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 100,
+                name : 'valign',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = cell();
+                        b.valign = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['top'],
+                        ['middle'],
+                        ['bottom'] // there are afew more... 
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            
             {
                 xtype : 'TextItem',
                 text : "Merge Cells: ",
@@ -47305,11 +47632,11 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().mergeRight();
                         //block().growColumn();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -47321,11 +47648,11 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().mergeBelow();
                         //block().growColumn();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -47343,14 +47670,91 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().split();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        toolbar.editorcore.onEditorEvent();
+                                             
                     }
                 },
                 xns : rooui.Toolbar
+            },
+            {
+                xtype : 'Fill',
+                xns : rooui.Toolbar 
+               
+            },
+        
+          
+            {
+                xtype : 'Button',
+                text: 'Delete',
+                 
+                xns : rooui.Toolbar,
+                menu : {
+                    xtype : 'Menu',
+                    xns : rooui.menu,
+                    items : [
+                        {
+                            xtype : 'Item',
+                            html: 'Column',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    
+                                    cell().deleteColumn();
+                                    syncValue();
+                                    toolbar.editorcore.selectNode(t.node);
+                                    toolbar.editorcore.onEditorEvent();   
+                                }
+                            },
+                            xns : rooui.menu
+                        },
+                        {
+                            xtype : 'Item',
+                            html: 'Row',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    cell().deleteRow();
+                                    syncValue();
+                                    
+                                    toolbar.editorcore.selectNode(t.node);
+                                    toolbar.editorcore.onEditorEvent();   
+                                                         
+                                }
+                            },
+                            xns : rooui.menu
+                        },
+                       {
+                            xtype : 'Separator',
+                            xns : rooui.menu
+                        },
+                        {
+                            xtype : 'Item',
+                            html: 'Table',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    var nn = t.node.nextSibling || t.node.previousSibling;
+                                    t.node.parentNode.removeChild(t.node);
+                                    if (nn) { 
+                                        toolbar.editorcore.selectNode(nn, true);
+                                    }
+                                    toolbar.editorcore.onEditorEvent();   
+                                                         
+                                }
+                            },
+                            xns : rooui.menu
+                        }
+                    ]
+                }
             }
+            
             // align... << fixme
             
         ];
@@ -47375,21 +47779,27 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
             tag : 'td',
             contenteditable : 'true', // this stops cell selection from picking the table.
             'data-block' : 'Td',
-            width:  this.width,
+            valign : this.valign,
             style : {  
-                width:  this.width,
                 'text-align' :  this.textAlign,
                 border : 'solid 1px rgb(0, 0, 0)', // ??? hard coded?
-                'border-collapse' : 'collapse' 
+                'border-collapse' : 'collapse',
+                padding : '6px', // 8 for desktop / 4 for mobile
+                'vertical-align': this.valign
             },
             html : this.html
         };
+        if (this.width != '') {
+            ret.width = this.width;
+            ret.style.width = this.width;
+        }
+        
         
         if (this.colspan > 1) {
-            ret.colspan = cell.colspan ;
+            ret.colspan = this.colspan ;
         } 
-        if (ret.rowspan > 1) {
-            this.rowspan = cell.rowspan ;
+        if (this.rowspan > 1) {
+            ret.rowspan = this.rowspan ;
         }
         
            
@@ -47402,7 +47812,8 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     {
         node  = node ? node : this.node ;
         this.width = node.style.width;
-        
+        this.colspan = Math.max(1,1*node.getAttribute('colspan'));
+        this.rowspan = Math.max(1,1*node.getAttribute('rowspan'));
         this.html = node.innerHTML;
         
         
@@ -47422,8 +47833,7 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     removeNode : function()
     {
         return this.node.closest('table');
-        
-        
+         
     },
     
     cellData : false,
@@ -47596,13 +48006,19 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         
          
         var tab = this.node.closest('tr').closest('table');
+        var ctr = tab.rows[0].parentNode;
         Array.from(tab.rows).forEach(function(r, ri){
+            
             Array.from(r.cells).forEach(function(ce, ci){
                 ce.parentNode.removeChild(ce);
             });
+            r.parentNode.removeChild(r);
         });
         for(var r = 0 ; r < table.length; r++) {
             var re = tab.rows[r];
+            
+            var re = tab.ownerDocument.createElement('tr');
+            ctr.appendChild(re);
             for(var c = 0 ; c < table[r].length; c++) {
                 if (table[r][c].cell === false) {
                     continue;
@@ -47718,9 +48134,52 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         }, this);
         this.updateWidths(table);
          
+    },
+    deleteRow : function()
+    {
+        // delete this rows 'tr'
+        // if any of the cells in this row have a rowspan > 1 && row!= this row..
+        // then reduce the rowspan.
+        var table = this.toTableArray();
+        // this.cellData.row;
+        for (var i =0;i< table[this.cellData.row].length ; i++) {
+            var c = table[this.cellData.row][i];
+            if (c.row != this.cellData.row) {
+                
+                c.rowspan--;
+                c.cell.setAttribute('rowspan', c.rowspan);
+                continue;
+            }
+            if (c.rowspan > 1) {
+                c.rowspan--;
+                c.cell.setAttribute('rowspan', c.rowspan);
+            }
+        }
+        table.splice(this.cellData.row,1);
+        this.redrawAllCells(table);
+        
+    },
+    deleteColumn : function()
+    {
+        var table = this.toTableArray();
+        
+        for (var i =0;i< table.length ; i++) {
+            var c = table[i][this.cellData.col];
+            if (c.col != this.cellData.col) {
+                table[i][this.cellData.col].colspan--;
+            } else if (c.colspan > 1) {
+                c.colspan--;
+                c.cell.setAttribute('colspan', c.colspan);
+            }
+            table[i].splice(this.cellData.col,1);
+        }
+        
+        this.redrawAllCells(table);
     }
     
     
+    
+    
 })
 
 //<script type="text/javascript">
@@ -47796,7 +48255,8 @@ Roo.HtmlEditorCore = function(config){
          * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
          * @param {Roo.HtmlEditorCore} this
          */
-        editorevent: true
+        editorevent: true 
+         
         
     });
     
@@ -47832,7 +48292,16 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
      * @cfg {Number} width (in pixels)
      */   
     width: 500,
+     /**
+     * @cfg {boolean} autoClean - default true - loading and saving will remove quite a bit of formating,
+     *         if you are doing an email editor, this probably needs disabling, it's designed
+     */
+    autoClean: true,
     
+    /**
+     * @cfg {boolean} enableBlocks - default true - if the block editor (table and figure should be enabled)
+     */
+    enableBlocks : true,
     /**
      * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
      * 
@@ -47840,7 +48309,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     stylesheets: false,
     
     /**
-     * @cfg {boolean} allowComments - default false - allow comments in HTML source - by default they are stripped - if you are editing email you may need this.
+     * @cfg {boolean} allowComments - default false - allow comments in HTML source
+     *          - by default they are stripped - if you are editing email you may need this.
      */
     allowComments: false,
     // id of frame..
@@ -48065,26 +48535,18 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
             
             var bd = (this.doc.body || this.doc.documentElement);
-            //this.cleanUpPaste(); -- this is done else where and causes havoc..
-            
-            // not sure if this is really the place for this
-            // the blocks are synced occasionaly - since we currently dont add listeners on the blocks
-            // this has to update attributes that get duped.. like alt and caption..
-            
-            
-            //Roo.each(Roo.get(this.doc.body).query('*[data-block]'), function(e) {
-            //     Roo.htmleditor.Block.factory(e);
-            //},this);
+           
             
             
             var div = document.createElement('div');
             div.innerHTML = bd.innerHTML;
-            // remove content editable. (blocks)
-            
+             
            
-            
+            if (this.enableBlocks) {
+                new Roo.htmleditor.FilterBlock({ node : div });
+            }
             //?? tidy?
-            new Roo.htmleditor.FilterBlock({ node : div });
+            
             
             var html = div.innerHTML;
             if(Roo.isSafari){
@@ -48149,6 +48611,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 this.el.dom.value = d.innerHTML;
                 this.owner.fireEvent('push', this, v);
             }
+            if (this.autoClean) {
+                new Roo.htmleditor.FilterParagraph({node : this.doc.body}); // paragraphs
+                new Roo.htmleditor.FilterSpan({node : this.doc.body}); // empty spans
+            }
+            
             Roo.htmleditor.Block.initAll(this.doc.body);
             
             var lc = this.doc.body.lastChild;
@@ -48237,6 +48704,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         if(Roo.isGecko){
             Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
         }
+        //??? needed???
         if(Roo.isIE || Roo.isSafari || Roo.isOpera){
             Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
         }
@@ -48303,25 +48771,39 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 img.setAttribute('src', images[i]);
             });
         }
-        
-      
-        new Roo.htmleditor.FilterStyleToTag({ node : d });
-        new Roo.htmleditor.FilterAttributes({
-            node : d,
-            attrib_white : ['href', 'src', 'name', 'align'],
-            attrib_clean : ['href', 'src' ] 
-        });
-        new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
-        // should be fonts..
-        new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT' ]} );
-        new Roo.htmleditor.FilterParagraph({ node : d });
-        new Roo.htmleditor.FilterSpan({ node : d });
-        new Roo.htmleditor.FilterLongBr({ node : d });
-        
+        if (this.autoClean) {
+            new Roo.htmleditor.FilterStyleToTag({ node : d });
+            new Roo.htmleditor.FilterAttributes({
+                node : d,
+                attrib_white : ['href', 'src', 'name', 'align'],
+                attrib_clean : ['href', 'src' ] 
+            });
+            new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
+            // should be fonts..
+            new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT' ]} );
+            new Roo.htmleditor.FilterParagraph({ node : d });
+            new Roo.htmleditor.FilterSpan({ node : d });
+            new Roo.htmleditor.FilterLongBr({ node : d });
+        }
+        if (this.enableBlocks) {
+                
+            Array.from(d.getElementsByTagName('img')).forEach(function(img) {
+                if (img.closest('figure')) { // assume!! that it's aready
+                    return;
+                }
+                var fig  = new Roo.htmleditor.BlockFigure({
+                    image_src  : img.src
+                });
+                fig.updateElement(img); // replace it..
+                
+            });
+        }
         
         
-        this.insertAtCursor(d.innerHTML);
-        Roo.htmleditor.Block.initAll(this.doc.body);
+        this.insertAtCursor(d.innerHTML.replace(/&nbsp;/g,' '));
+        if (this.enableBlocks) {
+            Roo.htmleditor.Block.initAll(this.doc.body);
+        }
         
         
         e.preventDefault();
@@ -48408,7 +48890,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             this.doc.body.lastChild
            ) {
             var lc = this.doc.body.lastChild;
-            while (lc.nodeType == 3 && lc.nodeValue == '') {
+            // gtx-trans is google translate plugin adding crap.
+            while ((lc.nodeType == 3 && lc.nodeValue == '') || lc.id == 'gtx-trans') {
                 lc = lc.previousSibling;
             }
             if (lc.nodeType == 1 && lc.nodeName != 'BR') {
@@ -48427,10 +48910,15 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         
         
-        this.owner.fireEvent('editorevent', this, e);
+        this.fireEditorEvent(e);
       //  this.updateToolbar();
         this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
     },
+    
+    fireEditorEvent: function(e)
+    {
+        this.owner.fireEvent('editorevent', this, e);
+    },
 
     insertTag : function(tg)
     {
@@ -48475,7 +48963,37 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
      * @param {String} cmd The Midas command
      * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
      */
-    relayCmd : function(cmd, value){
+    relayCmd : function(cmd, value)
+    {
+        
+        switch (cmd) {
+            case 'justifyleft':
+            case 'justifyright':
+            case 'justifycenter':
+                // if we are in a cell, then we will adjust the
+                var n = this.getParentElement();
+                var td = n.closest('td');
+                if (td) {
+                    var bl = Roo.htmleditor.Block.factory(td);
+                    bl.textAlign = cmd.replace('justify','');
+                    bl.updateElement();
+                    this.owner.fireEvent('editorevent', this);
+                    return;
+                }
+                this.execCmd('styleWithCSS', true); // 
+                break;
+            case 'bold':
+            case 'italic':
+                // if there is no selection, then we insert, and set the curson inside it..
+                this.execCmd('styleWithCSS', false); 
+                break;
+                
+        
+            default:
+                break;
+        }
+        
+        
         this.win.focus();
         this.execCmd(cmd, value);
         this.owner.fireEvent('editorevent', this);
@@ -48573,9 +49091,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                         
                 }
                 if(cmd){
-                    this.win.focus();
-                    this.execCmd(cmd);
-                    this.deferFocus();
+                    
+                    this.relayCmd(cmd);
+                    //this.win.focus();
+                    //this.execCmd(cmd);
+                    //this.deferFocus();
                     e.preventDefault();
                 }
                 
@@ -48585,6 +49105,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
     // private
     fixKeys : function(){ // load time branching for fastest keydown performance
+        
+        
         if(Roo.isIE){
             return function(e){
                 var k = e.getKey(), r;
@@ -48629,6 +49151,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                     this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
                     this.deferFocus();
                 }
+               
                 //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
                 //    this.cleanUpPaste.defer(100, this);
                  //   return;
@@ -48645,6 +49168,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                     this.deferFocus();
                     return;
                 }
+                 this.mozKeyPress(e);
+                
                //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
                  //   this.cleanUpPaste.defer(100, this);
                  //   return;
@@ -48678,13 +49203,13 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     getSelection : function() 
     {
         this.assignDocWin();
-        return Roo.isIE ? this.doc.selection : this.win.getSelection();
+        return Roo.lib.Selection.wrap(Roo.isIE ? this.doc.selection : this.win.getSelection(), this.doc);
     },
     /**
      * Select a dom node
      * @param {DomElement} node the node to select
      */
-    selectNode : function(node)
+    selectNode : function(node, collapse)
     {
         var nodeRange = node.ownerDocument.createRange();
         try {
@@ -48692,7 +49217,10 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         } catch (e) {
             nodeRange.selectNodeContents(node);
         }
-        //nodeRange.collapse(true);
+        if (collapse === true) {
+            nodeRange.collapse(true);
+        }
+        //
         var s = this.win.getSelection();
         s.removeAllRanges();
         s.addRange(nodeRange);
@@ -48704,8 +49232,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         // should we cache this!!!!
         
-        
-        
+         
          
         var range = this.createRange(this.getSelection()).cloneRange();
         
@@ -48769,6 +49296,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         return nodes[0];
     },
+    
+    
     createRange: function(sel)
     {
         // this has strange effects when using with 
@@ -49302,11 +49831,19 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
      */
     allowComments: false,
     /**
-     * @cfg {string} bodyCls- default '' default classes to add to body of editable area - usually undoreset is a good start..
+     * @cfg {boolean} enableBlocks - default true - if the block editor (table and figure should be enabled)
      */
+    enableBlocks : true,
     
-    
-     bodyCls : '',
+    /**
+     * @cfg {boolean} autoClean - default true - loading and saving will remove quite a bit of formating,
+     *         if you are doing an email editor, this probably needs disabling, it's designed
+     */
+    autoClean: true,
+    /**
+     * @cfg {string} bodyCls- default '' default classes to add to body of editable area - usually undoreset is a good start..
+     */
+    bodyCls : '',
     
     // id of frame..
     frameId: false,
@@ -49449,8 +49986,19 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
          
         
     },
-
-     
+    /**
+     * get the Context selected node
+     * @returns {DomElement|boolean} selected node if active or false if none
+     * 
+     */
+    getSelectedNode : function()
+    {
+        if (this.toolbars.length < 2 || !this.toolbars[1].tb) {
+            return false;
+        }
+        return this.toolbars[1].tb.selectedNode;
+    
+    },
     // private
     onRender : function(ct, position)
     {
@@ -50885,9 +51433,9 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         // disable everything...
         var ty= Roo.form.HtmlEditor.ToolbarContext.types;
         this.toolbars = {};
-           
+        // block toolbars are built in updateToolbar when needed.
         for (var i in  ty) {
-          
+            
             this.toolbars[i] = this.buildToolbar(ty[i],i);
         }
         this.tb = this.toolbars.BODY;
@@ -50946,8 +51494,13 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
             // this triggers looping?
             //this.editorcore.selectNode(sel);
              
-        }  
-        Roo.select('.roo-ed-selection', false, this.editorcore.doc).removeClass('roo-ed-selection');
+        }
+        
+        // this forces an id..
+        Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e) {
+             e.classList.remove('roo-ed-selection');
+        });
+        //Roo.select('.roo-ed-selection', false, this.editorcore.doc).removeClass('roo-ed-selection');
         //Roo.get(node).addClass('roo-ed-selection');
       
         //var updateFooter = sel ? false : true; 
@@ -50976,24 +51529,28 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         // you are not actually selecting the block.
         if (sel && sel.hasAttribute('data-block')) {
             db = sel;
-        } else if (sel && !sel.hasAttribute('contenteditable')) {
-            var sel_el = Roo.get(sel);
-            db = sel_el.findParent('[data-block]');
-            var cepar = sel_el.findParent('[contenteditable=true]');
-            if (db && cepar && cepar.tagName != 'BODY') {
-               db = false; // we are inside an editable block.. = not sure how we are going to handle nested blocks!?
-            }   
+        } else if (sel && sel.closest('[data-block]')) {
+            
+            db = sel.closest('[data-block]');
+            //var cepar = sel.closest('[contenteditable=true]');
+            //if (db && cepar && cepar.tagName != 'BODY') {
+            //   db = false; // we are inside an editable block.. = not sure how we are going to handle nested blocks!?
+            //}   
         }
         
         
         var block = false;
         //if (db && !sel.hasAttribute('contenteditable') && sel.getAttribute('contenteditable') != 'true' ) {
-        if (db) {
+        if (db && this.editorcore.enableBlocks) {
             block = Roo.htmleditor.Block.factory(db);
             
             
             if (block) {
-                db.className +=  ' roo-ed-selection'; // since we removed it earlier... its not there..
+                 db.className = (
+                        db.classList.length > 0  ? db.className + ' ' : ''
+                    )  + 'roo-ed-selection';
+                 
+                 // since we removed it earlier... its not there..
                 tn = 'BLOCK.' + db.getAttribute('data-block');
                 
                 //this.editorcore.selectNode(db);
@@ -51248,13 +51805,7 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
                     width: item.width ? item.width  : 130,
                     listeners : {
                         'select': function(c, r, i) {
-                            if (tb.selectedNode.hasAttribute('data-block')) {
-                                var b = Roo.htmleditor.Block.factory(tb.selectedNode);
-                                b[c.attrname] = r.get('val');
-                                b.updateElement(tb.selectedNode);
-                                editorcore.syncValue();
-                                return;
-                            }
+                             
                             
                             if (c.stylename) {
                                 tb.selectedNode.style[c.stylename] =  r.get('val');
@@ -51295,14 +51846,7 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
                 listeners: {
                     'change' : function(f, nv, ov) {
                         
-                        if (tb.selectedNode.hasAttribute('data-block')) {
-                            var b = Roo.htmleditor.Block.factory(tb.selectedNode);
-                            b[f.attrname] = nv;
-                            b.updateElement(tb.selectedNode);
-                            editorcore.syncValue();
-                            return;
-                        }
-                        
+                         
                         tb.selectedNode.setAttribute(f.attrname, nv);
                         editorcore.syncValue();
                     }
@@ -51312,8 +51856,9 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         }
         
         var _this = this;
-        
+        var show_delete = !block || block.deleteTitle !== false;
         if(nm == 'BODY'){
+            show_delete = false;
             tb.addSeparator();
         
             tb.addButton( {
@@ -51329,53 +51874,54 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         }
         
         tb.addFill();
-        tb.addButton({
-            text: block && block.deleteTitle ? block.deleteTitle  : 'Remove Block or Formating', // remove the tag, and puts the children outside...
-    
-            listeners : {
-                click : function ()
-                {
-                    var sn = tb.selectedNode;
-                    if (block) {
-                        sn = Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();
+        if (show_delete) {
+            tb.addButton({
+                text: block && block.deleteTitle ? block.deleteTitle  : 'Remove Block or Formating', // remove the tag, and puts the children outside...
+        
+                listeners : {
+                    click : function ()
+                    {
+                        var sn = tb.selectedNode;
+                        if (block) {
+                            sn = Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();
+                            
+                        }
+                        if (!sn) {
+                            return;
+                        }
+                        var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
+                        if (sn.hasAttribute('data-block')) {
+                            stn =  sn.nextSibling || sn.previousSibling || sn.parentNode;
+                            sn.parentNode.removeChild(sn);
+                            
+                        } else if (sn && sn.tagName != 'BODY') {
+                            // remove and keep parents.
+                            a = new Roo.htmleditor.FilterKeepChildren({tag : false});
+                            a.replaceTag(sn);
+                        }
                         
-                    }
-                    if (!sn) {
-                        return;
-                    }
-                    var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
-                    if (sn.hasAttribute('data-block')) {
-                        stn =  sn.nextSibling || sn.previousSibling || sn.parentNode;
-                        sn.parentNode.removeChild(sn);
                         
-                    } else if (sn && sn.tagName != 'BODY') {
-                        // remove and keep parents.
-                        a = new Roo.htmleditor.FilterKeepChildren({tag : false});
-                        a.removeTag(sn);
+                        var range = editorcore.createRange();
+            
+                        range.setStart(stn,0);
+                        range.setEnd(stn,0); 
+                        var selection = editorcore.getSelection();
+                        selection.removeAllRanges();
+                        selection.addRange(range);
+                        
+                        
+                        //_this.updateToolbar(null, null, pn);
+                        _this.updateToolbar(null, null, null);
+                        _this.updateFooter(false);
+                        
                     }
-                    
-                    
-                    var range = editorcore.createRange();
-        
-                    range.setStart(stn,0);
-                    range.setEnd(stn,0); 
-                    var selection = editorcore.getSelection();
-                    selection.removeAllRanges();
-                    selection.addRange(range);
-                    
-                    
-                    //_this.updateToolbar(null, null, pn);
-                    _this.updateToolbar(null, null, null);
-                    _this.updateFooter(false);
-                    
                 }
-            }
-            
+                
+                        
                     
                 
-            
-        });
-        
+            });
+        }    
         
         tb.el.on('click', function(e){
             e.preventDefault(); // what does this do?
index 5dfd60b..def8f5c 100644 (file)
@@ -15520,7 +15520,7 @@ Roo.extend(Roo.menu.Item, Roo.menu.BaseItem, {
      */
     text: '',
      /**
-     * @cfg {String} HTML to render in menu
+     * @cfg {String} html to render in menu
      * The text to show on the menu item (HTML version).
      */
     html: '',
@@ -21719,7 +21719,7 @@ Roo.extend(Roo.htmleditor.FilterStyleToTag, Roo.htmleditor.Filter,
         var cn = Array.from(node.childNodes);
         var nn = node;
         Roo.each(inject, function(t) {
-            var nc = node.ownerDocument.createelement(t);
+            var nc = node.ownerDocument.createElement(t);
             nn.appendChild(nc);
             nn = nc;
         });
@@ -21991,6 +21991,8 @@ Roo.htmleditor.Tidy.prototype = {
 
 
 
+
+
 Roo.htmleditor.KeyEnter = function(cfg) {
     Roo.apply(this, cfg);
     // this does not actually call walk as it's really just a abstract class
@@ -22007,89 +22009,58 @@ Roo.htmleditor.KeyEnter.prototype = {
     
     keypress : function(e)
     {
-        if (e.charCode != 13) {
+        if (e.charCode != 13 && e.charCode != 10) {
+            Roo.log([e.charCode,e]);
             return true;
         }
         e.preventDefault();
         // https://stackoverflow.com/questions/18552336/prevent-contenteditable-adding-div-on-enter-chrome
         var doc = this.core.doc;
-        
-        var docFragment = doc.createDocumentFragment();
-    
-        //add a new line
+          //add a new line
        
     
-    
-        var range = this.core.win.getSelection().getRangeAt(0);
-        var n = range.commonAncestorContainer ;
-        while (n && n.nodeType != 1) {
-            n  = n.parentNode;
-        }
-        var li = false;
-        if (n && n.tagName == 'UL') {
-            li = doc.createElement('LI');
-            n.appendChild(li);
-            
-        }
-        if (n && n.tagName == 'LI') {
-            li = doc.createElement('LI');
-            if (n.nextSibling) {
-                n.parentNode.insertBefore(li, n.firstSibling);
-                
-            } else {
-                n.parentNode.appendChild(li);
-            }
-        }
-        if (li) {   
-            range = doc.createRange();
-            range.setStartAfter(li);
-            range.collapse(true);
-        
-            //make the cursor there
-            var sel = this.core.win.getSelection();
-            sel.removeAllRanges();
-            sel.addRange(range);
+        var sel = this.core.getSelection();
+        var range = sel.getRangeAt(0);
+        var n = range.commonAncestorContainer;
+        var pc = range.closest([ 'ol', 'ul']);
+        var pli = range.closest('li');
+        if (!pc || e.ctrlKey) {
+            sel.insertNode('br', 'after'); 
+         
             this.core.undoManager.addEvent();
+            this.core.fireEditorEvent(e);
             return false;
-            
-            
         }
-        var newEle = doc.createTextNode('\n');
-        docFragment.appendChild(newEle);
-        
-        //add the br, or p, or something else
-        newEle = doc.createElement('br');
-        //newEle.setAttribute('data-id', Roo.htmleditor.KeyEnter.i++);
-        docFragment.appendChild(newEle);
-        doc.createTextNode('\n');
-        docFragment.appendChild(newEle);
         
-        range.deleteContents();
-        range.insertNode(docFragment);  //<< inseting here...
-         
-        var ns = newEle.nextSibling;
-        while (ns && ns.nodeType == 3) { 
-            ns = ns.nextSibling;
+        // deal with <li> insetion
+        if (pli.innerText.trim() == '' &&
+            pli.previousSibling &&
+            pli.previousSibling.nodeName == 'LI' &&
+            pli.previousSibling.innerText.trim() ==  '') {
+            pli.parentNode.removeChild(pli.previousSibling);
+            sel.cursorAfter(pc);
+            this.core.undoManager.addEvent();
+            this.core.fireEditorEvent(e);
+            return false;
         }
-        
-        if (!ns) {
-            //Roo.log('add extra');
-            ns = doc.createElement('br');
-            //ns.setAttribute('data-id', 'x' +  Roo.htmleditor.KeyEnter.i++);
-            newEle.parentNode.appendChild(ns);
+    
+        var li = doc.createElement('LI');
+        li.innerHTML = '&nbsp;';
+        if (!pli || !pli.firstSibling) {
+            pc.appendChild(li);
+        } else {
+            pli.parentNode.insertBefore(li, pli.firstSibling);
         }
+        sel.cursorText (li.firstChild);
+      
+        this.core.undoManager.addEvent();
+        this.core.fireEditorEvent(e);
+
+        return false;
         
+    
         
         
-        range = doc.createRange();
-        range.setStartAfter(newEle);
-        range.collapse(true);
-        
-        var sel = this.core.win.getSelection();
-        sel.removeAllRanges();
-        sel.addRange(range);
-        //this.core.undoManager.addEvent();
-        return false;
          
     }
 };
@@ -22120,7 +22091,7 @@ Roo.htmleditor.Block.factory = function(node)
     var cc = Roo.htmleditor.Block.cache;
     var id = Roo.get(node).id;
     if (typeof(cc[id]) != 'undefined' && (!cc[id].node || cc[id].node.closest('body'))) {
-        Roo.htmleditor.Block.cache[id].readElement();
+        Roo.htmleditor.Block.cache[id].readElement(node);
         return Roo.htmleditor.Block.cache[id];
     }
     var db  = node.getAttribute('data-block');
@@ -22202,14 +22173,17 @@ Roo.htmleditor.Block.prototype = {
             // but kiss for now.
             n = node.getElementsByTagName(tag).item(0);
         }
+        if (!n) {
+            return '';
+        }
         if (attr == 'html') {
             return n.innerHTML;
         }
         if (attr == 'style') {
-            return n.style[style]
+            return n.style[style]
         }
         
-        return Roo.get(n).attr(attr);
+        return n.hasAttribute(attr) ? n.getAttribute(attr) : '';
             
     },
     /**
@@ -22240,8 +22214,8 @@ Roo.htmleditor.Block.prototype = {
  * Block that has an image and a figcaption
  * @cfg {String} image_src the url for the image
  * @cfg {String} align (left|right) alignment for the block default left
- * @cfg {String} text_align (left|right) alignment for the text caption default left.
  * @cfg {String} caption the text to appear below  (and in the alt tag)
+ * @cfg {String} caption_display (block|none) display or not the caption
  * @cfg {String|number} image_width the width of the image number or %?
  * @cfg {String|number} image_height the height of the image number or %?
  * 
@@ -22263,46 +22237,164 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
     
     // setable values.
     image_src: '',
-    
-    align: 'left',
+    align: 'center',
     caption : '',
-    text_align: 'left',
+    caption_display : 'block',
+    width : '100%',
+    
+    // margin: '2%', not used
     
-    width : '46%',
-    margin: '2%',
+    text_align: 'left', //   (left|right) alignment for the text caption default left. - not used at present
+
     
     // used by context menu
     friendly_name : 'Image with caption',
     deleteTitle : "Delete Image and Caption",
     
-    context : { // ?? static really
-        width : {
-            title: "Width",
-            width: 40
-            // ?? number
-        },
-        margin : {
-            title: "Margin",
-            width: 40
-            // ?? number
-        },
-        align: {
-            title: "Align",
-            opts : [[ "left"],[ "right"]],
-            width : 80
+    contextMenu : function(toolbar)
+    {
+        
+        var block = function() {
+            return Roo.htmleditor.Block.factory(toolbar.tb.selectedNode);
+        };
+        
+        
+        var rooui =  typeof(Roo.bootstrap) == 'undefined' ? Roo : Roo.bootstrap;
+        
+        var syncValue = toolbar.editorcore.syncValue;
+        
+        var fields = {};
+        
+        return [
+             {
+                xtype : 'TextItem',
+                text : "Source: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'TextField',
+                allowBlank : false,
+                width : 150,
+                name : 'image_src',
+                listeners : {
+                    keyup : function (combo, e)
+                    { 
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.image_src = this.getValue();
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form
+                
+            },
+            {
+                xtype : 'TextItem',
+                text : "Width: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'width',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.width = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['auto'],
+                        ['50%'],
+                        ['100%']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            {
+                xtype : 'TextItem',
+                text : "Align: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 70,
+                name : 'align',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = block();
+                        b.align = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['left'],
+                        ['right'],
+                        ['center']
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
             
-        },
-        text_align: {
-            title: "Caption Align",
-            opts : [ [ "left"],[ "right"],[ "center"]],
-            width : 80
-        },
+            
+            {
+                xtype : 'Button',
+                text: 'Hide Caption',
+                name : 'caption_display',
+                pressed : false,
+                enableToggle : true,
+                setValue : function(v) {
+                    this.toggle(v == 'block' ? false : true);
+                },
+                listeners : {
+                    toggle: function (btn, state)
+                    {
+                        var b  = block();
+                        b.caption_display = b.caption_display == 'block' ? 'none' : 'block';
+                        this.setText(b.caption_display == 'block' ? "Hide Caption" : "Show Caption");
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.Toolbar
+            }
+        ];
         
-       
-        image_src : {
-            title: "Src",
-            width: 220
-        }
     },
     /**
      * create a DomHelper friendly object - for use with
@@ -22313,48 +22405,66 @@ Roo.extend(Roo.htmleditor.BlockFigure, Roo.htmleditor.Block, {
         var d = document.createElement('div');
         d.innerHTML = this.caption;
         
-        return {
+        return  {
             tag: 'figure',
             'data-block' : 'Figure',
             contenteditable : 'false',
             style : {
-                display: 'table',
+                display: 'block',
                 float :  this.align ,
-                width :  this.width,
-                margin:  this.margin
+                'max-width':  this.width,
+                width : 'auto',
+                margin:  0,
+                padding: '10px'
+                
             },
+            align : this.align,
             cn : [
                 {
                     tag : 'img',
                     src : this.image_src,
                     alt : d.innerText.replace(/\n/g, " "), // removeHTML..
                     style: {
-                        width: '100%'
+                        width : 'auto',
+                        'max-width': '100%',
+                        margin : '0px' 
+                        
+                        
                     }
                 },
                 {
                     tag: 'figcaption',
                     contenteditable : true,
                     style : {
-                        'text-align': this.text_align
+                        'text-align': 'left',
+                        'margin-top' : '16px',
+                        'font-size' : '16px',
+                        'line-height' : '24px',
+                        'font-style': 'italic',
+                        display : this.caption_display
                     },
                     html : this.caption
                     
                 }
             ]
         };
+         
     },
     
     readElement : function(node)
     {
         this.image_src = this.getVal(node, 'img', 'src');
-        this.align = this.getVal(node, 'figure', 'style', 'float');
+        this.align = this.getVal(node, 'figure', 'align');
         this.caption = this.getVal(node, 'figcaption', 'html');
-        this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
-        this.width = this.getVal(node, 'figure', 'style', 'width');
-        this.margin = this.getVal(node, 'figure', 'style', 'margin');
+        //this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
+        this.width = this.getVal(node, 'figure', 'style', 'max-width');
+        //this.margin = this.getVal(node, 'figure', 'style', 'margin');
         
-    } 
+    },
+    removeNode : function()
+    {
+        return this.node;
+    }
     
   
    
@@ -22424,6 +22534,11 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
         var fields = {};
         
         return [
+            {
+                xtype : 'TextItem',
+                text : "Width: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
             {
                 xtype : 'ComboBox',
                 allowBlank : false,
@@ -22438,11 +22553,12 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     select : function (combo, r, index)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         var b = block();
                         b.width = r.get('val');
                         b.updateElement();
                         syncValue();
-                        
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.form,
@@ -22470,8 +22586,10 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         block().removeColumn();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -22482,8 +22600,10 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         block().addColumn();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -22501,8 +22621,10 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         block().removeRow();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -22515,6 +22637,7 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                     {
                         block().addRow();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -22529,6 +22652,7 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
                     {
                         block().resetWidths();
                         syncValue();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -22624,22 +22748,18 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
         
         this.rows = [];
         this.no_row = 0;
-        var trs = Array.from(node.getElementsByTagName('tr'));
+        var trs = Array.from(node.rows);
         trs.forEach(function(tr) {
             var row =  [];
             this.rows.push(row);
-            if (Roo.get(tr).hasClass('roo-html-editor-el')) { // ??? this is for our 'row' selection'
-                return;
-            }
+            
             this.no_row++;
             var no_column = 0;
-            Array.from(tr.getElementsByTagName('td')).forEach(function(td) {
-                if (Roo.get(td).hasClass('roo-html-editor-el')) { // ??? this is for our 'row' selection'
-                    return;
-                }
+            Array.from(tr.cells).forEach(function(td) {
+                
                 var add = {
-                    colspan : td.hasAttribute('colspan') ? td.getAttribute('colspan') : 1,
-                    rowspan : td.hasAttribute('rowspan') ? td.getAttribute('rowspan') : 1,
+                    colspan : td.hasAttribute('colspan') ? td.getAttribute('colspan')*1 : 1,
+                    rowspan : td.hasAttribute('rowspan') ? td.getAttribute('rowspan')*1 : 1,
                     style : td.hasAttribute('style') ? td.getAttribute('style') : '',
                     html : td.innerHTML
                 };
@@ -22805,7 +22925,7 @@ Roo.extend(Roo.htmleditor.BlockTable, Roo.htmleditor.Block, {
     addRow : function()
     {
         
-        row = [];
+        var row = [];
         for (var i = 0; i < this.no_col; i++ ) {
             
             row.push(this.emptyCell());
@@ -22889,6 +23009,7 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     
     width: '',
     textAlign : 'left',
+    valign : 'top',
     
     colspan : 1,
     rowspan : 1,
@@ -22896,7 +23017,7 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     
     // used by context menu
     friendly_name : 'Table Cell',
-    deleteTitle : 'Delete Table',
+    deleteTitle : false, // use our customer delete
     
     // context menu is drawn once..
     
@@ -22965,10 +23086,10 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().shrinkColumn();
                         syncValue();
-                        restoreSel();
+                         toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -22979,14 +23100,55 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().growColumn();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
             },
+            
+            {
+                xtype : 'TextItem',
+                text : "Vertical Align: ",
+                xns : rooui.Toolbar  //Boostrap?
+            },
+            {
+                xtype : 'ComboBox',
+                allowBlank : false,
+                displayField : 'val',
+                editable : true,
+                listWidth : 100,
+                triggerAction : 'all',
+                typeAhead : true,
+                valueField : 'val',
+                width : 100,
+                name : 'valign',
+                listeners : {
+                    select : function (combo, r, index)
+                    {
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        var b = cell();
+                        b.valign = r.get('val');
+                        b.updateElement();
+                        syncValue();
+                        toolbar.editorcore.onEditorEvent();
+                    }
+                },
+                xns : rooui.form,
+                store : {
+                    xtype : 'SimpleStore',
+                    data : [
+                        ['top'],
+                        ['middle'],
+                        ['bottom'] // there are afew more... 
+                    ],
+                    fields : [ 'val'],
+                    xns : Roo.data
+                }
+            },
+            
             {
                 xtype : 'TextItem',
                 text : "Merge Cells: ",
@@ -23001,11 +23163,11 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().mergeRight();
                         //block().growColumn();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -23017,11 +23179,11 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().mergeBelow();
                         //block().growColumn();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.onEditorEvent();
                     }
                 },
                 xns : rooui.Toolbar
@@ -23039,14 +23201,91 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
                 listeners : {
                     click : function (_self, e)
                     {
-                        saveSel();
+                        //toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
                         cell().split();
                         syncValue();
-                        restoreSel();
+                        toolbar.editorcore.selectNode(toolbar.tb.selectedNode);
+                        toolbar.editorcore.onEditorEvent();
+                                             
                     }
                 },
                 xns : rooui.Toolbar
+            },
+            {
+                xtype : 'Fill',
+                xns : rooui.Toolbar 
+               
+            },
+        
+          
+            {
+                xtype : 'Button',
+                text: 'Delete',
+                 
+                xns : rooui.Toolbar,
+                menu : {
+                    xtype : 'Menu',
+                    xns : rooui.menu,
+                    items : [
+                        {
+                            xtype : 'Item',
+                            html: 'Column',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    
+                                    cell().deleteColumn();
+                                    syncValue();
+                                    toolbar.editorcore.selectNode(t.node);
+                                    toolbar.editorcore.onEditorEvent();   
+                                }
+                            },
+                            xns : rooui.menu
+                        },
+                        {
+                            xtype : 'Item',
+                            html: 'Row',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    cell().deleteRow();
+                                    syncValue();
+                                    
+                                    toolbar.editorcore.selectNode(t.node);
+                                    toolbar.editorcore.onEditorEvent();   
+                                                         
+                                }
+                            },
+                            xns : rooui.menu
+                        },
+                       {
+                            xtype : 'Separator',
+                            xns : rooui.menu
+                        },
+                        {
+                            xtype : 'Item',
+                            html: 'Table',
+                            listeners : {
+                                click : function (_self, e)
+                                {
+                                    var t = table();
+                                    var nn = t.node.nextSibling || t.node.previousSibling;
+                                    t.node.parentNode.removeChild(t.node);
+                                    if (nn) { 
+                                        toolbar.editorcore.selectNode(nn, true);
+                                    }
+                                    toolbar.editorcore.onEditorEvent();   
+                                                         
+                                }
+                            },
+                            xns : rooui.menu
+                        }
+                    ]
+                }
             }
+            
             // align... << fixme
             
         ];
@@ -23071,21 +23310,27 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
             tag : 'td',
             contenteditable : 'true', // this stops cell selection from picking the table.
             'data-block' : 'Td',
-            width:  this.width,
+            valign : this.valign,
             style : {  
-                width:  this.width,
                 'text-align' :  this.textAlign,
                 border : 'solid 1px rgb(0, 0, 0)', // ??? hard coded?
-                'border-collapse' : 'collapse' 
+                'border-collapse' : 'collapse',
+                padding : '6px', // 8 for desktop / 4 for mobile
+                'vertical-align': this.valign
             },
             html : this.html
         };
+        if (this.width != '') {
+            ret.width = this.width;
+            ret.style.width = this.width;
+        }
+        
         
         if (this.colspan > 1) {
-            ret.colspan = cell.colspan ;
+            ret.colspan = this.colspan ;
         } 
-        if (ret.rowspan > 1) {
-            this.rowspan = cell.rowspan ;
+        if (this.rowspan > 1) {
+            ret.rowspan = this.rowspan ;
         }
         
            
@@ -23098,7 +23343,8 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     {
         node  = node ? node : this.node ;
         this.width = node.style.width;
-        
+        this.colspan = Math.max(1,1*node.getAttribute('colspan'));
+        this.rowspan = Math.max(1,1*node.getAttribute('rowspan'));
         this.html = node.innerHTML;
         
         
@@ -23118,8 +23364,7 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
     removeNode : function()
     {
         return this.node.closest('table');
-        
-        
+         
     },
     
     cellData : false,
@@ -23292,13 +23537,19 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         
          
         var tab = this.node.closest('tr').closest('table');
+        var ctr = tab.rows[0].parentNode;
         Array.from(tab.rows).forEach(function(r, ri){
+            
             Array.from(r.cells).forEach(function(ce, ci){
                 ce.parentNode.removeChild(ce);
             });
+            r.parentNode.removeChild(r);
         });
         for(var r = 0 ; r < table.length; r++) {
             var re = tab.rows[r];
+            
+            var re = tab.ownerDocument.createElement('tr');
+            ctr.appendChild(re);
             for(var c = 0 ; c < table[r].length; c++) {
                 if (table[r][c].cell === false) {
                     continue;
@@ -23414,9 +23665,52 @@ Roo.extend(Roo.htmleditor.BlockTd, Roo.htmleditor.Block, {
         }, this);
         this.updateWidths(table);
          
+    },
+    deleteRow : function()
+    {
+        // delete this rows 'tr'
+        // if any of the cells in this row have a rowspan > 1 && row!= this row..
+        // then reduce the rowspan.
+        var table = this.toTableArray();
+        // this.cellData.row;
+        for (var i =0;i< table[this.cellData.row].length ; i++) {
+            var c = table[this.cellData.row][i];
+            if (c.row != this.cellData.row) {
+                
+                c.rowspan--;
+                c.cell.setAttribute('rowspan', c.rowspan);
+                continue;
+            }
+            if (c.rowspan > 1) {
+                c.rowspan--;
+                c.cell.setAttribute('rowspan', c.rowspan);
+            }
+        }
+        table.splice(this.cellData.row,1);
+        this.redrawAllCells(table);
+        
+    },
+    deleteColumn : function()
+    {
+        var table = this.toTableArray();
+        
+        for (var i =0;i< table.length ; i++) {
+            var c = table[i][this.cellData.col];
+            if (c.col != this.cellData.col) {
+                table[i][this.cellData.col].colspan--;
+            } else if (c.colspan > 1) {
+                c.colspan--;
+                c.cell.setAttribute('colspan', c.colspan);
+            }
+            table[i].splice(this.cellData.col,1);
+        }
+        
+        this.redrawAllCells(table);
     }
     
     
+    
+    
 })
 
 //<script type="text/javascript">
@@ -23492,7 +23786,8 @@ Roo.HtmlEditorCore = function(config){
          * Fires when on any editor (mouse up/down cursor movement etc.) - used for toolbar hooks.
          * @param {Roo.HtmlEditorCore} this
          */
-        editorevent: true
+        editorevent: true 
+         
         
     });
     
@@ -23528,7 +23823,16 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
      * @cfg {Number} width (in pixels)
      */   
     width: 500,
+     /**
+     * @cfg {boolean} autoClean - default true - loading and saving will remove quite a bit of formating,
+     *         if you are doing an email editor, this probably needs disabling, it's designed
+     */
+    autoClean: true,
     
+    /**
+     * @cfg {boolean} enableBlocks - default true - if the block editor (table and figure should be enabled)
+     */
+    enableBlocks : true,
     /**
      * @cfg {Array} stylesheets url of stylesheets. set to [] to disable stylesheets.
      * 
@@ -23536,7 +23840,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     stylesheets: false,
     
     /**
-     * @cfg {boolean} allowComments - default false - allow comments in HTML source - by default they are stripped - if you are editing email you may need this.
+     * @cfg {boolean} allowComments - default false - allow comments in HTML source
+     *          - by default they are stripped - if you are editing email you may need this.
      */
     allowComments: false,
     // id of frame..
@@ -23761,26 +24066,18 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
             
             var bd = (this.doc.body || this.doc.documentElement);
-            //this.cleanUpPaste(); -- this is done else where and causes havoc..
-            
-            // not sure if this is really the place for this
-            // the blocks are synced occasionaly - since we currently dont add listeners on the blocks
-            // this has to update attributes that get duped.. like alt and caption..
-            
-            
-            //Roo.each(Roo.get(this.doc.body).query('*[data-block]'), function(e) {
-            //     Roo.htmleditor.Block.factory(e);
-            //},this);
+           
             
             
             var div = document.createElement('div');
             div.innerHTML = bd.innerHTML;
-            // remove content editable. (blocks)
-            
+             
            
-            
+            if (this.enableBlocks) {
+                new Roo.htmleditor.FilterBlock({ node : div });
+            }
             //?? tidy?
-            new Roo.htmleditor.FilterBlock({ node : div });
+            
             
             var html = div.innerHTML;
             if(Roo.isSafari){
@@ -23845,6 +24142,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 this.el.dom.value = d.innerHTML;
                 this.owner.fireEvent('push', this, v);
             }
+            if (this.autoClean) {
+                new Roo.htmleditor.FilterParagraph({node : this.doc.body}); // paragraphs
+                new Roo.htmleditor.FilterSpan({node : this.doc.body}); // empty spans
+            }
+            
             Roo.htmleditor.Block.initAll(this.doc.body);
             
             var lc = this.doc.body.lastChild;
@@ -23933,6 +24235,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         if(Roo.isGecko){
             Roo.EventManager.on(this.doc, 'keypress', this.mozKeyPress, this);
         }
+        //??? needed???
         if(Roo.isIE || Roo.isSafari || Roo.isOpera){
             Roo.EventManager.on(this.doc, 'keydown', this.fixKeys, this);
         }
@@ -23999,25 +24302,39 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                 img.setAttribute('src', images[i]);
             });
         }
-        
-      
-        new Roo.htmleditor.FilterStyleToTag({ node : d });
-        new Roo.htmleditor.FilterAttributes({
-            node : d,
-            attrib_white : ['href', 'src', 'name', 'align'],
-            attrib_clean : ['href', 'src' ] 
-        });
-        new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
-        // should be fonts..
-        new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT' ]} );
-        new Roo.htmleditor.FilterParagraph({ node : d });
-        new Roo.htmleditor.FilterSpan({ node : d });
-        new Roo.htmleditor.FilterLongBr({ node : d });
-        
+        if (this.autoClean) {
+            new Roo.htmleditor.FilterStyleToTag({ node : d });
+            new Roo.htmleditor.FilterAttributes({
+                node : d,
+                attrib_white : ['href', 'src', 'name', 'align'],
+                attrib_clean : ['href', 'src' ] 
+            });
+            new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
+            // should be fonts..
+            new Roo.htmleditor.FilterKeepChildren({node : d, tag : [ 'FONT' ]} );
+            new Roo.htmleditor.FilterParagraph({ node : d });
+            new Roo.htmleditor.FilterSpan({ node : d });
+            new Roo.htmleditor.FilterLongBr({ node : d });
+        }
+        if (this.enableBlocks) {
+                
+            Array.from(d.getElementsByTagName('img')).forEach(function(img) {
+                if (img.closest('figure')) { // assume!! that it's aready
+                    return;
+                }
+                var fig  = new Roo.htmleditor.BlockFigure({
+                    image_src  : img.src
+                });
+                fig.updateElement(img); // replace it..
+                
+            });
+        }
         
         
-        this.insertAtCursor(d.innerHTML);
-        Roo.htmleditor.Block.initAll(this.doc.body);
+        this.insertAtCursor(d.innerHTML.replace(/&nbsp;/g,' '));
+        if (this.enableBlocks) {
+            Roo.htmleditor.Block.initAll(this.doc.body);
+        }
         
         
         e.preventDefault();
@@ -24104,7 +24421,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
             this.doc.body.lastChild
            ) {
             var lc = this.doc.body.lastChild;
-            while (lc.nodeType == 3 && lc.nodeValue == '') {
+            // gtx-trans is google translate plugin adding crap.
+            while ((lc.nodeType == 3 && lc.nodeValue == '') || lc.id == 'gtx-trans') {
                 lc = lc.previousSibling;
             }
             if (lc.nodeType == 1 && lc.nodeName != 'BR') {
@@ -24123,10 +24441,15 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         
         
-        this.owner.fireEvent('editorevent', this, e);
+        this.fireEditorEvent(e);
       //  this.updateToolbar();
         this.syncValue(); //we can not sync so often.. sync cleans, so this breaks stuff
     },
+    
+    fireEditorEvent: function(e)
+    {
+        this.owner.fireEvent('editorevent', this, e);
+    },
 
     insertTag : function(tg)
     {
@@ -24171,7 +24494,37 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
      * @param {String} cmd The Midas command
      * @param {String/Boolean} value (optional) The value to pass to the command (defaults to null)
      */
-    relayCmd : function(cmd, value){
+    relayCmd : function(cmd, value)
+    {
+        
+        switch (cmd) {
+            case 'justifyleft':
+            case 'justifyright':
+            case 'justifycenter':
+                // if we are in a cell, then we will adjust the
+                var n = this.getParentElement();
+                var td = n.closest('td');
+                if (td) {
+                    var bl = Roo.htmleditor.Block.factory(td);
+                    bl.textAlign = cmd.replace('justify','');
+                    bl.updateElement();
+                    this.owner.fireEvent('editorevent', this);
+                    return;
+                }
+                this.execCmd('styleWithCSS', true); // 
+                break;
+            case 'bold':
+            case 'italic':
+                // if there is no selection, then we insert, and set the curson inside it..
+                this.execCmd('styleWithCSS', false); 
+                break;
+                
+        
+            default:
+                break;
+        }
+        
+        
         this.win.focus();
         this.execCmd(cmd, value);
         this.owner.fireEvent('editorevent', this);
@@ -24269,9 +24622,11 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                         
                 }
                 if(cmd){
-                    this.win.focus();
-                    this.execCmd(cmd);
-                    this.deferFocus();
+                    
+                    this.relayCmd(cmd);
+                    //this.win.focus();
+                    //this.execCmd(cmd);
+                    //this.deferFocus();
                     e.preventDefault();
                 }
                 
@@ -24281,6 +24636,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
 
     // private
     fixKeys : function(){ // load time branching for fastest keydown performance
+        
+        
         if(Roo.isIE){
             return function(e){
                 var k = e.getKey(), r;
@@ -24325,6 +24682,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                     this.execCmd('InsertHTML','&#160;&#160;&#160;&#160;');
                     this.deferFocus();
                 }
+               
                 //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
                 //    this.cleanUpPaste.defer(100, this);
                  //   return;
@@ -24341,6 +24699,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
                     this.deferFocus();
                     return;
                 }
+                 this.mozKeyPress(e);
+                
                //if (String.fromCharCode(k).toLowerCase() == 'v') { // paste
                  //   this.cleanUpPaste.defer(100, this);
                  //   return;
@@ -24374,13 +24734,13 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
     getSelection : function() 
     {
         this.assignDocWin();
-        return Roo.isIE ? this.doc.selection : this.win.getSelection();
+        return Roo.lib.Selection.wrap(Roo.isIE ? this.doc.selection : this.win.getSelection(), this.doc);
     },
     /**
      * Select a dom node
      * @param {DomElement} node the node to select
      */
-    selectNode : function(node)
+    selectNode : function(node, collapse)
     {
         var nodeRange = node.ownerDocument.createRange();
         try {
@@ -24388,7 +24748,10 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         } catch (e) {
             nodeRange.selectNodeContents(node);
         }
-        //nodeRange.collapse(true);
+        if (collapse === true) {
+            nodeRange.collapse(true);
+        }
+        //
         var s = this.win.getSelection();
         s.removeAllRanges();
         s.addRange(nodeRange);
@@ -24400,8 +24763,7 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         // should we cache this!!!!
         
-        
-        
+         
          
         var range = this.createRange(this.getSelection()).cloneRange();
         
@@ -24465,6 +24827,8 @@ Roo.extend(Roo.HtmlEditorCore, Roo.Component,  {
         
         return nodes[0];
     },
+    
+    
     createRange: function(sel)
     {
         // this has strange effects when using with 
@@ -24998,11 +25362,19 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
      */
     allowComments: false,
     /**
-     * @cfg {string} bodyCls- default '' default classes to add to body of editable area - usually undoreset is a good start..
+     * @cfg {boolean} enableBlocks - default true - if the block editor (table and figure should be enabled)
      */
+    enableBlocks : true,
     
-    
-     bodyCls : '',
+    /**
+     * @cfg {boolean} autoClean - default true - loading and saving will remove quite a bit of formating,
+     *         if you are doing an email editor, this probably needs disabling, it's designed
+     */
+    autoClean: true,
+    /**
+     * @cfg {string} bodyCls- default '' default classes to add to body of editable area - usually undoreset is a good start..
+     */
+    bodyCls : '',
     
     // id of frame..
     frameId: false,
@@ -25145,8 +25517,19 @@ Roo.extend(Roo.form.HtmlEditor, Roo.form.Field, {
          
         
     },
-
-     
+    /**
+     * get the Context selected node
+     * @returns {DomElement|boolean} selected node if active or false if none
+     * 
+     */
+    getSelectedNode : function()
+    {
+        if (this.toolbars.length < 2 || !this.toolbars[1].tb) {
+            return false;
+        }
+        return this.toolbars[1].tb.selectedNode;
+    
+    },
     // private
     onRender : function(ct, position)
     {
@@ -26581,9 +26964,9 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         // disable everything...
         var ty= Roo.form.HtmlEditor.ToolbarContext.types;
         this.toolbars = {};
-           
+        // block toolbars are built in updateToolbar when needed.
         for (var i in  ty) {
-          
+            
             this.toolbars[i] = this.buildToolbar(ty[i],i);
         }
         this.tb = this.toolbars.BODY;
@@ -26642,8 +27025,13 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
             // this triggers looping?
             //this.editorcore.selectNode(sel);
              
-        }  
-        Roo.select('.roo-ed-selection', false, this.editorcore.doc).removeClass('roo-ed-selection');
+        }
+        
+        // this forces an id..
+        Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e) {
+             e.classList.remove('roo-ed-selection');
+        });
+        //Roo.select('.roo-ed-selection', false, this.editorcore.doc).removeClass('roo-ed-selection');
         //Roo.get(node).addClass('roo-ed-selection');
       
         //var updateFooter = sel ? false : true; 
@@ -26672,24 +27060,28 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         // you are not actually selecting the block.
         if (sel && sel.hasAttribute('data-block')) {
             db = sel;
-        } else if (sel && !sel.hasAttribute('contenteditable')) {
-            var sel_el = Roo.get(sel);
-            db = sel_el.findParent('[data-block]');
-            var cepar = sel_el.findParent('[contenteditable=true]');
-            if (db && cepar && cepar.tagName != 'BODY') {
-               db = false; // we are inside an editable block.. = not sure how we are going to handle nested blocks!?
-            }   
+        } else if (sel && sel.closest('[data-block]')) {
+            
+            db = sel.closest('[data-block]');
+            //var cepar = sel.closest('[contenteditable=true]');
+            //if (db && cepar && cepar.tagName != 'BODY') {
+            //   db = false; // we are inside an editable block.. = not sure how we are going to handle nested blocks!?
+            //}   
         }
         
         
         var block = false;
         //if (db && !sel.hasAttribute('contenteditable') && sel.getAttribute('contenteditable') != 'true' ) {
-        if (db) {
+        if (db && this.editorcore.enableBlocks) {
             block = Roo.htmleditor.Block.factory(db);
             
             
             if (block) {
-                db.className +=  ' roo-ed-selection'; // since we removed it earlier... its not there..
+                 db.className = (
+                        db.classList.length > 0  ? db.className + ' ' : ''
+                    )  + 'roo-ed-selection';
+                 
+                 // since we removed it earlier... its not there..
                 tn = 'BLOCK.' + db.getAttribute('data-block');
                 
                 //this.editorcore.selectNode(db);
@@ -26944,13 +27336,7 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
                     width: item.width ? item.width  : 130,
                     listeners : {
                         'select': function(c, r, i) {
-                            if (tb.selectedNode.hasAttribute('data-block')) {
-                                var b = Roo.htmleditor.Block.factory(tb.selectedNode);
-                                b[c.attrname] = r.get('val');
-                                b.updateElement(tb.selectedNode);
-                                editorcore.syncValue();
-                                return;
-                            }
+                             
                             
                             if (c.stylename) {
                                 tb.selectedNode.style[c.stylename] =  r.get('val');
@@ -26991,14 +27377,7 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
                 listeners: {
                     'change' : function(f, nv, ov) {
                         
-                        if (tb.selectedNode.hasAttribute('data-block')) {
-                            var b = Roo.htmleditor.Block.factory(tb.selectedNode);
-                            b[f.attrname] = nv;
-                            b.updateElement(tb.selectedNode);
-                            editorcore.syncValue();
-                            return;
-                        }
-                        
+                         
                         tb.selectedNode.setAttribute(f.attrname, nv);
                         editorcore.syncValue();
                     }
@@ -27008,8 +27387,9 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         }
         
         var _this = this;
-        
+        var show_delete = !block || block.deleteTitle !== false;
         if(nm == 'BODY'){
+            show_delete = false;
             tb.addSeparator();
         
             tb.addButton( {
@@ -27025,53 +27405,54 @@ Roo.apply(Roo.form.HtmlEditor.ToolbarContext.prototype,  {
         }
         
         tb.addFill();
-        tb.addButton({
-            text: block && block.deleteTitle ? block.deleteTitle  : 'Remove Block or Formating', // remove the tag, and puts the children outside...
-    
-            listeners : {
-                click : function ()
-                {
-                    var sn = tb.selectedNode;
-                    if (block) {
-                        sn = Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();
+        if (show_delete) {
+            tb.addButton({
+                text: block && block.deleteTitle ? block.deleteTitle  : 'Remove Block or Formating', // remove the tag, and puts the children outside...
+        
+                listeners : {
+                    click : function ()
+                    {
+                        var sn = tb.selectedNode;
+                        if (block) {
+                            sn = Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();
+                            
+                        }
+                        if (!sn) {
+                            return;
+                        }
+                        var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
+                        if (sn.hasAttribute('data-block')) {
+                            stn =  sn.nextSibling || sn.previousSibling || sn.parentNode;
+                            sn.parentNode.removeChild(sn);
+                            
+                        } else if (sn && sn.tagName != 'BODY') {
+                            // remove and keep parents.
+                            a = new Roo.htmleditor.FilterKeepChildren({tag : false});
+                            a.replaceTag(sn);
+                        }
                         
-                    }
-                    if (!sn) {
-                        return;
-                    }
-                    var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
-                    if (sn.hasAttribute('data-block')) {
-                        stn =  sn.nextSibling || sn.previousSibling || sn.parentNode;
-                        sn.parentNode.removeChild(sn);
                         
-                    } else if (sn && sn.tagName != 'BODY') {
-                        // remove and keep parents.
-                        a = new Roo.htmleditor.FilterKeepChildren({tag : false});
-                        a.removeTag(sn);
+                        var range = editorcore.createRange();
+            
+                        range.setStart(stn,0);
+                        range.setEnd(stn,0); 
+                        var selection = editorcore.getSelection();
+                        selection.removeAllRanges();
+                        selection.addRange(range);
+                        
+                        
+                        //_this.updateToolbar(null, null, pn);
+                        _this.updateToolbar(null, null, null);
+                        _this.updateFooter(false);
+                        
                     }
-                    
-                    
-                    var range = editorcore.createRange();
-        
-                    range.setStart(stn,0);
-                    range.setEnd(stn,0); 
-                    var selection = editorcore.getSelection();
-                    selection.removeAllRanges();
-                    selection.addRange(range);
-                    
-                    
-                    //_this.updateToolbar(null, null, pn);
-                    _this.updateToolbar(null, null, null);
-                    _this.updateFooter(false);
-                    
                 }
-            }
-            
+                
+                        
                     
                 
-            
-        });
-        
+            });
+        }    
         
         tb.el.on('click', function(e){
             e.preventDefault(); // what does this do?
index 112ccdd..0370500 100644 (file)
@@ -985,7 +985,7 @@ if(!C.length){A.removeAttribute("class");}}if(A.hasAttribute("lang")){A.removeAt
 }E.push(s);});A.setAttribute("style",E.length?E.join(';'):'');if(!E.length){A.removeAttribute('style');}}return true;}});
 // 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);
+}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);
 nn.appendChild(nc);nn=nc;});for(var i=0;i<cn.length;cn++){A.removeChild(cn[i]);nn.appendChild(cn[i]);}return true}})
 // Roo/htmleditor/FilterLongBr.js
 Roo.htmleditor.FilterLongBr=function(A){this.walk(A.node);};Roo.extend(Roo.htmleditor.FilterLongBr,Roo.htmleditor.Filter,{tag:'BR',replaceTag:function(A){var ps=A.nextSibling;while(ps&&ps.nodeType==3&&ps.nodeValue.trim().length<1){ps=ps.nextSibling;}if(!ps&&['TD','TH','LI','H1','H2','H3','H4','H5','H6'].indexOf(A.parentNode.tagName)>-1){A.parentNode.removeChild(A);
@@ -1001,69 +1001,82 @@ Roo.htmleditor.Tidy=function(A){Roo.apply(this,A);this.core.doc.body.innerHTML=t
 }C.push(" ");}if(B!==false&&ar[i].nodeType==1){C.push("\n"+B);}C.push(this.tidy(ar[i],B));if(B!==false&&ar[i].nodeType==3&&ar[i].nodeValue.length>0&&ar[i].nodeValue.match(/\s+$/)){C.push("\n"+B);}}return C.join('');},attr:function(A){var B=[];for(i=0;i<A.attributes.length;
 i++){if(!A.attributes.item(i).value.length){continue;}B.push(A.attributes.item(i).name+'="'+Roo.util.Format.htmlEncode(A.attributes.item(i).value)+'"');}return B.length?(' '+B.join(' ')):'';}}
 // Roo/htmleditor/KeyEnter.js
-Roo.htmleditor.KeyEnter=function(A){Roo.apply(this,A);Roo.get(this.core.doc.body).on('keypress',this.keypress,this);};Roo.htmleditor.KeyEnter.prototype={core:false,keypress:function(e){if(e.charCode!=13){return true;}e.preventDefault();var A=this.core.doc;
-var B=A.createDocumentFragment();var C=this.core.win.getSelection().getRangeAt(0);var n=C.commonAncestorContainer;while(n&&n.nodeType!=1){n=n.parentNode;}var li=false;if(n&&n.tagName=='UL'){li=A.createElement('LI');n.appendChild(li);}if(n&&n.tagName=='LI'){li=A.createElement('LI');
-if(n.nextSibling){n.parentNode.insertBefore(li,n.firstSibling);}else{n.parentNode.appendChild(li);}}if(li){C=A.createRange();C.setStartAfter(li);C.collapse(true);var D=this.core.win.getSelection();D.removeAllRanges();D.addRange(C);this.core.undoManager.addEvent();
-return false;}var E=A.createTextNode('\n');B.appendChild(E);E=A.createElement('br');B.appendChild(E);A.createTextNode('\n');B.appendChild(E);C.deleteContents();C.insertNode(B);var ns=E.nextSibling;while(ns&&ns.nodeType==3){ns=ns.nextSibling;}if(!ns){ns=A.createElement('br');
-E.parentNode.appendChild(ns);}C=A.createRange();C.setStartAfter(E);C.collapse(true);var D=this.core.win.getSelection();D.removeAllRanges();D.addRange(C);return false;}};
+Roo.htmleditor.KeyEnter=function(A){Roo.apply(this,A);Roo.get(this.core.doc.body).on('keypress',this.keypress,this);};Roo.htmleditor.KeyEnter.prototype={core:false,keypress:function(e){if(e.charCode!=13&&e.charCode!=10){Roo.log([e.charCode,e]);return true;
+}e.preventDefault();var A=this.core.doc;var B=this.core.getSelection();var C=B.getRangeAt(0);var n=C.commonAncestorContainer;var pc=C.closest(['ol','ul']);var D=C.closest('li');if(!pc||e.ctrlKey){B.insertNode('br','after');this.core.undoManager.addEvent();
+this.core.fireEditorEvent(e);return false;}if(D.innerText.trim()==''&&D.previousSibling&&D.previousSibling.nodeName=='LI'&&D.previousSibling.innerText.trim()==''){D.parentNode.removeChild(D.previousSibling);B.cursorAfter(pc);this.core.undoManager.addEvent();
+this.core.fireEditorEvent(e);return false;}var li=A.createElement('LI');li.innerHTML='&nbsp;';if(!D||!D.firstSibling){pc.appendChild(li);}else{D.parentNode.insertBefore(li,D.firstSibling);}B.cursorText(li.firstChild);this.core.undoManager.addEvent();this.core.fireEditorEvent(e);
+return false;}};
 // Roo/htmleditor/Block.js
-Roo.htmleditor.Block=function(A){};Roo.htmleditor.Block.factory=function(A){var cc=Roo.htmleditor.Block.cache;var id=Roo.get(A).id;if(typeof(cc[id])!='undefined'&&(!cc[id].node||cc[id].node.closest('body'))){Roo.htmleditor.Block.cache[id].readElement();return Roo.htmleditor.Block.cache[id];
+Roo.htmleditor.Block=function(A){};Roo.htmleditor.Block.factory=function(A){var cc=Roo.htmleditor.Block.cache;var id=Roo.get(A).id;if(typeof(cc[id])!='undefined'&&(!cc[id].node||cc[id].node.closest('body'))){Roo.htmleditor.Block.cache[id].readElement(A);return Roo.htmleditor.Block.cache[id];
 }var db=A.getAttribute('data-block');if(!db){db=A.nodeName.toLowerCase().toUpperCaseFirst();}var B=Roo.htmleditor['Block'+db];if(typeof(B)=='undefined'){Roo.log("OOps missing block : "+'Block'+db);return false;}Roo.htmleditor.Block.cache[id]=new B({node:A}
 );return Roo.htmleditor.Block.cache[id];};Roo.htmleditor.Block.initAll=function(A,B){if(typeof(B)=='undefined'){var ia=Roo.htmleditor.Block.initAll;ia(A,'table');ia(A,'td');ia(A,'figure');return;}Roo.each(Roo.get(A).query(B),function(e){Roo.htmleditor.Block.factory(e);
 },this);};Roo.htmleditor.Block.cache={};Roo.htmleditor.Block.prototype={node:false,friendly_name:'Based Block',deleteTitle:false,context:false,updateElement:function(A){Roo.DomHelper.update(A===undefined?this.node:A,this.toObject());},toHTML:function(){return Roo.DomHelper.markup(this.toObject());
-},getVal:function(A,B,C,D){var n=A;if(B!==true&&n.tagName!=B.toUpperCase()){n=A.getElementsByTagName(B).item(0);}if(C=='html'){return n.innerHTML;}if(C=='style'){return n.style[D]}return Roo.get(n).attr(C);},toObject:function(){return {};},readElement:function(A){}
-};
+},getVal:function(A,B,C,D){var n=A;if(B!==true&&n.tagName!=B.toUpperCase()){n=A.getElementsByTagName(B).item(0);}if(!n){return '';}if(C=='html'){return n.innerHTML;}if(C=='style'){return n.style[D];}return n.hasAttribute(C)?n.getAttribute(C):'';},toObject:function(){return {}
+;},readElement:function(A){}};
 // Roo/htmleditor/BlockFigure.js
-Roo.htmleditor.BlockFigure=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockFigure,Roo.htmleditor.Block,{image_src:'',align:'left',caption:'',text_align:'left',width:'46%',margin:'2%',friendly_name:'Image with caption',deleteTitle:"Delete Image and Caption",context:{width:{title:"Width",width:40}
-,margin:{title:"Margin",width:40},align:{title:"Align",opts:[["left"],["right"]],width:80},text_align:{title:"Caption Align",opts:[["left"],["right"],["center"]],width:80},image_src:{title:"Src",width:220}},toObject:function(){var d=document.createElement('div');
-d.innerHTML=this.caption;return {tag:'figure','data-block':'Figure',contenteditable:'false',style:{display:'table',float:this.align,width:this.width,margin:this.margin},cn:[{tag:'img',src:this.image_src,alt:d.innerText.replace(/\n/g," "),style:{width:'100%'}
-},{tag:'figcaption',contenteditable:true,style:{'text-align':this.text_align},html:this.caption}]};},readElement:function(A){this.image_src=this.getVal(A,'img','src');this.align=this.getVal(A,'figure','style','float');this.caption=this.getVal(A,'figcaption','html');
-this.text_align=this.getVal(A,'figcaption','style','text-align');this.width=this.getVal(A,'figure','style','width');this.margin=this.getVal(A,'figure','style','margin');}})
+Roo.htmleditor.BlockFigure=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockFigure,Roo.htmleditor.Block,{image_src:'',align:'center',caption:'',caption_display:'block',width:'100%',text_align:'left',friendly_name:'Image with caption',deleteTitle:"Delete Image and Caption",contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);
+};var C=typeof(Roo.bootstrap)=='undefined'?Roo:Roo.bootstrap;var D=A.editorcore.syncValue;var E={};return [{xtype:'TextItem',text:"Source: ",xns:C.Toolbar},{xtype:'TextField',allowBlank:false,width:150,name:'image_src',listeners:{keyup:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.image_src=this.getValue();b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form},{xtype:'TextItem',text:"Width: ",xns:C.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:70,name:'width',listeners:{select:function(F,r,G){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.width=r.get('val');b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form,store:{xtype:'SimpleStore',data:[['auto'],['50%'],['100%']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Align: ",xns:C.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:70,name:'align',listeners:{select:function(F,r,G){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.align=r.get('val');b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form,store:{xtype:'SimpleStore',data:[['left'],['right'],['center']],fields:['val'],xns:Roo.data}},{xtype:'Button',text:'Hide Caption',name:'caption_display',pressed:false,enableToggle:true,setValue:function(v){this.toggle(v=='block'?false:true);
+},listeners:{toggle:function(F,G){var b=B();b.caption_display=b.caption_display=='block'?'none':'block';this.setText(b.caption_display=='block'?"Hide Caption":"Show Caption");b.updateElement();D();A.editorcore.selectNode(A.tb.selectedNode);A.editorcore.onEditorEvent();
+}},xns:C.Toolbar}];},toObject:function(){var d=document.createElement('div');d.innerHTML=this.caption;return {tag:'figure','data-block':'Figure',contenteditable:'false',style:{display:'block',float:this.align,'max-width':this.width,width:'auto',margin:0,padding:'10px'}
+,align:this.align,cn:[{tag:'img',src:this.image_src,alt:d.innerText.replace(/\n/g," "),style:{width:'auto','max-width':'100%',margin:'0px'}},{tag:'figcaption',contenteditable:true,style:{'text-align':'left','margin-top':'16px','font-size':'16px','line-height':'24px','font-style':'italic',display:this.caption_display}
+,html:this.caption}]};},readElement:function(A){this.image_src=this.getVal(A,'img','src');this.align=this.getVal(A,'figure','align');this.caption=this.getVal(A,'figcaption','html');this.width=this.getVal(A,'figure','style','max-width');},removeNode:function(){return this.node;
+}})
 // Roo/htmleditor/BlockTable.js
 Roo.htmleditor.BlockTable=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);if(!A.node){this.rows=[];for(var r=0;r<this.no_row;r++){this.rows[r]=[];for(var c=0;c<this.no_col;c++){this.rows[r][c]=this.emptyCell();
 }}}};Roo.extend(Roo.htmleditor.BlockTable,Roo.htmleditor.Block,{rows:false,no_col:1,no_row:1,width:'100%',friendly_name:'Table',deleteTitle:'Delete Table',contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);};var C=typeof(Roo.bootstrap)=='undefined'?Roo:Roo.bootstrap;
-var D=A.editorcore.syncValue;var E={};return [{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:100,name:'width',listeners:{select:function(F,r,G){var b=B();b.width=r.get('val');
-b.updateElement();D();}},xns:C.form,store:{xtype:'SimpleStore',data:[['100%'],['auto']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Columns: ",xns:C.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(F,e){B().removeColumn();D();}},xns:C.Toolbar}
-,{xtype:'Button',text:'+',listeners:{click:function(F,e){B().addColumn();D();}},xns:C.Toolbar},{xtype:'TextItem',text:"Rows: ",xns:C.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(F,e){B().removeRow();D();}},xns:C.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(F,e){B().addRow();
-D();}},xns:C.Toolbar},{xtype:'Button',text:'Reset Column Widths',listeners:{click:function(F,e){B().resetWidths();D();}},xns:C.Toolbar}];},toObject:function(){var A={tag:'table',contenteditable:'false','data-block':'Table',style:{width:this.width,border:'solid 1px #000','border-collapse':'collapse'}
+var D=A.editorcore.syncValue;var E={};return [{xtype:'TextItem',text:"Width: ",xns:C.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:100,name:'width',listeners:{select:function(F,r,G){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.width=r.get('val');b.updateElement();D();A.editorcore.onEditorEvent();}},xns:C.form,store:{xtype:'SimpleStore',data:[['100%'],['auto']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Columns: ",xns:C.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);
+B().removeColumn();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);B().addColumn();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar},{xtype:'TextItem',text:"Rows: ",xns:C.Toolbar}
+,{xtype:'Button',text:'-',listeners:{click:function(F,e){A.editorcore.selectNode(A.tb.selectedNode);B().removeRow();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(F,e){B().addRow();D();A.editorcore.onEditorEvent();
+}},xns:C.Toolbar},{xtype:'Button',text:'Reset Column Widths',listeners:{click:function(F,e){B().resetWidths();D();A.editorcore.onEditorEvent();}},xns:C.Toolbar}];},toObject:function(){var A={tag:'table',contenteditable:'false','data-block':'Table',style:{width:this.width,border:'solid 1px #000','border-collapse':'collapse'}
 ,cn:[{tag:'tbody',cn:[]}]};var B=0;Roo.each(this.rows,function(C){var tr={tag:'tr',style:{margin:'6px',border:'solid 1px #000',textAlign:'left'},cn:[]};A.cn[0].cn.push(tr);var nc=0;Roo.each(C,function(D){var td={tag:'td',contenteditable:'true','data-block':'Td',html:D.html,style:D.style}
 ;if(D.colspan>1){td.colspan=D.colspan;nc+=D.colspan;}else{nc++;}if(D.rowspan>1){td.rowspan=D.rowspan;}tr.cn.push(td);},this);B=Math.max(nc,B);},this);B++;return A;},readElement:function(A){A=A?A:this.node;this.width=this.getVal(A,true,'style','width')||'100%';
-this.rows=[];this.no_row=0;var B=Array.from(A.getElementsByTagName('tr'));B.forEach(function(tr){var C=[];this.rows.push(C);if(Roo.get(tr).hasClass('roo-html-editor-el')){return;}this.no_row++;var D=0;Array.from(tr.getElementsByTagName('td')).forEach(function(td){if(Roo.get(td).hasClass('roo-html-editor-el')){return;
-}var E={colspan:td.hasAttribute('colspan')?td.getAttribute('colspan'):1,rowspan:td.hasAttribute('rowspan')?td.getAttribute('rowspan'):1,style:td.hasAttribute('style')?td.getAttribute('style'):'',html:td.innerHTML};D+=E.colspan;C.push(E);},this);this.no_col=Math.max(this.no_col,D);
-},this);},normalizeRows:function(){var A=[];var B=-1;this.rows.forEach(function(C){B++;A[B]=[];C=this.normalizeRow(C);var D=0;C.forEach(function(c){while(typeof(A[B][D])!='undefined'){D++;}if(typeof(A[B])=='undefined'){A[B]=[];}A[B][D]=c;c.row=B;c.col=D;if(c.rowspan<2){return;
-}for(var i=1;i<c.rowspan;i++){if(typeof(A[B+i])=='undefined'){A[B+i]=[];}A[B+i][D]=c;}});},this);return A;},normalizeRow:function(A){var B=[];A.forEach(function(c){if(c.colspan<2){B.push(c);return;}for(var i=0;i<c.colspan;i++){B.push(c);}});return B;},deleteColumn:function(A){if(!A||A.type!='col'){return;
-}if(this.no_col<2){return;}this.rows.forEach(function(B){var C=this.normalizeRow(B);var D=C[A.col];if(D.colspan>1){D.colspan--;}else{B.remove(D);}},this);this.no_col--;},removeColumn:function(){this.deleteColumn({type:'col',col:this.no_col-1});this.updateElement();
-},addColumn:function(){this.rows.forEach(function(A){A.push(this.emptyCell());},this);this.updateElement();},deleteRow:function(A){if(!A||A.type!='row'){return;}if(this.no_row<2){return;}var B=this.normalizeRows();B[A.row].forEach(function(D){if(D.rowspan>1){D.rowspan--;
-}else{D.remove=1;}},this);var C=[];this.rows.forEach(function(D){newrow=[];D.forEach(function(c){if(typeof(c.remove)=='undefined'){newrow.push(c);}});if(newrow.length>0){C.push(D);}});this.rows=C;this.no_row--;this.updateElement();},removeRow:function(){this.deleteRow({type:'row',row:this.no_row-1}
-);},addRow:function(){row=[];for(var i=0;i<this.no_col;i++){row.push(this.emptyCell());}this.rows.push(row);this.updateElement();},emptyCell:function(){return (new Roo.htmleditor.BlockTd({})).toObject();},removeNode:function(){return this.node;},resetWidths:function(){Array.from(this.node.getElementsByTagName('td')).forEach(function(n){var nn=Roo.htmleditor.Block.factory(n);
+this.rows=[];this.no_row=0;var B=Array.from(A.rows);B.forEach(function(tr){var C=[];this.rows.push(C);this.no_row++;var D=0;Array.from(tr.cells).forEach(function(td){var E={colspan:td.hasAttribute('colspan')?td.getAttribute('colspan')*1:1,rowspan:td.hasAttribute('rowspan')?td.getAttribute('rowspan')*1:1,style:td.hasAttribute('style')?td.getAttribute('style'):'',html:td.innerHTML}
+;D+=E.colspan;C.push(E);},this);this.no_col=Math.max(this.no_col,D);},this);},normalizeRows:function(){var A=[];var B=-1;this.rows.forEach(function(C){B++;A[B]=[];C=this.normalizeRow(C);var D=0;C.forEach(function(c){while(typeof(A[B][D])!='undefined'){D++;
+}if(typeof(A[B])=='undefined'){A[B]=[];}A[B][D]=c;c.row=B;c.col=D;if(c.rowspan<2){return;}for(var i=1;i<c.rowspan;i++){if(typeof(A[B+i])=='undefined'){A[B+i]=[];}A[B+i][D]=c;}});},this);return A;},normalizeRow:function(A){var B=[];A.forEach(function(c){if(c.colspan<2){B.push(c);
+return;}for(var i=0;i<c.colspan;i++){B.push(c);}});return B;},deleteColumn:function(A){if(!A||A.type!='col'){return;}if(this.no_col<2){return;}this.rows.forEach(function(B){var C=this.normalizeRow(B);var D=C[A.col];if(D.colspan>1){D.colspan--;}else{B.remove(D);
+}},this);this.no_col--;},removeColumn:function(){this.deleteColumn({type:'col',col:this.no_col-1});this.updateElement();},addColumn:function(){this.rows.forEach(function(A){A.push(this.emptyCell());},this);this.updateElement();},deleteRow:function(A){if(!A||A.type!='row'){return;
+}if(this.no_row<2){return;}var B=this.normalizeRows();B[A.row].forEach(function(D){if(D.rowspan>1){D.rowspan--;}else{D.remove=1;}},this);var C=[];this.rows.forEach(function(D){newrow=[];D.forEach(function(c){if(typeof(c.remove)=='undefined'){newrow.push(c);
+}});if(newrow.length>0){C.push(D);}});this.rows=C;this.no_row--;this.updateElement();},removeRow:function(){this.deleteRow({type:'row',row:this.no_row-1});},addRow:function(){var A=[];for(var i=0;i<this.no_col;i++){A.push(this.emptyCell());}this.rows.push(A);
+this.updateElement();},emptyCell:function(){return (new Roo.htmleditor.BlockTd({})).toObject();},removeNode:function(){return this.node;},resetWidths:function(){Array.from(this.node.getElementsByTagName('td')).forEach(function(n){var nn=Roo.htmleditor.Block.factory(n);
 nn.width='';nn.updateElement(n);});}})
 // Roo/htmleditor/BlockTd.js
-Roo.htmleditor.BlockTd=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockTd,Roo.htmleditor.Block,{node:false,width:'',textAlign:'left',colspan:1,rowspan:1,friendly_name:'Table Cell',deleteTitle:'Delete Table',contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);
+Roo.htmleditor.BlockTd=function(A){if(A.node){this.readElement(A.node);this.updateElement(A.node);}Roo.apply(this,A);};Roo.extend(Roo.htmleditor.BlockTd,Roo.htmleditor.Block,{node:false,width:'',textAlign:'left',valign:'top',colspan:1,rowspan:1,friendly_name:'Table Cell',deleteTitle:false,contextMenu:function(A){var B=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode);
 };var C=function(){return Roo.htmleditor.Block.factory(A.tb.selectedNode.closest('table'));};var lr=false;var D=function(){lr=A.editorcore.getSelection().getRangeAt(0);};var restoreSel=function(){if(lr){(function(){A.editorcore.focus();var cr=A.editorcore.getSelection();
 cr.removeAllRanges();cr.addRange(lr);A.editorcore.onEditorEvent();}).defer(10,this);}};var rooui=typeof(Roo.bootstrap)=='undefined'?Roo:Roo.bootstrap;var E=A.editorcore.syncValue;var F={};return [{xtype:'Button',text:'Edit Table',listeners:{click:function(){var t=A.tb.selectedNode.closest('table');
-A.editorcore.selectNode(t);A.editorcore.onEditorEvent();}}},{xtype:'TextItem',text:"Column Width: ",xns:rooui.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(G,e){D();B().shrinkColumn();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(G,e){D();
-B().growColumn();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"Merge Cells: ",xns:rooui.Toolbar},{xtype:'Button',text:'Right',listeners:{click:function(G,e){D();B().mergeRight();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'Button',text:'Below',listeners:{click:function(G,e){D();
-B().mergeBelow();E();restoreSel();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"| ",xns:rooui.Toolbar},{xtype:'Button',text:'Split',listeners:{click:function(G,e){D();B().split();E();restoreSel();}},xns:rooui.Toolbar}];},toObject:function(){var A={tag:'td',contenteditable:'true','data-block':'Td',width:this.width,style:{width:this.width,'text-align':this.textAlign,border:'solid 1px rgb(0, 0, 0)','border-collapse':'collapse'}
-,html:this.html};if(this.colspan>1){A.colspan=cell.colspan;}if(A.rowspan>1){this.rowspan=cell.rowspan;}return A;},readElement:function(A){A=A?A:this.node;this.width=A.style.width;this.html=A.innerHTML;},emptyCell:function(){return {colspan:1,rowspan:1,textAlign:'left',html:"&nbsp;"}
-;},removeNode:function(){return this.node.closest('table');},cellData:false,colWidths:false,toTableArray:function(){var A=[];var B=this.node.closest('tr').closest('table');Array.from(B.rows).forEach(function(r,ri){A[ri]=[];});var rn=0;this.colWidths=[];var C=true;
-Array.from(B.rows).forEach(function(r,ri){var cn=0;Array.from(r.cells).forEach(function(ce,ci){var c={cell:ce,row:rn,col:cn,colspan:ce.colSpan,rowspan:ce.rowSpan};if(ce.isEqualNode(this.node)){this.cellData=c;}if(typeof(A[rn][cn])!='undefined'){while(typeof(A[rn][cn])!='undefined'){cn++;
-}c.col=cn;}if(typeof(this.colWidths[cn])=='undefined'){this.colWidths[cn]=ce.style.width;if(this.colWidths[cn]!=''){C=false;}}if(c.colspan<2&&c.rowspan<2){A[rn][cn]=c;cn++;return;}for(var j=0;j<c.rowspan;j++){if(typeof(A[rn+j])=='undefined'){continue;}A[rn+j][cn]=c;
-for(var i=0;i<c.colspan;i++){A[rn+j][cn+i]=c;}}cn+=c.colspan;},this);rn++;},this);if(C){this.colWidths[0]=false;}return A;},mergeRight:function(){var tr=this.node.closest('tr');var i=Array.prototype.indexOf.call(tr.childNodes,this.node);if(i>=tr.childNodes.length-1){return;
-}var A=this.toTableArray();if(typeof(A[this.cellData.row][this.cellData.col+this.cellData.colspan])=='undefined'){return;}var rc=A[this.cellData.row][this.cellData.col+this.cellData.colspan];if(rc.rowspan!=this.cellData.rowspan||rc.row!=this.cellData.row){return;
-}this.node.innerHTML+=' '+rc.cell.innerHTML;tr.removeChild(rc.cell);this.colspan+=rc.colspan;this.node.setAttribute('colspan',this.colspan);},mergeBelow:function(){var A=this.toTableArray();if(typeof(A[this.cellData.row+this.cellData.rowspan])=='undefined'){return;
-}if(typeof(A[this.cellData.row+this.cellData.rowspan][this.cellData.col])=='undefined'){return;}var rc=A[this.cellData.row+this.cellData.rowspan][this.cellData.col];if(rc.colspan!=this.cellData.colspan||rc.col!=this.cellData.col){return;}this.node.innerHTML=this.node.innerHTML+rc.cell.innerHTML;
-rc.cell.parentNode.removeChild(rc.cell);this.rowspan+=rc.rowspan;this.node.setAttribute('rowspan',this.rowspan);},split:function(){if(this.node.rowSpan<2&&this.node.colSpan<2){return;}var A=this.toTableArray();var cd=this.cellData;this.rowspan=1;this.colspan=1;
-for(var r=cd.row;r<cd.row+cd.rowspan;r++){for(var c=cd.col;c<cd.col+cd.colspan;c++){if(r==cd.row&&c==cd.col){this.node.removeAttribute('rowspan');this.node.removeAttribute('colspan');continue;}var B=this.node.cloneNode();B.removeAttribute('id');B.innerHTML='';
-A[r][c]={cell:B,col:c,row:r,colspan:1,rowspan:1};}}this.redrawAllCells(A);},redrawAllCells:function(A){var B=this.node.closest('tr').closest('table');Array.from(B.rows).forEach(function(r,ri){Array.from(r.cells).forEach(function(ce,ci){ce.parentNode.removeChild(ce);
-});});for(var r=0;r<A.length;r++){var re=B.rows[r];for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;}re.appendChild(A[r][c].cell);A[r][c].cell=false;}}},updateWidths:function(A){for(var r=0;r<A.length;r++){for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;
-}if(this.colWidths[0]!=false&&A[r][c].colspan<2){var el=Roo.htmleditor.Block.factory(A[r][c].cell);el.width=Math.floor(this.colWidths[c])+'%';el.updateElement(el.node);}A[r][c].cell=false;}}},normalizeWidths:function(A){if(this.colWidths[0]===false){var nw=100.0/this.colWidths.length;
-this.colWidths.forEach(function(w,i){this.colWidths[i]=nw;},this);return;}var t=0,B=[];this.colWidths.forEach(function(w,i){this.colWidths[i]=this.colWidths[i]==''?0:(this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;var D=this.colWidths[i];if(D>0){t+=D;return;
-}B.push(i);},this);var nc=this.colWidths.length;if(B.length){var C=(nc-B.length)/(1.0*nc);var t=C*t;var ew=(100-t)/(1.0*B.length);this.colWidths.forEach(function(w,i){if(w>0){this.colWidths[i]=w*C;return;}this.colWidths[i]=ew;},this);}},shrinkColumn:function(){var A=this.toTableArray();
-this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*0.8;if(nw<5){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;return;}this.colWidths[i]+=C},this);this.updateWidths(A);
-},growColumn:function(){var A=this.toTableArray();this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*1.2;if(nw>90){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;
-return;}this.colWidths[i]-=C},this);this.updateWidths(A);}})
+A.editorcore.selectNode(t);A.editorcore.onEditorEvent();}}},{xtype:'TextItem',text:"Column Width: ",xns:rooui.Toolbar},{xtype:'Button',text:'-',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);B().shrinkColumn();E();A.editorcore.onEditorEvent();
+}},xns:rooui.Toolbar},{xtype:'Button',text:'+',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);B().growColumn();E();A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"Vertical Align: ",xns:rooui.Toolbar},{xtype:'ComboBox',allowBlank:false,displayField:'val',editable:true,listWidth:100,triggerAction:'all',typeAhead:true,valueField:'val',width:100,name:'valign',listeners:{select:function(G,r,H){A.editorcore.selectNode(A.tb.selectedNode);
+var b=B();b.valign=r.get('val');b.updateElement();E();A.editorcore.onEditorEvent();}},xns:rooui.form,store:{xtype:'SimpleStore',data:[['top'],['middle'],['bottom']],fields:['val'],xns:Roo.data}},{xtype:'TextItem',text:"Merge Cells: ",xns:rooui.Toolbar},{xtype:'Button',text:'Right',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);
+B().mergeRight();E();A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'Button',text:'Below',listeners:{click:function(G,e){A.editorcore.selectNode(A.tb.selectedNode);B().mergeBelow();E();A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'TextItem',text:"| ",xns:rooui.Toolbar}
+,{xtype:'Button',text:'Split',listeners:{click:function(G,e){B().split();E();A.editorcore.selectNode(A.tb.selectedNode);A.editorcore.onEditorEvent();}},xns:rooui.Toolbar},{xtype:'Fill',xns:rooui.Toolbar},{xtype:'Button',text:'Delete',xns:rooui.Toolbar,menu:{xtype:'Menu',xns:rooui.menu,items:[{xtype:'Item',html:'Column',listeners:{click:function(G,e){var t=C();
+B().deleteColumn();E();A.editorcore.selectNode(t.node);A.editorcore.onEditorEvent();}},xns:rooui.menu},{xtype:'Item',html:'Row',listeners:{click:function(G,e){var t=C();B().deleteRow();E();A.editorcore.selectNode(t.node);A.editorcore.onEditorEvent();}},xns:rooui.menu}
+,{xtype:'Separator',xns:rooui.menu},{xtype:'Item',html:'Table',listeners:{click:function(G,e){var t=C();var nn=t.node.nextSibling||t.node.previousSibling;t.node.parentNode.removeChild(t.node);if(nn){A.editorcore.selectNode(nn,true);}A.editorcore.onEditorEvent();
+}},xns:rooui.menu}]}}];},toObject:function(){var A={tag:'td',contenteditable:'true','data-block':'Td',valign:this.valign,style:{'text-align':this.textAlign,border:'solid 1px rgb(0, 0, 0)','border-collapse':'collapse',padding:'6px','vertical-align':this.valign}
+,html:this.html};if(this.width!=''){A.width=this.width;A.style.width=this.width;}if(this.colspan>1){A.colspan=this.colspan;}if(this.rowspan>1){A.rowspan=this.rowspan;}return A;},readElement:function(A){A=A?A:this.node;this.width=A.style.width;this.colspan=Math.max(1,1*A.getAttribute('colspan'));
+this.rowspan=Math.max(1,1*A.getAttribute('rowspan'));this.html=A.innerHTML;},emptyCell:function(){return {colspan:1,rowspan:1,textAlign:'left',html:"&nbsp;"};},removeNode:function(){return this.node.closest('table');},cellData:false,colWidths:false,toTableArray:function(){var A=[];
+var B=this.node.closest('tr').closest('table');Array.from(B.rows).forEach(function(r,ri){A[ri]=[];});var rn=0;this.colWidths=[];var C=true;Array.from(B.rows).forEach(function(r,ri){var cn=0;Array.from(r.cells).forEach(function(ce,ci){var c={cell:ce,row:rn,col:cn,colspan:ce.colSpan,rowspan:ce.rowSpan}
+;if(ce.isEqualNode(this.node)){this.cellData=c;}if(typeof(A[rn][cn])!='undefined'){while(typeof(A[rn][cn])!='undefined'){cn++;}c.col=cn;}if(typeof(this.colWidths[cn])=='undefined'){this.colWidths[cn]=ce.style.width;if(this.colWidths[cn]!=''){C=false;}}if(c.colspan<2&&c.rowspan<2){A[rn][cn]=c;
+cn++;return;}for(var j=0;j<c.rowspan;j++){if(typeof(A[rn+j])=='undefined'){continue;}A[rn+j][cn]=c;for(var i=0;i<c.colspan;i++){A[rn+j][cn+i]=c;}}cn+=c.colspan;},this);rn++;},this);if(C){this.colWidths[0]=false;}return A;},mergeRight:function(){var tr=this.node.closest('tr');
+var i=Array.prototype.indexOf.call(tr.childNodes,this.node);if(i>=tr.childNodes.length-1){return;}var A=this.toTableArray();if(typeof(A[this.cellData.row][this.cellData.col+this.cellData.colspan])=='undefined'){return;}var rc=A[this.cellData.row][this.cellData.col+this.cellData.colspan];
+if(rc.rowspan!=this.cellData.rowspan||rc.row!=this.cellData.row){return;}this.node.innerHTML+=' '+rc.cell.innerHTML;tr.removeChild(rc.cell);this.colspan+=rc.colspan;this.node.setAttribute('colspan',this.colspan);},mergeBelow:function(){var A=this.toTableArray();
+if(typeof(A[this.cellData.row+this.cellData.rowspan])=='undefined'){return;}if(typeof(A[this.cellData.row+this.cellData.rowspan][this.cellData.col])=='undefined'){return;}var rc=A[this.cellData.row+this.cellData.rowspan][this.cellData.col];if(rc.colspan!=this.cellData.colspan||rc.col!=this.cellData.col){return;
+}this.node.innerHTML=this.node.innerHTML+rc.cell.innerHTML;rc.cell.parentNode.removeChild(rc.cell);this.rowspan+=rc.rowspan;this.node.setAttribute('rowspan',this.rowspan);},split:function(){if(this.node.rowSpan<2&&this.node.colSpan<2){return;}var A=this.toTableArray();
+var cd=this.cellData;this.rowspan=1;this.colspan=1;for(var r=cd.row;r<cd.row+cd.rowspan;r++){for(var c=cd.col;c<cd.col+cd.colspan;c++){if(r==cd.row&&c==cd.col){this.node.removeAttribute('rowspan');this.node.removeAttribute('colspan');continue;}var B=this.node.cloneNode();
+B.removeAttribute('id');B.innerHTML='';A[r][c]={cell:B,col:c,row:r,colspan:1,rowspan:1};}}this.redrawAllCells(A);},redrawAllCells:function(A){var B=this.node.closest('tr').closest('table');var C=B.rows[0].parentNode;Array.from(B.rows).forEach(function(r,ri){Array.from(r.cells).forEach(function(ce,ci){ce.parentNode.removeChild(ce);
+});r.parentNode.removeChild(r);});for(var r=0;r<A.length;r++){var re=B.rows[r];var re=B.ownerDocument.createElement('tr');C.appendChild(re);for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;}re.appendChild(A[r][c].cell);A[r][c].cell=false;}
+}},updateWidths:function(A){for(var r=0;r<A.length;r++){for(var c=0;c<A[r].length;c++){if(A[r][c].cell===false){continue;}if(this.colWidths[0]!=false&&A[r][c].colspan<2){var el=Roo.htmleditor.Block.factory(A[r][c].cell);el.width=Math.floor(this.colWidths[c])+'%';
+el.updateElement(el.node);}A[r][c].cell=false;}}},normalizeWidths:function(A){if(this.colWidths[0]===false){var nw=100.0/this.colWidths.length;this.colWidths.forEach(function(w,i){this.colWidths[i]=nw;},this);return;}var t=0,B=[];this.colWidths.forEach(function(w,i){this.colWidths[i]=this.colWidths[i]==''?0:(this.colWidths[i]+'').replace(/[^0-9]+/g,'')*1;
+var D=this.colWidths[i];if(D>0){t+=D;return;}B.push(i);},this);var nc=this.colWidths.length;if(B.length){var C=(nc-B.length)/(1.0*nc);var t=C*t;var ew=(100-t)/(1.0*B.length);this.colWidths.forEach(function(w,i){if(w>0){this.colWidths[i]=w*C;return;}this.colWidths[i]=ew;
+},this);}},shrinkColumn:function(){var A=this.toTableArray();this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*0.8;if(nw<5){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;
+return;}this.colWidths[i]+=C},this);this.updateWidths(A);},growColumn:function(){var A=this.toTableArray();this.normalizeWidths(A);var B=this.cellData.col;var nw=this.colWidths[B]*1.2;if(nw>90){return;}var C=(this.colWidths[B]*0.2)/(this.colWidths.length-1);
+this.colWidths.forEach(function(w,i){if(i==B){this.colWidths[i]=nw;return;}this.colWidths[i]-=C},this);this.updateWidths(A);},deleteRow:function(){var A=this.toTableArray();for(var i=0;i<A[this.cellData.row].length;i++){var c=A[this.cellData.row][i];if(c.row!=this.cellData.row){c.rowspan--;
+c.cell.setAttribute('rowspan',c.rowspan);continue;}if(c.rowspan>1){c.rowspan--;c.cell.setAttribute('rowspan',c.rowspan);}}A.splice(this.cellData.row,1);this.redrawAllCells(A);},deleteColumn:function(){var A=this.toTableArray();for(var i=0;i<A.length;i++){var c=A[i][this.cellData.col];
+if(c.col!=this.cellData.col){A[i][this.cellData.col].colspan--;}else if(c.colspan>1){c.colspan--;c.cell.setAttribute('colspan',c.colspan);}A[i].splice(this.cellData.col,1);}this.redrawAllCells(A);}})
 // Roo/HtmlEditorCore.js
-Roo.HtmlEditorCore=function(A){Roo.HtmlEditorCore.superclass.constructor.call(this,A);this.addEvents({initialize:true,activate:true,beforesync:true,beforepush:true,sync:true,push:true,editorevent:true});this.applyBlacklists();};Roo.extend(Roo.HtmlEditorCore,Roo.Component,{owner:false,resizable:false,height:300,width:500,stylesheets:false,allowComments:false,frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,sourceEditMode:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',clearUp:true,black:false,white:false,bodyCls:'',undoManager:false,getDocMarkup:function(){var st='';
+Roo.HtmlEditorCore=function(A){Roo.HtmlEditorCore.superclass.constructor.call(this,A);this.addEvents({initialize:true,activate:true,beforesync:true,beforepush:true,sync:true,push:true,editorevent:true});this.applyBlacklists();};Roo.extend(Roo.HtmlEditorCore,Roo.Component,{owner:false,resizable:false,height:300,width:500,autoClean:true,enableBlocks:true,stylesheets:false,allowComments:false,frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,sourceEditMode:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',clearUp:true,black:false,white:false,bodyCls:'',undoManager:false,getDocMarkup:function(){var st='';
 if(this.stylesheets===false){Roo.get(document.head).select('style').each(function(B){st+=B.dom.outerHTML||new XMLSerializer().serializeToString(B.dom);});Roo.get(document.head).select('link').each(function(B){st+=B.dom.outerHTML||new XMLSerializer().serializeToString(B.dom);
 });}else if(!this.stylesheets.length){st='<style type="text/css">'+'body{border:0;margin:0;padding:3px;height:98%;cursor:text;}'+'</style>';}else{for(var i in this.stylesheets){if(typeof(this.stylesheets[i])!='string'){continue;}st+='<link rel="stylesheet" href="'+this.stylesheets[i]+'" type="text/css">';
 }}st+='<style type="text/css">'+'IMG { cursor: pointer } '+'</style>';var A='roo-htmleditor-body';if(this.bodyCls.length){A+=' '+this.bodyCls;}return '<html><head>'+st+' </head><body contenteditable="true" data-enable-grammerly="true" class="'+A+'"></body></html>';
@@ -1073,37 +1086,39 @@ this.doc.open();this.doc.write(this.getDocMarkup());this.doc.close();var C={run:
 }},interval:10,duration:10000,scope:this};Roo.TaskMgr.start(C);},onResize:function(w,h){Roo.log('resize: '+w+','+h);if(!this.iframe){return;}if(typeof w=='number'){this.iframe.style.width=w+'px';}if(typeof h=='number'){this.iframe.style.height=h+'px';if(this.doc){(this.doc.body||this.doc.documentElement).style.height=(h-(this.iframePad*2))+'px';
 }}},toggleSourceEdit:function(A){this.sourceEditMode=A===true;if(this.sourceEditMode){Roo.get(this.iframe).addClass(['x-hidden','hide','d-none']);}else{Roo.get(this.iframe).removeClass(['x-hidden','hide','d-none']);this.deferFocus();}},cleanHtml:function(A){A=String(A);
 if(A.length>5){if(Roo.isSafari){A=A.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi,'');}}if(A=='&nbsp;'){A='';}return A;},syncValue:function(){if(this.initialized){this.undoManager.addEvent();var bd=(this.doc.body||this.doc.documentElement);
-var A=document.createElement('div');A.innerHTML=bd.innerHTML;new Roo.htmleditor.FilterBlock({node:A});var B=A.innerHTML;if(Roo.isSafari){var bs=bd.getAttribute('style');var m=bs?bs.match(/text-align:(.*?);/i):false;if(m&&m[1]){B='<div style="'+m[0]+'">'+B+'</div>';
+var A=document.createElement('div');A.innerHTML=bd.innerHTML;if(this.enableBlocks){new Roo.htmleditor.FilterBlock({node:A});}var B=A.innerHTML;if(Roo.isSafari){var bs=bd.getAttribute('style');var m=bs?bs.match(/text-align:(.*?);/i):false;if(m&&m[1]){B='<div style="'+m[0]+'">'+B+'</div>';
 }}B=this.cleanHtml(B);B=B.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u0080-\uFFFF]/g,function(C){var cc=C.charCodeAt();if(C.length==2){var D=C.charCodeAt(0)-0xD800;var E=C.charCodeAt(1)-0xDC00;cc=(D*0x400)+E+0x10000;}else if((cc>=0x4E00&&cc<0xA000)||(cc>=0x3400&&cc<0x4E00)||(cc>=0xf900&&cc<0xfb00)){return C;
 }return "&#"+cc+";";});if(this.owner.fireEvent('beforesync',this,B)!==false){this.el.dom.value=B;this.owner.fireEvent('sync',this,B);}}},pushValue:function(){if(this.initialized){var v=this.el.dom.value.trim();if(this.owner.fireEvent('beforepush',this,v)!==false){var d=(this.doc.body||this.doc.documentElement);
-d.innerHTML=v;this.el.dom.value=d.innerHTML;this.owner.fireEvent('push',this,v);}Roo.htmleditor.Block.initAll(this.doc.body);var lc=this.doc.body.lastChild;if(lc&&lc.nodeType==1&&lc.getAttribute("contenteditable")=="false"){this.doc.body.appendChild(this.doc.createElement('br'));
-}}},deferFocus:function(){this.focus.defer(10,this);},focus:function(){if(this.win&&!this.sourceEditMode){this.win.focus();}else{this.el.focus();}},assignDocWin:function(){var A=this.iframe;if(Roo.isIE){this.doc=A.contentWindow.document;this.win=A.contentWindow;
-}else{if(!Roo.get(this.frameId)&&!A.contentDocument){return;}this.doc=(A.contentDocument||Roo.get(this.frameId).dom.document);this.win=(A.contentWindow||Roo.get(this.frameId).dom.contentWindow);}},initEditor:function(){this.assignDocWin();this.doc.designMode="on";
-this.doc.open();this.doc.write(this.getDocMarkup());this.doc.close();var A=(this.doc.body||this.doc.documentElement);A.bgProperties='fixed';Roo.EventManager.on(this.doc,{'mouseup':this.onEditorEvent,'dblclick':this.onEditorEvent,'click':this.onEditorEvent,'keyup':this.onEditorEvent,buffer:100,scope:this}
+d.innerHTML=v;this.el.dom.value=d.innerHTML;this.owner.fireEvent('push',this,v);}if(this.autoClean){new Roo.htmleditor.FilterParagraph({node:this.doc.body});new Roo.htmleditor.FilterSpan({node:this.doc.body});}Roo.htmleditor.Block.initAll(this.doc.body);var lc=this.doc.body.lastChild;
+if(lc&&lc.nodeType==1&&lc.getAttribute("contenteditable")=="false"){this.doc.body.appendChild(this.doc.createElement('br'));}}},deferFocus:function(){this.focus.defer(10,this);},focus:function(){if(this.win&&!this.sourceEditMode){this.win.focus();}else{this.el.focus();
+}},assignDocWin:function(){var A=this.iframe;if(Roo.isIE){this.doc=A.contentWindow.document;this.win=A.contentWindow;}else{if(!Roo.get(this.frameId)&&!A.contentDocument){return;}this.doc=(A.contentDocument||Roo.get(this.frameId).dom.document);this.win=(A.contentWindow||Roo.get(this.frameId).dom.contentWindow);
+}},initEditor:function(){this.assignDocWin();this.doc.designMode="on";this.doc.open();this.doc.write(this.getDocMarkup());this.doc.close();var A=(this.doc.body||this.doc.documentElement);A.bgProperties='fixed';Roo.EventManager.on(this.doc,{'mouseup':this.onEditorEvent,'dblclick':this.onEditorEvent,'click':this.onEditorEvent,'keyup':this.onEditorEvent,buffer:100,scope:this}
 );Roo.EventManager.on(this.doc,{'paste':this.onPasteEvent,scope:this});if(Roo.isGecko){Roo.EventManager.on(this.doc,'keypress',this.mozKeyPress,this);}if(Roo.isIE||Roo.isSafari||Roo.isOpera){Roo.EventManager.on(this.doc,'keydown',this.fixKeys,this);}this.initialized=true;
 new Roo.htmleditor.KeyEnter({core:this});this.owner.fireEvent('initialize',this);this.pushValue();},onPasteEvent:function(e,v){var cd=(e.browserEvent.clipboardData||window.clipboardData);if(cd.files.length>0){var A=(window.createObjectURL&&window)||(window.URL&&URL.revokeObjectURL&&URL)||(window.webkitURL&&webkitURL);
 var B=A.createObjectURL(cd.files[0]);this.insertAtCursor('<img src=" + url + ">');return false;}var C=cd.getData('text/html');var D=new Roo.rtf.Parser(cd.getData('text/rtf'));var E=D.doc?D.doc.getElementsByType('pict'):[];Roo.log(E);E=E.filter(function(g){return !g.path.match(/^rtf\/(head|pgdsctbl|listtable)/);
 }).map(function(g){return g.toDataURL();});C=this.cleanWordChars(C);var d=(new DOMParser().parseFromString(C,'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(E.length>0){Roo.each(d.getElementsByTagName('img'),function(F,i){F.setAttribute('src',E[i]);});}new Roo.htmleditor.FilterStyleToTag({node:d});new Roo.htmleditor.FilterAttributes({node:d,attrib_white:['href','src','name','align'],attrib_clean:['href','src']}
-);new Roo.htmleditor.FilterBlack({node:d,tag:this.black});new Roo.htmleditor.FilterKeepChildren({node:d,tag:['FONT']});new Roo.htmleditor.FilterParagraph({node:d});new Roo.htmleditor.FilterSpan({node:d});new Roo.htmleditor.FilterLongBr({node:d});this.insertAtCursor(d.innerHTML);
-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=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.owner.fireEvent('editorevent',this,e);this.syncValue();},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){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;
+return false;}if(E.length>0){Roo.each(d.getElementsByTagName('img'),function(F,i){F.setAttribute('src',E[i]);});}if(this.autoClean){new Roo.htmleditor.FilterStyleToTag({node:d});new Roo.htmleditor.FilterAttributes({node:d,attrib_white:['href','src','name','align'],attrib_clean:['href','src']}
+);new Roo.htmleditor.FilterBlack({node:d,tag:this.black});new Roo.htmleditor.FilterKeepChildren({node:d,tag:['FONT']});new Roo.htmleditor.FilterParagraph({node:d});new Roo.htmleditor.FilterSpan({node:d});new Roo.htmleditor.FilterLongBr({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.win.focus();this.execCmd(A);this.deferFocus();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;}};}}(),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.isIE?this.doc.selection:this.win.getSelection();
-},selectNode:function(A){var B=A.ownerDocument.createRange();try{B.selectNode(A);}catch(e){B.selectNodeContents(A);}var s=this.win.getSelection();s.removeAllRanges();s.addRange(B);},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]);
+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();
@@ -1124,24 +1139,25 @@ Roo.HtmlEditorCore.black=['APPLET','BASE','BASEFONT','BGSOUND','BLINK','BODY','F
 Roo.HtmlEditorCore.tag_remove=['FONT','TBODY'];Roo.HtmlEditorCore.ablack=['on'];Roo.HtmlEditorCore.aclean=['action','background','codebase','dynsrc','href','lowsrc'];Roo.HtmlEditorCore.pwhite=['http','https','mailto'];Roo.HtmlEditorCore.cwhite=[];Roo.HtmlEditorCore.cblack=[];
 
 // Roo/form/HtmlEditor.js
-Roo.form.HtmlEditor=function(A){Roo.form.HtmlEditor.superclass.constructor.call(this,A);if(!this.toolbars){this.toolbars=[];}this.editorcore=new Roo.HtmlEditorCore(Roo.apply({owner:this},A));};Roo.extend(Roo.form.HtmlEditor,Roo.form.Field,{clearUp:true,toolbars:false,resizable:false,height:300,width:500,stylesheets:false,cblack:false,cwhite:false,black:false,white:false,allowComments:false,bodyCls:'',frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',actionMode:'container',defaultAutoCreate:{tag:"textarea",style:"width:500px;height:300px;",autocomplete:"new-password"}
+Roo.form.HtmlEditor=function(A){Roo.form.HtmlEditor.superclass.constructor.call(this,A);if(!this.toolbars){this.toolbars=[];}this.editorcore=new Roo.HtmlEditorCore(Roo.apply({owner:this},A));};Roo.extend(Roo.form.HtmlEditor,Roo.form.Field,{clearUp:true,toolbars:false,resizable:false,height:300,width:500,stylesheets:false,cblack:false,cwhite:false,black:false,white:false,allowComments:false,enableBlocks:true,autoClean:true,bodyCls:'',frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',actionMode:'container',defaultAutoCreate:{tag:"textarea",style:"width:500px;height:300px;",autocomplete:"new-password"}
 ,initComponent:function(){this.addEvents({initialize:true,activate:true,beforesync:true,beforepush:true,sync:true,push:true,editmodechange:true,editorevent:true,firstfocus:true,autosave:true,savedpreview:true,stylesheetsclick:true,paste:true});this.defaultAutoCreate={tag:"textarea",style:'width: '+this.width+'px;height: '+this.height+'px;',autocomplete:"new-password"}
 ;},createToolbar:function(A){Roo.log("create toolbars");if(!A.toolbars||!A.toolbars.length){A.toolbars=[new Roo.form.HtmlEditor.ToolbarStandard()];}for(var i=0;i<A.toolbars.length;i++){A.toolbars[i]=Roo.factory(typeof(A.toolbars[i])=='string'?{xtype:A.toolbars[i]}
-:A.toolbars[i],Roo.form.HtmlEditor);A.toolbars[i].init(A);}},onRender:function(ct,A){var _t=this;Roo.form.HtmlEditor.superclass.onRender.call(this,ct,A);this.wrap=this.el.wrap({cls:'x-html-editor-wrap',cn:{cls:'x-html-editor-tb'}});this.editorcore.onRender(ct,A);
-if(this.resizable){this.resizeEl=new Roo.Resizable(this.wrap,{pinned:true,wrap:true,dynamic:true,minHeight:this.height,height:this.height,handles:this.resizable,width:this.width,listeners:{resize:function(r,w,h){_t.onResize(w,h);}}});}this.createToolbar(this);
-if(!this.width){this.setSize(this.wrap.getSize());}if(this.resizeEl){this.resizeEl.resizeTo.defer(100,this.resizeEl,[this.width,this.height]);}this.keyNav=new Roo.KeyNav(this.el,{"tab":function(e){e.preventDefault();var B=this.getValue();var C=this.el.dom.selectionStart;
-var D=this.el.dom.selectionEnd;if(!e.shiftKey){this.setValue(B.substring(0,C)+"\t"+B.substring(D));this.el.dom.setSelectionRange(D+1,D+1);return;}var f=B.substring(0,C).split("\t");if(f.pop().length!=0){return;}this.setValue(f.join("\t")+B.substring(D));this.el.dom.setSelectionRange(C-1,C-1);
-},"home":function(e){e.preventDefault();var B=this.el.dom.selectionStart;var C=this.getValue().split("\n");if(!C.length){return;}if(e.ctrlKey){this.el.dom.setSelectionRange(0,0);return;}var D=0;for(var i=0;i<C.length;i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;
-}D-=C[i].length;break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);return;}this.el.dom.selectionStart=D;this.el.dom.selectionEnd=B;},"end":function(e){e.preventDefault();var B=this.el.dom.selectionStart;var C=this.getValue().split("\n");if(!C.length){return;
-}if(e.ctrlKey){this.el.dom.setSelectionRange(this.getValue().length,this.getValue().length);return;}var D=0;for(var i=0;i<C.length;i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;}break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);return;}this.el.dom.selectionStart=B;
-this.el.dom.selectionEnd=D;},scope:this,doRelay:function(B,C,D){return Roo.KeyNav.prototype.doRelay.apply(this,arguments);},forceKeyDown:true});},onResize:function(w,h){Roo.form.HtmlEditor.superclass.onResize.apply(this,arguments);var ew=false;var eh=false;
-if(this.el){if(typeof w=='number'){var aw=w-this.wrap.getFrameWidth('lr');this.el.setWidth(this.adjustWidth('textarea',aw));ew=aw;}if(typeof h=='number'){var A=0;for(var i=0;i<this.toolbars.length;i++){A+=this.toolbars[i].tb.el.getHeight();if(this.toolbars[i].footer){A+=this.toolbars[i].footer.el.getHeight();
-}}var ah=h-this.wrap.getFrameWidth('tb')-A;ah-=5;this.el.setHeight(this.adjustWidth('textarea',ah));var eh=ah;}}Roo.log('onResize:'+[w,h,ew,eh].join(','));this.editorcore.onResize(ew,eh);},toggleSourceEdit:function(A){this.editorcore.toggleSourceEdit(A);if(this.editorcore.sourceEditMode){Roo.log('editor - showing textarea');
-this.editorcore.syncValue();this.el.removeClass('x-hidden');this.el.dom.removeAttribute('tabIndex');this.el.focus();this.el.dom.scrollTop=0;for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.hide();
-this.toolbars[i].footer.hide();}}}else{Roo.log('editor - hiding textarea');this.editorcore.pushValue();this.el.addClass('x-hidden');this.el.dom.setAttribute('tabIndex',-1);for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.show();
-this.toolbars[i].footer.show();}}}this.setSize(this.wrap.getSize());this.onResize(this.wrap.getSize().width,this.wrap.getSize().height);this.fireEvent('editmodechange',this,this.editorcore.sourceEditMode);},adjustSize:Roo.BoxComponent.prototype.adjustSize,getResizeEl:function(){return this.wrap;
-},getPositionEl:function(){return this.wrap;},initEvents:function(){this.originalValue=this.getValue();},markInvalid:Roo.emptyFn,clearInvalid:Roo.emptyFn,setValue:function(v){Roo.form.HtmlEditor.superclass.setValue.call(this,v);this.editorcore.pushValue();
-},deferFocus:function(){this.focus.defer(10,this);},focus:function(){this.editorcore.focus();},onDestroy:function(){if(this.rendered){for(var i=0;i<this.toolbars.length;i++){this.toolbars[i].onDestroy();}this.wrap.dom.innerHTML='';this.wrap.remove();}},onFirstFocus:function(){this.editorcore.onFirstFocus();
+:A.toolbars[i],Roo.form.HtmlEditor);A.toolbars[i].init(A);}},getSelectedNode:function(){if(this.toolbars.length<2||!this.toolbars[1].tb){return false;}return this.toolbars[1].tb.selectedNode;},onRender:function(ct,A){var _t=this;Roo.form.HtmlEditor.superclass.onRender.call(this,ct,A);
+this.wrap=this.el.wrap({cls:'x-html-editor-wrap',cn:{cls:'x-html-editor-tb'}});this.editorcore.onRender(ct,A);if(this.resizable){this.resizeEl=new Roo.Resizable(this.wrap,{pinned:true,wrap:true,dynamic:true,minHeight:this.height,height:this.height,handles:this.resizable,width:this.width,listeners:{resize:function(r,w,h){_t.onResize(w,h);
+}}});}this.createToolbar(this);if(!this.width){this.setSize(this.wrap.getSize());}if(this.resizeEl){this.resizeEl.resizeTo.defer(100,this.resizeEl,[this.width,this.height]);}this.keyNav=new Roo.KeyNav(this.el,{"tab":function(e){e.preventDefault();var B=this.getValue();
+var C=this.el.dom.selectionStart;var D=this.el.dom.selectionEnd;if(!e.shiftKey){this.setValue(B.substring(0,C)+"\t"+B.substring(D));this.el.dom.setSelectionRange(D+1,D+1);return;}var f=B.substring(0,C).split("\t");if(f.pop().length!=0){return;}this.setValue(f.join("\t")+B.substring(D));
+this.el.dom.setSelectionRange(C-1,C-1);},"home":function(e){e.preventDefault();var B=this.el.dom.selectionStart;var C=this.getValue().split("\n");if(!C.length){return;}if(e.ctrlKey){this.el.dom.setSelectionRange(0,0);return;}var D=0;for(var i=0;i<C.length;
+i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;}D-=C[i].length;break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);return;}this.el.dom.selectionStart=D;this.el.dom.selectionEnd=B;},"end":function(e){e.preventDefault();var B=this.el.dom.selectionStart;
+var C=this.getValue().split("\n");if(!C.length){return;}if(e.ctrlKey){this.el.dom.setSelectionRange(this.getValue().length,this.getValue().length);return;}var D=0;for(var i=0;i<C.length;i++){D+=C[i].length;if(i!=0){D+=1;}if(D<B){continue;}break;}if(!e.shiftKey){this.el.dom.setSelectionRange(D,D);
+return;}this.el.dom.selectionStart=B;this.el.dom.selectionEnd=D;},scope:this,doRelay:function(B,C,D){return Roo.KeyNav.prototype.doRelay.apply(this,arguments);},forceKeyDown:true});},onResize:function(w,h){Roo.form.HtmlEditor.superclass.onResize.apply(this,arguments);
+var ew=false;var eh=false;if(this.el){if(typeof w=='number'){var aw=w-this.wrap.getFrameWidth('lr');this.el.setWidth(this.adjustWidth('textarea',aw));ew=aw;}if(typeof h=='number'){var A=0;for(var i=0;i<this.toolbars.length;i++){A+=this.toolbars[i].tb.el.getHeight();
+if(this.toolbars[i].footer){A+=this.toolbars[i].footer.el.getHeight();}}var ah=h-this.wrap.getFrameWidth('tb')-A;ah-=5;this.el.setHeight(this.adjustWidth('textarea',ah));var eh=ah;}}Roo.log('onResize:'+[w,h,ew,eh].join(','));this.editorcore.onResize(ew,eh);
+},toggleSourceEdit:function(A){this.editorcore.toggleSourceEdit(A);if(this.editorcore.sourceEditMode){Roo.log('editor - showing textarea');this.editorcore.syncValue();this.el.removeClass('x-hidden');this.el.dom.removeAttribute('tabIndex');this.el.focus();
+this.el.dom.scrollTop=0;for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.hide();this.toolbars[i].footer.hide();}}}else{Roo.log('editor - hiding textarea');this.editorcore.pushValue();
+this.el.addClass('x-hidden');this.el.dom.setAttribute('tabIndex',-1);for(var i=0;i<this.toolbars.length;i++){if(this.toolbars[i] instanceof Roo.form.HtmlEditor.ToolbarContext){this.toolbars[i].tb.show();this.toolbars[i].footer.show();}}}this.setSize(this.wrap.getSize());
+this.onResize(this.wrap.getSize().width,this.wrap.getSize().height);this.fireEvent('editmodechange',this,this.editorcore.sourceEditMode);},adjustSize:Roo.BoxComponent.prototype.adjustSize,getResizeEl:function(){return this.wrap;},getPositionEl:function(){return this.wrap;
+},initEvents:function(){this.originalValue=this.getValue();},markInvalid:Roo.emptyFn,clearInvalid:Roo.emptyFn,setValue:function(v){Roo.form.HtmlEditor.superclass.setValue.call(this,v);this.editorcore.pushValue();},deferFocus:function(){this.focus.defer(10,this);
+},focus:function(){this.editorcore.focus();},onDestroy:function(){if(this.rendered){for(var i=0;i<this.toolbars.length;i++){this.toolbars[i].onDestroy();}this.wrap.dom.innerHTML='';this.wrap.remove();}},onFirstFocus:function(){this.editorcore.onFirstFocus();
 for(var i=0;i<this.toolbars.length;i++){this.toolbars[i].onFirstFocus();}},syncValue:function(){this.editorcore.syncValue();},pushValue:function(){this.editorcore.pushValue();},setStylesheets:function(A){this.editorcore.setStylesheets(A);},removeStylesheets:function(){this.editorcore.removeStylesheets();
 }});
 // Roo/form/HtmlEditor/ToolbarStandard.js
@@ -1186,11 +1202,11 @@ Roo.form.HtmlEditor.ToolbarContext.options={'font-family':[['Helvetica,Arial,san
 this.editorcore=A.editorcore?A.editorcore:A;var B=this.editorcore;var C=B.frameId;var D=this;function btn(id,F,G){var H=C+'-'+id;return {id:H,cmd:id,cls:'x-btn-icon x-edit-'+id,enableToggle:F!==false,scope:B,handler:G||B.relayBtnCmd,clickEvent:'mousedown',tooltip:D.buttonTips[id]||undefined,tabIndex:-1}
 ;}var E=A.wrap.createChild({tag:'div'},A.wrap.dom.firstChild.nextSibling,true);var ty=Roo.form.HtmlEditor.ToolbarContext.types;this.toolbars={};for(var i in ty){this.toolbars[i]=this.buildToolbar(ty[i],i);}this.tb=this.toolbars.BODY;this.tb.el.show();this.buildFooter();
 this.footer.show();A.on('hide',function(){this.footer.hide()},this);A.on('show',function(){this.footer.show()},this);this.rendered=true;A.on('editorevent',this.updateToolbar,this);},updateToolbar:function(A,ev,B){if(ev){ev.stopEvent();}if(!this.editorcore.activated){this.editor.onFirstFocus();
-return;}if(ev&&(ev.type=='mouseup'||ev.type=='click')&&ev.target&&ev.target.tagName!='BODY'){B=ev.target;}Roo.select('.roo-ed-selection',false,this.editorcore.doc).removeClass('roo-ed-selection');var C=this.editorcore.getAllAncestors();var ty=Roo.form.HtmlEditor.ToolbarContext.types;
-if(!B){B=C.length?(C[0]?C[0]:C[1]):this.editorcore.doc.body;B=B?B:this.editorcore.doc.body;B=B.tagName.length?B:this.editorcore.doc.body;}var tn=B.tagName.toUpperCase();var D=this.tb.selectedNode;this.tb.selectedNode=B;var E=tn;var db=false;if(B&&B.hasAttribute('data-block')){db=B;
-}else if(B&&!B.hasAttribute('contenteditable')){var F=Roo.get(B);db=F.findParent('[data-block]');var G=F.findParent('[contenteditable=true]');if(db&&G&&G.tagName!='BODY'){db=false;}}var H=false;if(db){H=Roo.htmleditor.Block.factory(db);if(H){db.className+=' roo-ed-selection';
-tn='BLOCK.'+db.getAttribute('data-block');if(typeof(this.toolbars[tn])=='undefined'){this.toolbars[tn]=this.buildToolbar(false,tn,H.friendly_name,H);}this.toolbars[tn].selectedNode=db;E=H.friendly_name;C=this.editorcore.getAllAncestors();}}if(this.tb.name==tn&&D==this.tb.selectedNode&&ev!==false){return;
-}this.tb.el.hide();this.tb=typeof(this.toolbars[tn])!='undefined'?this.toolbars[tn]:this.toolbars['*'];this.tb.el.show();this.tb.items.first().el.innerHTML=E+':&nbsp;';if(H&&this.tb.fields){this.tb.fields.each(function(e){e.setValue(H[e.name]);});}else if(this.tb.fields&&this.tb.selectedNode){this.tb.fields.each(function(e){if(e.stylename){e.setValue(this.tb.selectedNode.style[e.stylename]);
+return;}if(ev&&(ev.type=='mouseup'||ev.type=='click')&&ev.target&&ev.target.tagName!='BODY'){B=ev.target;}Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e){e.classList.remove('roo-ed-selection');});var C=this.editorcore.getAllAncestors();
+var ty=Roo.form.HtmlEditor.ToolbarContext.types;if(!B){B=C.length?(C[0]?C[0]:C[1]):this.editorcore.doc.body;B=B?B:this.editorcore.doc.body;B=B.tagName.length?B:this.editorcore.doc.body;}var tn=B.tagName.toUpperCase();var D=this.tb.selectedNode;this.tb.selectedNode=B;
+var E=tn;var db=false;if(B&&B.hasAttribute('data-block')){db=B;}else if(B&&B.closest('[data-block]')){db=B.closest('[data-block]');}var F=false;if(db&&this.editorcore.enableBlocks){F=Roo.htmleditor.Block.factory(db);if(F){db.className=(db.classList.length>0?db.className+' ':'')+'roo-ed-selection';
+tn='BLOCK.'+db.getAttribute('data-block');if(typeof(this.toolbars[tn])=='undefined'){this.toolbars[tn]=this.buildToolbar(false,tn,F.friendly_name,F);}this.toolbars[tn].selectedNode=db;E=F.friendly_name;C=this.editorcore.getAllAncestors();}}if(this.tb.name==tn&&D==this.tb.selectedNode&&ev!==false){return;
+}this.tb.el.hide();this.tb=typeof(this.toolbars[tn])!='undefined'?this.toolbars[tn]:this.toolbars['*'];this.tb.el.show();this.tb.items.first().el.innerHTML=E+':&nbsp;';if(F&&this.tb.fields){this.tb.fields.each(function(e){e.setValue(F[e.name]);});}else if(this.tb.fields&&this.tb.selectedNode){this.tb.fields.each(function(e){if(e.stylename){e.setValue(this.tb.selectedNode.style[e.stylename]);
 return;}e.setValue(this.tb.selectedNode.getAttribute(e.attrname));},this);this.updateToolbarStyles(this.tb.selectedNode);}Roo.menu.MenuMgr.hideAll();this.updateFooter(C);},updateToolbarStyles:function(A){var B=false;for(var i in this.styles){B=true;break;
 }if(B&&this.tb.hasStyles){var st=this.tb.fields.item(0);st.store.removeAll();var cn=A.className.split(/\s+/);var C=[];if(this.styles['*']){Roo.each(this.styles['*'],function(v){C.push([v,cn.indexOf(v)>-1?1:0]);});}if(this.styles[tn]){Roo.each(this.styles[tn],function(v){C.push([v,cn.indexOf(v)>-1?1:0]);
 });}st.store.loadData(C);st.collapse();st.setValue(cn);}},updateFooter:function(A){var B='';if(A===false){this.footDisp.dom.innerHTML='';return;}this.footerEls=A.reverse();Roo.each(this.footerEls,function(a,i){if(!a){return;}B+=B.length?' &gt; ':'';B+='<span class="x-ed-loc-'+i+'">'+a.tagName+'</span>';
@@ -1199,15 +1215,14 @@ if(A.menu.el){A.menu.el.destroy();}}A.destroy();});}},onFirstFocus:function(){th
 var tb=new Roo.Toolbar(F);if(A===false&&C){A=C.contextMenu(this);}tb.hasStyles=false;tb.name=nm;tb.add((typeof(B)=='undefined'?nm:B)+":&nbsp;");var G=Array.from(this.styles);if(G&&G.length){tb.hasStyles=true;tb.addField(new Roo.form.ComboBox({store:new Roo.data.SimpleStore({id:'val',fields:['val','selected'],data:[]}
 ),name:'-roo-edit-className',attrname:'className',displayField:'val',typeAhead:false,mode:'local',editable:false,triggerAction:'all',emptyText:'Select Style',selectOnFocus:true,width:130,listeners:{'select':function(c,r,i){tb.selectedNode.className=r?r.get('val'):'';
 E.syncValue();}}}));}var H=Roo.form.HtmlEditor.ToolbarContext;for(var i=0;i<A.length;i++){if(typeof(A[i].xtype)!='undefined'){tb[typeof(A[i].name)=='undefined'?'add':'addField'](Roo.factory(A[i]));continue;}var I=A[i];tb.add(I.title+":&nbsp;");var J=I.opts?I.opts:false;
-if(I.optname){J=Roo.form.HtmlEditor.ToolbarContext.options[I.optname];}if(J){tb.addField(new Roo.form.ComboBox({store:typeof(H.stores[i])!='undefined'?Roo.factory(H.stores[i],Roo.data):new Roo.data.SimpleStore({id:'val',fields:['val','display'],data:J}),name:'-roo-edit-'+A[i].name,attrname:A[i].name,stylename:I.style?I.style:false,displayField:I.displayField?I.displayField:'val',valueField:'val',typeAhead:false,mode:typeof(H.stores[A[i].name])!='undefined'?'remote':'local',editable:false,triggerAction:'all',emptyText:'Select',selectOnFocus:true,width:I.width?I.width:130,listeners:{'select':function(c,r,i){if(tb.selectedNode.hasAttribute('data-block')){var b=Roo.htmleditor.Block.factory(tb.selectedNode);
-b[c.attrname]=r.get('val');b.updateElement(tb.selectedNode);E.syncValue();return;}if(c.stylename){tb.selectedNode.style[c.stylename]=r.get('val');E.syncValue();return;}if(r===false){tb.selectedNode.removeAttribute(c.attrname);E.syncValue();return;}tb.selectedNode.setAttribute(c.attrname,r.get('val'));
-E.syncValue();}}}));continue;}tb.addField(new Roo.form.TextField({name:'-roo-edit-'+A[i].name,attrname:A[i].name,width:I.width,value:'',listeners:{'change':function(f,nv,ov){if(tb.selectedNode.hasAttribute('data-block')){var b=Roo.htmleditor.Block.factory(tb.selectedNode);
-b[f.attrname]=nv;b.updateElement(tb.selectedNode);E.syncValue();return;}tb.selectedNode.setAttribute(f.attrname,nv);E.syncValue();}}}));}var K=this;if(nm=='BODY'){tb.addSeparator();tb.addButton({text:'Stylesheets',listeners:{click:function(){K.editor.fireEvent('stylesheetsclick',K.editor);
-}}});}tb.addFill();tb.addButton({text:C&&C.deleteTitle?C.deleteTitle:'Remove Block or Formating',listeners:{click:function(){var sn=tb.selectedNode;if(C){sn=Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();}if(!sn){return;}var L=sn.childNodes[0]||sn.nextSibling||sn.previousSibling||sn.parentNode;
-if(sn.hasAttribute('data-block')){L=sn.nextSibling||sn.previousSibling||sn.parentNode;sn.parentNode.removeChild(sn);}else if(sn&&sn.tagName!='BODY'){a=new Roo.htmleditor.FilterKeepChildren({tag:false});a.removeTag(sn);}var M=E.createRange();M.setStart(L,0);
-M.setEnd(L,0);var N=E.getSelection();N.removeAllRanges();N.addRange(M);K.updateToolbar(null,null,null);K.updateFooter(false);}}});tb.el.on('click',function(e){e.preventDefault();});tb.el.setVisibilityMode(Roo.Element.DISPLAY);tb.el.hide();return tb;},buildFooter:function(){var A=this.editor.wrap.createChild();
-this.footer=new Roo.Toolbar(A);var B=new Roo.Toolbar.Fill();var _t=this;this.footer.add({text:'&lt;',xtype:'Button',handler:function(){_t.footDisp.scrollTo('left',0,true)}});this.footer.add(B);this.footer.add({text:'&gt;',xtype:'Button',handler:function(){_t.footDisp.select('span').last().scrollIntoView(_t.footDisp,true);
-}});var A=Roo.get(B.el);A.addClass('x-editor-context');this.footDispWrap=A;this.footDispWrap.overflow='hidden';this.footDisp=A.createChild();this.footDispWrap.on('click',this.onContextClick,this)},onContextClick:function(ev,A){ev.preventDefault();var cn=A.className;
+if(I.optname){J=Roo.form.HtmlEditor.ToolbarContext.options[I.optname];}if(J){tb.addField(new Roo.form.ComboBox({store:typeof(H.stores[i])!='undefined'?Roo.factory(H.stores[i],Roo.data):new Roo.data.SimpleStore({id:'val',fields:['val','display'],data:J}),name:'-roo-edit-'+A[i].name,attrname:A[i].name,stylename:I.style?I.style:false,displayField:I.displayField?I.displayField:'val',valueField:'val',typeAhead:false,mode:typeof(H.stores[A[i].name])!='undefined'?'remote':'local',editable:false,triggerAction:'all',emptyText:'Select',selectOnFocus:true,width:I.width?I.width:130,listeners:{'select':function(c,r,i){if(c.stylename){tb.selectedNode.style[c.stylename]=r.get('val');
+E.syncValue();return;}if(r===false){tb.selectedNode.removeAttribute(c.attrname);E.syncValue();return;}tb.selectedNode.setAttribute(c.attrname,r.get('val'));E.syncValue();}}}));continue;}tb.addField(new Roo.form.TextField({name:'-roo-edit-'+A[i].name,attrname:A[i].name,width:I.width,value:'',listeners:{'change':function(f,nv,ov){tb.selectedNode.setAttribute(f.attrname,nv);
+E.syncValue();}}}));}var K=this;var L=!C||C.deleteTitle!==false;if(nm=='BODY'){L=false;tb.addSeparator();tb.addButton({text:'Stylesheets',listeners:{click:function(){K.editor.fireEvent('stylesheetsclick',K.editor);}}});}tb.addFill();if(L){tb.addButton({text:C&&C.deleteTitle?C.deleteTitle:'Remove Block or Formating',listeners:{click:function(){var sn=tb.selectedNode;
+if(C){sn=Roo.htmleditor.Block.factory(tb.selectedNode).removeNode();}if(!sn){return;}var M=sn.childNodes[0]||sn.nextSibling||sn.previousSibling||sn.parentNode;if(sn.hasAttribute('data-block')){M=sn.nextSibling||sn.previousSibling||sn.parentNode;sn.parentNode.removeChild(sn);
+}else if(sn&&sn.tagName!='BODY'){a=new Roo.htmleditor.FilterKeepChildren({tag:false});a.replaceTag(sn);}var N=E.createRange();N.setStart(M,0);N.setEnd(M,0);var O=E.getSelection();O.removeAllRanges();O.addRange(N);K.updateToolbar(null,null,null);K.updateFooter(false);
+}}});}tb.el.on('click',function(e){e.preventDefault();});tb.el.setVisibilityMode(Roo.Element.DISPLAY);tb.el.hide();return tb;},buildFooter:function(){var A=this.editor.wrap.createChild();this.footer=new Roo.Toolbar(A);var B=new Roo.Toolbar.Fill();var _t=this;
+this.footer.add({text:'&lt;',xtype:'Button',handler:function(){_t.footDisp.scrollTo('left',0,true)}});this.footer.add(B);this.footer.add({text:'&gt;',xtype:'Button',handler:function(){_t.footDisp.select('span').last().scrollIntoView(_t.footDisp,true);}});
+var A=Roo.get(B.el);A.addClass('x-editor-context');this.footDispWrap=A;this.footDispWrap.overflow='hidden';this.footDisp=A.createChild();this.footDispWrap.on('click',this.onContextClick,this)},onContextClick:function(ev,A){ev.preventDefault();var cn=A.className;
 if(!cn.match(/x-ed-loc-/)){return;}var n=cn.split('-').pop();var B=this.footerEls;var C=B[n];this.editorcore.selectNode(C);this.updateToolbar(null,null,C);}});
 // Roo/form/BasicForm.js
 Roo.form.BasicForm=function(el,A){this.allItems=[];this.childForms=[];Roo.apply(this,A);this.items=new Roo.util.MixedCollection(false,function(o){return o.id||(o.id=Roo.id());});this.addEvents({beforeaction:true,actionfailed:true,actioncomplete:true});if(el){this.initEl(el);