roojs-bootstrap.js
authorAlan <alan@roojs.com>
Thu, 16 Feb 2023 07:33:36 +0000 (15:33 +0800)
committerAlan <alan@roojs.com>
Thu, 16 Feb 2023 07:33:36 +0000 (15:33 +0800)
roojs-bootstrap-debug.js

roojs-bootstrap-debug.js
roojs-bootstrap.js

index 1585f7b..f48e5d6 100644 (file)
@@ -15176,8 +15176,8 @@ Roo.data.Store = function(config){
          * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
          * 
          * @param {Proxy} 
-         * @param {Object} return from JsonData.reader() - success, totalRecords, records
-         * @param {Object} load options 
+         * @param {Object} ret return data from JsonData.reader() - success, totalRecords, records
+         * @param {Object} opts - load Options
          * @param {Object} jsonData from your request (normally this contains the Exception)
          */
         loadexception : true
@@ -16183,24 +16183,24 @@ Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
     // thse are take from connection...
     
     /**
-     * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
+     * @cfg {String} url  The default URL to be used for requests to the server. (defaults to undefined)
      */
     /**
-     * @cfg {Object} extraParams (Optional) An object containing properties which are used as
+     * @cfg {Object} extraParams  An object containing properties which are used as
      * extra parameters to each request made by this object. (defaults to undefined)
      */
     /**
-     * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
+     * @cfg {Object} defaultHeaders   An object containing request headers which are added
      *  to each request made by this object. (defaults to undefined)
      */
     /**
-     * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
+     * @cfg {String} method (GET|POST)  The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
      */
     /**
-     * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
+     * @cfg {Number} timeout The timeout in milliseconds to be used for requests. (defaults to 30000)
      */
      /**
-     * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
+     * @cfg {Boolean} autoAbort Whether this request should abort any pending requests. (defaults to false)
      * @type Boolean
      */
   
@@ -32616,22 +32616,23 @@ Roo.extend(Roo.bootstrap.form.HtmlEditor, Roo.bootstrap.form.TextArea,  {
             return;
         }
         if (this.toolbars === true) {
-            this.toolbars = [
-                new Roo.bootstrap.form.HtmlEditorToolbar.Standard({editor: this} )
-            ];
+            this.toolbars = [ 'Standard' ];
         }
         
         var ar = Array.from(this.toolbars);
         this.toolbars = [];
         ar.forEach(function(t,i) {
             if (typeof(t) == 'string') {
-                t = new Roo.bootstrap.form.HtmlEditorToolbar[t]({editor : this});
+                t = {
+                    xtype : t
+                };
             }
             if (typeof(t) == 'object' && typeof(t.xtype) == 'string') {
                 t.editor = this;
                 t.xns = t.xns || Roo.bootstrap.form.HtmlEditorToolbar;
                 t = Roo.factory(t);
             }
+            this.toolbars[i] = t;
             this.toolbars[i].render(this.toolbarContainer());
         }, this);
         
@@ -32910,7 +32911,7 @@ Roo.bootstrap.form.HtmlEditorToolbar.Standard = function(config)
     this.editor = config.editor;
     this.editorcore = config.editor.editorcore;
     
-    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
+    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.btnid; });
     
     //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
     // dont call parent... till later.
@@ -32931,6 +32932,9 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
         'div','span'
     ],
     
+    
+    deleteBtn: false,
+    
     onRender : function(ct, position)
     {
        // Roo.log("Call onRender: " + this.xtype);
@@ -32943,7 +32947,7 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
        var editor= this.editor;
        
        var children = [];
-       var btn = function(id,cmd , toggle, handler, html){
+       var btn = function(id, cmd , toggle, handler, html){
        
             var  event = toggle ? 'toggle' : 'click';
        
@@ -32952,9 +32956,10 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
                 xtype: 'Button',
                 xns: Roo.bootstrap,
                 //glyphicon : id,
+                btnid : id,
                 fa: id,
-                cmd : id || cmd,
-                enableToggle:toggle !== false,
+                cmd : cmd, // why id || cmd
+                enableToggle: toggle !== false,
                 html : html || '',
                 pressed : toggle ? false : null,
                 listeners : {}
@@ -32998,13 +33003,13 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
         });
         children.push(style);   
         
-        btn('bold',false,true);
-        btn('italic',false,true);
-        btn('align-left', 'justifyleft',true);
+        btn('bold',         false,true);
+        btn('italic',       false,true);
+        btn('align-left',   'justifyleft',true);
         btn('align-center', 'justifycenter',true);
         btn('align-right' , 'justifyright',true);
-        btn('link', false, false, function(btn) {
-            //Roo.log("create link?");
+        btn('link', false, true, function(btn) {
+            
             var url = prompt(this.createLinkText, this.defaultLinkValue);
             if(url && url != 'http:/'+'/'){
                 this.editorcore.relayCmd('createlink', url);
@@ -33024,47 +33029,43 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
             }
         }
         
-        /*
-        var cog = {
-                xtype: 'Button',
-                size : 'sm',
-                xns: Roo.bootstrap,
-                glyphicon : 'cog',
-                //html : 'submit'
-                menu : {
-                    xtype: 'Menu',
-                    xns: Roo.bootstrap,
-                    items:  []
-                }
-        };
-        
-        cog.menu.items.push({
-            xtype :'MenuItem',
-            xns: Roo.bootstrap,
-            html : Clean styles,
-            tagname : f,
-            listeners : {
-                click : function()
-                {
-                    editorcore.insertTag(this.tagname);
-                    editor.focus();
-                }
-            }
-            
-        });
-       */
         
          
-       this.xtype = 'NavSimplebar';
+        this.xtype = 'NavSimplebar'; // why?
         
         for(var i=0;i< children.length;i++) {
             
             this.buttons.add(this.addxtypeChild(children[i]));
             
         }
-        
+        this.buildToolbarDelete();
+
         editor.on('editorevent', this.updateToolbar, this);
     },
+    
+    buildToolbarDelete : function()
+    {
+        
+       /* this.addxtypeChild({
+            xtype : 'Element',
+            xns : Roo.bootstrap,
+            cls : 'roo-htmleditor-fill'
+        });
+        */
+        this.deleteBtn = this.addxtypeChild({
+            size : 'sm',
+            xtype: 'Button',
+            xns: Roo.bootstrap,
+            fa: 'trash',
+            listeners : {
+                click : this.onDelete.createDelegate(this)
+            }
+        });
+        this.deleteBtn.hide();     
+        
+    },
+    
+    
     onBtnClick : function(id)
     {
        this.editorcore.relayCmd(id);
@@ -33075,7 +33076,7 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
      * Protected method that will not generally be called directly. It triggers
      * a toolbar update by reading the markup state of the current selection in the editor.
      */
-    updateToolbar: function(){
+    updateToolbar: function(editor ,ev, sel){
 
         if(!this.editorcore.activated){
             this.editor.onFirstFocus(); // is this neeed?
@@ -33084,39 +33085,45 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
 
         var btns = this.buttons; 
         var doc = this.editorcore.doc;
-        btns.get('bold').setActive(doc.queryCommandState('bold'));
-        btns.get('italic').setActive(doc.queryCommandState('italic'));
-        //btns.get('underline').setActive(doc.queryCommandState('underline'));
-        
-        btns.get('align-left').setActive(doc.queryCommandState('justifyleft'));
-        btns.get('align-center').setActive(doc.queryCommandState('justifycenter'));
-        btns.get('align-right').setActive(doc.queryCommandState('justifyright'));
+        var hasToggle  = false;
+        btns.each(function(e) {
+            if (e.enableToggle && e.cmd) {
+                hasToggle = hasToggle  || doc.queryCommandState(e.cmd);
+                e.setActive(doc.queryCommandState(e.cmd));
+            }
+        }, this);
         
-        //btns[frameId + '-insertorderedlist').setActive(doc.queryCommandState('insertorderedlist'));
-        btns.get('list').setActive(doc.queryCommandState('insertunorderedlist'));
-         /*
         
-        var ans = this.editorcore.getAllAncestors();
-        if (this.formatCombo) {
-            
+        if (ev &&
+            (ev.type == 'mouseup' || ev.type == 'click' ) &&
+            ev.target && ev.target.tagName != 'BODY' ) { // && ev.target.tagName == 'IMG') {
+            // they have click on an image...
+            // let's see if we can change the selection...
+            sel = ev.target;
             
-            var store = this.formatCombo.store;
-            this.formatCombo.setValue("");
-            for (var i =0; i < ans.length;i++) {
-                if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
-                    // select it..
-                    this.formatCombo.setValue(ans[i].tagName.toLowerCase());
-                    break;
-                }
+        }
+        var tn = sel && sel.tagName.toUpperCase() || '';
+        if (sel && tn != 'A') {
+            var asel = sel.closest('A');
+            if (asel) {
+                sel = asel;
             }
         }
+       
+        btns.get('link').setActive(tn == 'A');
+        
+        Roo.bootstrap.menu.Manager.hideAll();
+        
+        // handle delete button..
+        if (hasToggle || (tn.length && tn == 'BODY')) {
+            this.deleteBtn.hide();
+            return;
+            
+        }
+        this.deleteBtn.show();
         
         
         
-        // hides menus... - so this cant be on a menu...
-        Roo.bootstrap.MenuMgr.hideAll();
-        */
-        Roo.bootstrap.menu.Manager.hideAll();
         //this.editorsyncValue();
     },
     onFirstFocus: function() {
@@ -33124,6 +33131,46 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
            item.enable();
         });
     },
+    
+    onDelete : function()
+    {
+        var range = this.editorcore.createRange();
+        var selection = this.editorcore.getSelection();
+        var sn = this.selectedNode;
+        range.setStart(sn,0);
+        range.setEnd(sn,0); 
+        
+        
+        if (sn.hasAttribute('data-block')) {
+            var block = Roo.htmleditor.Block.factory(tb.selectedNode);
+            if (block) {
+                block.removeNode();
+                selection.removeAllRanges();
+                selection.addRange(range);
+                this.updateToolbar(null, null, null);
+            }   
+             
+        }
+        if (!sn) {
+            return; // should not really happen..
+        }
+        if (sn && sn.tagName == 'BODY') {
+            return;
+        }
+        var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
+        
+        // remove and keep parents.
+        a = new Roo.htmleditor.FilterKeepChildren({tag : false});
+        a.replaceTag(sn);
+        
+        selection.removeAllRanges();
+        selection.addRange(range);
+        this.editorcore.fireEditorEvent(false);
+        
+        
+    },
+    
+    
     toggleSourceEdit : function(sourceEditMode){
         
           
@@ -33154,7 +33201,498 @@ Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simp
 
 
 
+  
+/**
+ * @class Roo.bootstrap.form.HtmlEditorToolbar.Context
+ * @parent Roo.bootstrap.form.HtmlEditor
+ * @extends Roo.bootstrap.nav.Simplebar
+ * Basic Toolbar
+ * 
+ * @example
+ * Usage:
+ *
+ new Roo.bootstrap.form.HtmlEditor({
+    ....
+    toolbars : [
+        {
+            xtyle: 'Standard',
+            disable : { fonts: 1 , format: 1, ..., ... , ...],
+            btns : [ .... ]
+        },
+        {
+            xtyle : 'Context',
+            ....
+        }
+    }
+     
+ * 
+ * 
+ */
  
+Roo.bootstrap.form.HtmlEditorToolbar.Context = function(config)
+{
+    
+    Roo.apply(this, config);
+    
+    
+    Roo.bootstrap.form.HtmlEditorToolbar.Context.superclass.constructor.call(this, config);
+    
+    this.editor = config.editor;
+    this.editorcore = config.editor.editorcore;
+    
+    this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.cmd; });
+    
+}
+
+Roo.bootstrap.form.HtmlEditorToolbar.Context.types = {
+    'IMG' : [
+        {
+            name : 'width',
+            title: "Width",
+            width: 40
+        },
+        {
+            name : 'height',
+            title: "Height",
+            width: 40
+        },
+        {
+            name : 'align',
+            title: "Align",
+            opts : [ [""],[ "left"],[ "right"],[ "center"],[ "top"]],
+            width : 80
+            
+        },
+        {
+            name : 'border',
+            title: "Border",
+            width: 40
+        },
+        {
+            name : 'alt',
+            title: "Alt",
+            width: 120
+        },
+        {
+            name : 'src',
+            title: "Src",
+            width: 220
+        }
+        
+    ],
+    
+    /*
+    'A' : [
+        {
+            name : 'name',
+            title: "Name",
+            width: 50
+        },
+        {
+            name : 'target',
+            title: "Target",
+            width: 120
+        },
+        {
+            name : 'href',
+            title: "Href",
+            width: 220
+        } // border?
+        
+    ],
+    */
+    /*
+    'INPUT' : [
+        {
+            name : 'name',
+            title: "name",
+            width: 120
+        },
+        {
+            name : 'value',
+            title: "Value",
+            width: 120
+        },
+        {
+            name : 'width',
+            title: "Width",
+            width: 40
+        }
+    ],
+    'LABEL' : [
+         {
+            name : 'for',
+            title: "For",
+            width: 120
+        }
+    ],
+    'TEXTAREA' : [
+        {
+            name : 'name',
+            title: "name",
+            width: 120
+        },
+        {
+            name : 'rows',
+            title: "Rows",
+            width: 20
+        },
+        {
+            name : 'cols',
+            title: "Cols",
+            width: 20
+        }
+    ],
+    'SELECT' : [
+        {
+            name : 'name',
+            title: "name",
+            width: 120
+        },
+        {
+            name : 'selectoptions',
+            title: "Options",
+            width: 200
+        }
+    ],
+    
+    // should we really allow this??
+    // should this just be 
+    'BODY' : [
+        
+        {
+            name : 'title',
+            title: "Title",
+            width: 200,
+            disabled : true
+        }
+    ],
+    */
+    '*' : [
+        // empty.
+    ]
+
+};
+
+Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Context, Roo.bootstrap.nav.Simplebar,  {
+    
+    editor : false,
+    editorcore : false,
+    buttons : false,
+    
+    button_groups : false, // subtoolbars...  - buttson?
+    active_group : false,
+    
+    selectedNode : false,
+    
+    onRender : function(ct, position)
+    {
+       // Roo.log("Call onRender: " + this.xtype);
+        
+        this.constructor.superclass.onRender.call(this, ct, position);
+       
+        
+         
+        
+          
+        // disable everything...
+        var ty = this.constructor.types;
+        this.button_groups = {};
+        // block toolbars are built in updateToolbar when needed.
+        for (var i in  ty) {
+            this.button_groups[i] = this.buildToolbarGroup(ty[i],i);
+        }
+        this.buildToolbarDelete();
+          this.hide();
+        // the all the btns;
+        this.editor.on('editorevent', this.updateToolbar, this);
+        
+    },
+    onFirstFocus: function() {
+       
+    },
+    
+    
+    buildToolbarGroup: function(tlist, key )
+    {
+        var editor = this.editor;
+        var editorcore = this.editorcore;
+        var tb = this;
+       
+        var ret = [];
+         
+        for (var i = 0; i < tlist.length; i++) {
+            
+            // newer versions will use xtype cfg to create menus.
+            if (typeof(tlist[i].xtype) != 'undefined') {
+                tb[typeof(tlist[i].name)== 'undefined' ? 'add' : 'addField'](Roo.factory(tlist[i]));
+                continue;
+            }
+            
+            var item = tlist[i];
+            ret.push(
+                this.addxtypeChild({
+                    xtype : 'Element',
+                    xns : Roo.bootstrap,
+                    cls : 'roo-htmleditor-context-label-' + key + '-' + item.name,
+                    html : item.title
+                })  
+            );
+            
+            // add a text entry!?
+            ret.push(
+                this.addxtypeChild({
+                    xtype : 'Input',
+                    xns : Roo.bootstrap.form,
+                    cls : 'roo-htmleditor-context-entry-' + key + '-' + item.name,
+                    name: '-roo-edit-' + item.name,
+                    attrname : item.name,
+                    width: item.width,
+                    //allowBlank:true,
+                    value: '',
+                    listeners: {
+                        'change' : function(f, nv, ov) {
+                            tb.selectedNode.setAttribute(f.attrname, nv);
+                            editorcore.syncValue();
+                        }
+                    }
+                })
+            );
+                
+        }
+        // hide them all..
+        ret.forEach(function(e) {
+            e.hide();
+        });
+        ret.name = key;
+        
+        return ret;
+    },
+    buildToolbarDelete : function()
+    {
+        
+        this.addxtypeChild({
+            xtype : 'Element',
+            xns : Roo.bootstrap,
+            cls : 'roo-htmleditor-fill'
+        });
+        
+        this.deleteBtn = this.addxtypeChild({
+            size : 'sm',
+            xtype: 'Button',
+            xns: Roo.bootstrap,
+            fa: 'trash',
+            listeners : {
+                click : this.onDelete.createDelegate(this)
+            }
+        });
+        this.deleteBtn.hide();     
+        
+    },
+    
+    
+    onDelete : function()
+    {
+        var range = this.editorcore.createRange();
+        var selection = this.editorcore.getSelection();
+        var sn = this.selectedNode;
+        range.setStart(sn,0);
+        range.setEnd(sn,0); 
+        
+        
+        if (sn.hasAttribute('data-block')) {
+            var block = Roo.htmleditor.Block.factory(tb.selectedNode);
+            if (block) {
+                block.removeNode();
+                selection.removeAllRanges();
+                selection.addRange(range);
+                this.updateToolbar(null, null, null);
+            }   
+             
+        }
+        if (!sn) {
+            return; // should not really happen..
+        }
+        if (sn && sn.tagName == 'BODY') {
+            return;
+        }
+        var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
+        
+        // remove and keep parents.
+        a = new Roo.htmleditor.FilterKeepChildren({tag : false});
+        a.replaceTag(sn);
+        
+        selection.removeAllRanges();
+        selection.addRange(range);
+        this.editorcore.fireEditorEvent(false);
+        
+        
+    },
+    /**
+     * Protected method that will not generally be called directly. It triggers
+     * a toolbar update by reading the markup state of the current selection in the editor.
+     *
+     * Note you can force an update by calling on('editorevent', scope, false)
+     */
+    updateToolbar: function(editor ,ev, sel)
+    {
+        var ty = this.constructor.types;
+        
+        
+        if (ev) {
+            ev.stopEvent(); // se if we can stop this looping with mutiple events.
+        }
+        
+         
+        // capture mouse up - this is handy for selecting images..
+        // perhaps should go somewhere else...
+        if(!this.editorcore.activated){
+            this.editor.onFirstFocus();
+            return;
+        }
+        //Roo.log(ev ? ev.target : 'NOTARGET');
+        
+        
+        // http://developer.yahoo.com/yui/docs/simple-editor.js.html
+        // selectNode - might want to handle IE?
+         
+        if (ev &&
+            (ev.type == 'mouseup' || ev.type == 'click' ) &&
+            ev.target && ev.target.tagName != 'BODY' ) { // && ev.target.tagName == 'IMG') {
+            // they have click on an image...
+            // let's see if we can change the selection...
+            sel = ev.target;
+           
+             
+        }
+        
+        // this forces an id..
+        Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e) {
+            e.classList.remove('roo-ed-selection');
+        });
+          
+        var ans = this.editorcore.getAllAncestors();
+        
+               
+        if (!sel) { 
+            sel = ans.length ? (ans[0] ?  ans[0]  : ans[1]) : this.editorcore.doc.body;
+            sel = sel ? sel : this.editorcore.doc.body;
+            sel = sel.tagName.length ? sel : this.editorcore.doc.body;
+            
+        }
+        
+        var tn = sel.tagName.toUpperCase();
+        var lastSel = this.selectedNode;
+        this.selectedNode = sel;
+        var left_label = tn;
+        
+        // ok see if we are editing a block?
+        
+        var db = false;
+        // you are not actually selecting the block.
+        if (sel && sel.hasAttribute('data-block')) {
+            db = sel;
+        } else if (sel && sel.closest('[data-block]')) {
+            
+            db = sel.closest('[data-block]');
+             
+        }
+        
+        
+        var block = false;
+        if (db && this.editorcore.enableBlocks) {
+            block = Roo.htmleditor.Block.factory(db);
+            
+            
+            if (block) {
+                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);
+                if (typeof(this.button_groups[tn]) == 'undefined') {
+                   this.button_groups[tn] = this.buildBlockToolbar( block );
+                }
+                this.selectedNode = db;
+                left_label = block.friendly_name;
+                ans = this.editorcore.getAllAncestors();
+            }
+              
+            
+        }
+        
+        
+        if ( this.active_group !== false && this.active_group.name == tn && lastSel == this.selectedNode && ev !== false) {
+            return; // no change?
+        }
+        
+        if (tn == 'BODY') {
+            this.deleteBtn.hide();
+            this.hide();
+            this.hideActiveGroup();
+            return;
+            
+        }
+        
+        
+        if (this.active_group) {
+            this.hideActiveGroup();
+        }
+        this.showActiveGroup(tn);
+        this.show();
+        this.deleteBtn.show();
+        
+    },
+    hideActiveGroup : function()
+    {
+        this.hide();
+        if (this.active_group === false) {
+            return;
+        }
+        this.active_group.forEach(function(e) {
+            e.hide();
+        });
+        this.active_group = false;
+    },
+    showActiveGroup : function(tn)
+    {
+        
+        if (typeof(this.button_groups[tn]) == 'undefined') {
+            
+            return;
+        }
+        
+        this.active_group = this.button_groups[tn];
+        
+        this.active_group.forEach(function(e) {
+            e.show();
+        });
+        
+        // update attributes
+        if (this.selectedNode.hasAttribute('data-block') ) {
+            var block = Roo.htmleditor.Block.factory(this.selectedNode);
+            this.active_group.forEach(function(e) {
+                e.setValue(this.selectedNode.getAttribute(block[e.name]));
+            }, this);
+                
+            return;
+            
+        }
+        // based on attributes...
+        this.active_group.forEach(function(e) {
+            if (typeof(e.attrname) == 'undefined') {
+                return;
+            }
+             e.setValue(this.selectedNode.getAttribute(e.attrname));
+        }, this);
+        
+            
+    }
+    
+}); 
 /*
  * - LGPL
  */
index ef8cca5..6490cb9 100644 (file)
@@ -1402,28 +1402,50 @@ Roo.HtmlEditorCore.tag_remove=['FONT','TBODY'];Roo.HtmlEditorCore.ablack=['on'];
 // Roo/bootstrap/form/HtmlEditor.js
 Roo.bootstrap.form.HtmlEditor=function(A){Roo.bootstrap.form.HtmlEditor.superclass.constructor.call(this,A);if(!this.toolbars){this.toolbars=[];}this.editorcore=new Roo.HtmlEditorCore(Roo.apply({owner:this},A));this.addEvents({initialize:true,activate:true,beforesync:true,beforepush:true,sync:true,push:true,editmodechange:true,editorevent:true,firstfocus:true,autosave:true,savedpreview:true}
 );};Roo.extend(Roo.bootstrap.form.HtmlEditor,Roo.bootstrap.form.TextArea,{toolbars:true,btns:[],resize:false,height:300,width:false,stylesheets:false,frameId:false,validationEvent:false,deferHeight:true,initialized:false,activated:false,onFocus:Roo.emptyFn,iframePad:3,hideMode:'offsets',tbContainer:false,bodyCls:'',toolbarContainer:function(){return this.wrap.select('.x-html-editor-tb',true).first();
-},createToolbar:function(){if(this.toolbars===false){return;}if(this.toolbars===true){this.toolbars=[new Roo.bootstrap.form.HtmlEditorToolbar.Standard({editor:this})];}var ar=Array.from(this.toolbars);this.toolbars=[];ar.forEach(function(t,i){if(typeof(t)=='string'){t=new Roo.bootstrap.form.HtmlEditorToolbar[t]({editor:this}
-);}if(typeof(t)=='object'&&typeof(t.xtype)=='string'){t.editor=this;t.xns=t.xns||Roo.bootstrap.form.HtmlEditorToolbar;t=Roo.factory(t);}this.toolbars[i].render(this.toolbarContainer());},this);},onRender:function(ct,A){var _t=this;Roo.bootstrap.form.HtmlEditor.superclass.onRender.call(this,ct,A);
-this.wrap=this.inputEl().wrap({cls:'x-html-editor-wrap',cn:{cls:'x-html-editor-tb'}});this.editorcore.onRender(ct,A);this.createToolbar(this);},onResize:function(w,h){Roo.log('resize: '+w+','+h);Roo.bootstrap.form.HtmlEditor.superclass.onResize.apply(this,arguments);
-var ew=false;var eh=false;if(this.inputEl()){if(typeof w=='number'){var aw=w-this.wrap.getFrameWidth('lr');this.inputEl().setWidth(this.adjustWidth('textarea',aw));ew=aw;}if(typeof h=='number'){var A=-11;for(var i=0;i<this.toolbars.length;i++){A+=this.toolbars[i].el.getHeight();
-}var ah=h-this.wrap.getFrameWidth('tb')-A;ah-=5;this.inputEl().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.syncValue();this.inputEl().removeClass(['hide','x-hidden']);this.inputEl().dom.removeAttribute('tabIndex');this.inputEl().focus();}else{Roo.log('editor - hiding textarea');this.pushValue();
-this.inputEl().addClass(['hide','x-hidden']);this.inputEl().dom.setAttribute('tabIndex',-1);}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();},setValue:function(v){Roo.bootstrap.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();}});
+},createToolbar:function(){if(this.toolbars===false){return;}if(this.toolbars===true){this.toolbars=['Standard'];}var ar=Array.from(this.toolbars);this.toolbars=[];ar.forEach(function(t,i){if(typeof(t)=='string'){t={xtype:t};}if(typeof(t)=='object'&&typeof(t.xtype)=='string'){t.editor=this;
+t.xns=t.xns||Roo.bootstrap.form.HtmlEditorToolbar;t=Roo.factory(t);}this.toolbars[i]=t;this.toolbars[i].render(this.toolbarContainer());},this);},onRender:function(ct,A){var _t=this;Roo.bootstrap.form.HtmlEditor.superclass.onRender.call(this,ct,A);this.wrap=this.inputEl().wrap({cls:'x-html-editor-wrap',cn:{cls:'x-html-editor-tb'}
+});this.editorcore.onRender(ct,A);this.createToolbar(this);},onResize:function(w,h){Roo.log('resize: '+w+','+h);Roo.bootstrap.form.HtmlEditor.superclass.onResize.apply(this,arguments);var ew=false;var eh=false;if(this.inputEl()){if(typeof w=='number'){var aw=w-this.wrap.getFrameWidth('lr');
+this.inputEl().setWidth(this.adjustWidth('textarea',aw));ew=aw;}if(typeof h=='number'){var A=-11;for(var i=0;i<this.toolbars.length;i++){A+=this.toolbars[i].el.getHeight();}var ah=h-this.wrap.getFrameWidth('tb')-A;ah-=5;this.inputEl().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.syncValue();this.inputEl().removeClass(['hide','x-hidden']);
+this.inputEl().dom.removeAttribute('tabIndex');this.inputEl().focus();}else{Roo.log('editor - hiding textarea');this.pushValue();this.inputEl().addClass(['hide','x-hidden']);this.inputEl().dom.setAttribute('tabIndex',-1);}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();},setValue:function(v){Roo.bootstrap.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();}});
+
 // Roo/bootstrap/form/HtmlEditorToolbar/Standard.js
 Roo.bootstrap.form.HtmlEditorToolbar.Standard=function(A){Roo.apply(this,A);this.disable=this.disable||{};Roo.applyIf(this.disable,{fontSize:true,colors:true,specialElements:true});Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.constructor.call(this,A);
-this.editor=A.editor;this.editorcore=A.editor.editorcore;this.buttons=new Roo.util.MixedCollection(false,function(o){return o.cmd;});};Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard,Roo.bootstrap.nav.Simplebar,{bar:true,editor:false,editorcore:false,formats:["p","h1","h2","h3","h4","h5","h6","pre","code","abbr","acronym","address","cite","samp","var",'div','span'],onRender:function(ct,A){Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.onRender.call(this,ct,A);
-Roo.log(this.el);this.el.dom.style.marginBottom='0';var B=this;var C=this.editorcore;var D=this.editor;var E=[];var F=function(id,G,H,I,J){var K=H?'toggle':'click';var a={size:'sm',xtype:'Button',xns:Roo.bootstrap,fa:id,cmd:id||G,enableToggle:H!==false,html:J||'',pressed:H?false:null,listeners:{}
+this.editor=A.editor;this.editorcore=A.editor.editorcore;this.buttons=new Roo.util.MixedCollection(false,function(o){return o.btnid;});};Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard,Roo.bootstrap.nav.Simplebar,{bar:true,editor:false,editorcore:false,formats:["p","h1","h2","h3","h4","h5","h6","pre","code","abbr","acronym","address","cite","samp","var",'div','span'],deleteBtn:false,onRender:function(ct,A){Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.onRender.call(this,ct,A);
+Roo.log(this.el);this.el.dom.style.marginBottom='0';var B=this;var C=this.editorcore;var D=this.editor;var E=[];var F=function(id,G,H,I,J){var K=H?'toggle':'click';var a={size:'sm',xtype:'Button',xns:Roo.bootstrap,btnid:id,fa:id,cmd:G,enableToggle:H!==false,html:J||'',pressed:H?false:null,listeners:{}
 };a.listeners[H?'toggle':'click']=function(){I?I.call(B,this):B.onBtnClick.call(B,G||id);};E.push(a);return a;};var style={xtype:'Button',size:'sm',xns:Roo.bootstrap,fa:'font',menu:{xtype:'Menu',xns:Roo.bootstrap,items:[]}};Roo.each(this.formats,function(f){style.menu.items.push({xtype:'MenuItem',xns:Roo.bootstrap,html:'<'+f+' style="margin:2px">'+f+'</'+f+'>',tagname:f,listeners:{click:function(){C.insertTag(this.tagname);
-D.focus();}}});});E.push(style);F('bold',false,true);F('italic',false,true);F('align-left','justifyleft',true);F('align-center','justifycenter',true);F('align-right','justifyright',true);F('link',false,false,function(G){var H=prompt(this.createLinkText,this.defaultLinkValue);
+D.focus();}}});});E.push(style);F('bold',false,true);F('italic',false,true);F('align-left','justifyleft',true);F('align-center','justifycenter',true);F('align-right','justifyright',true);F('link',false,true,function(G){var H=prompt(this.createLinkText,this.defaultLinkValue);
 if(H&&H!='http:/'+'/'){this.editorcore.relayCmd('createlink',H);}}),F('list','insertunorderedlist',true);F('list-ol','insertorderedlist',true);F('pencil',false,true,function(G){Roo.log(this);this.toggleSourceEdit(G.pressed);});if(this.editor.btns.length>0){for(var i=0;
-i<this.editor.btns.length;i++){E.push(this.editor.btns[i]);}}this.xtype='NavSimplebar';for(var i=0;i<E.length;i++){this.buttons.add(this.addxtypeChild(E[i]));}D.on('editorevent',this.updateToolbar,this);},onBtnClick:function(id){this.editorcore.relayCmd(id);
-this.editorcore.focus();},updateToolbar:function(){if(!this.editorcore.activated){this.editor.onFirstFocus();return;}var A=this.buttons;var B=this.editorcore.doc;A.get('bold').setActive(B.queryCommandState('bold'));A.get('italic').setActive(B.queryCommandState('italic'));
-A.get('align-left').setActive(B.queryCommandState('justifyleft'));A.get('align-center').setActive(B.queryCommandState('justifycenter'));A.get('align-right').setActive(B.queryCommandState('justifyright'));A.get('list').setActive(B.queryCommandState('insertunorderedlist'));
-Roo.bootstrap.menu.Manager.hideAll();},onFirstFocus:function(){this.buttons.each(function(A){A.enable();});},toggleSourceEdit:function(A){if(A){Roo.log("disabling buttons");this.buttons.each(function(B){if(B.cmd!='pencil'){B.disable();}});}else{Roo.log("enabling buttons");
-if(this.editorcore.initialized){this.buttons.each(function(B){B.enable();});}}Roo.log("calling toggole on editor");this.editor.toggleSourceEdit(A);}});
+i<this.editor.btns.length;i++){E.push(this.editor.btns[i]);}}this.xtype='NavSimplebar';for(var i=0;i<E.length;i++){this.buttons.add(this.addxtypeChild(E[i]));}this.buildToolbarDelete();D.on('editorevent',this.updateToolbar,this);},buildToolbarDelete:function(){this.deleteBtn=this.addxtypeChild({size:'sm',xtype:'Button',xns:Roo.bootstrap,fa:'trash',listeners:{click:this.onDelete.createDelegate(this)}
+});this.deleteBtn.hide();},onBtnClick:function(id){this.editorcore.relayCmd(id);this.editorcore.focus();},updateToolbar:function(A,ev,B){if(!this.editorcore.activated){this.editor.onFirstFocus();return;}var C=this.buttons;var D=this.editorcore.doc;var E=false;
+C.each(function(e){if(e.enableToggle&&e.cmd){E=E||D.queryCommandState(e.cmd);e.setActive(D.queryCommandState(e.cmd));}},this);if(ev&&(ev.type=='mouseup'||ev.type=='click')&&ev.target&&ev.target.tagName!='BODY'){B=ev.target;}var tn=B&&B.tagName.toUpperCase()||'';
+if(B&&tn!='A'){var F=B.closest('A');if(F){B=F;}}C.get('link').setActive(tn=='A');Roo.bootstrap.menu.Manager.hideAll();if(E||(tn.length&&tn=='BODY')){this.deleteBtn.hide();return;}this.deleteBtn.show();},onFirstFocus:function(){this.buttons.each(function(A){A.enable();
+});},onDelete:function(){var A=this.editorcore.createRange();var B=this.editorcore.getSelection();var sn=this.selectedNode;A.setStart(sn,0);A.setEnd(sn,0);if(sn.hasAttribute('data-block')){var C=Roo.htmleditor.Block.factory(tb.selectedNode);if(C){C.removeNode();
+B.removeAllRanges();B.addRange(A);this.updateToolbar(null,null,null);}}if(!sn){return;}if(sn&&sn.tagName=='BODY'){return;}var D=sn.childNodes[0]||sn.nextSibling||sn.previousSibling||sn.parentNode;a=new Roo.htmleditor.FilterKeepChildren({tag:false});a.replaceTag(sn);
+B.removeAllRanges();B.addRange(A);this.editorcore.fireEditorEvent(false);},toggleSourceEdit:function(A){if(A){Roo.log("disabling buttons");this.buttons.each(function(B){if(B.cmd!='pencil'){B.disable();}});}else{Roo.log("enabling buttons");if(this.editorcore.initialized){this.buttons.each(function(B){B.enable();
+});}}Roo.log("calling toggole on editor");this.editor.toggleSourceEdit(A);}});
+// Roo/bootstrap/form/HtmlEditorToolbar/Context.js
+Roo.bootstrap.form.HtmlEditorToolbar.Context=function(A){Roo.apply(this,A);Roo.bootstrap.form.HtmlEditorToolbar.Context.superclass.constructor.call(this,A);this.editor=A.editor;this.editorcore=A.editor.editorcore;this.buttons=new Roo.util.MixedCollection(false,function(o){return o.cmd;
+});};Roo.bootstrap.form.HtmlEditorToolbar.Context.types={'IMG':[{name:'width',title:"Width",width:40},{name:'height',title:"Height",width:40},{name:'align',title:"Align",opts:[[""],["left"],["right"],["center"],["top"]],width:80},{name:'border',title:"Border",width:40}
+,{name:'alt',title:"Alt",width:120},{name:'src',title:"Src",width:220}],'*':[]};Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Context,Roo.bootstrap.nav.Simplebar,{editor:false,editorcore:false,buttons:false,button_groups:false,active_group:false,selectedNode:false,onRender:function(ct,A){this.constructor.superclass.onRender.call(this,ct,A);
+var ty=this.constructor.types;this.button_groups={};for(var i in ty){this.button_groups[i]=this.buildToolbarGroup(ty[i],i);}this.buildToolbarDelete();this.hide();this.editor.on('editorevent',this.updateToolbar,this);},onFirstFocus:function(){},buildToolbarGroup:function(A,B){var C=this.editor;
+var D=this.editorcore;var tb=this;var E=[];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 F=A[i];E.push(this.addxtypeChild({xtype:'Element',xns:Roo.bootstrap,cls:'roo-htmleditor-context-label-'+B+'-'+F.name,html:F.title}
+));E.push(this.addxtypeChild({xtype:'Input',xns:Roo.bootstrap.form,cls:'roo-htmleditor-context-entry-'+B+'-'+F.name,name:'-roo-edit-'+F.name,attrname:F.name,width:F.width,value:'',listeners:{'change':function(f,nv,ov){tb.selectedNode.setAttribute(f.attrname,nv);
+D.syncValue();}}}));}E.forEach(function(e){e.hide();});E.name=B;return E;},buildToolbarDelete:function(){this.addxtypeChild({xtype:'Element',xns:Roo.bootstrap,cls:'roo-htmleditor-fill'});this.deleteBtn=this.addxtypeChild({size:'sm',xtype:'Button',xns:Roo.bootstrap,fa:'trash',listeners:{click:this.onDelete.createDelegate(this)}
+});this.deleteBtn.hide();},onDelete:function(){var A=this.editorcore.createRange();var B=this.editorcore.getSelection();var sn=this.selectedNode;A.setStart(sn,0);A.setEnd(sn,0);if(sn.hasAttribute('data-block')){var C=Roo.htmleditor.Block.factory(tb.selectedNode);
+if(C){C.removeNode();B.removeAllRanges();B.addRange(A);this.updateToolbar(null,null,null);}}if(!sn){return;}if(sn&&sn.tagName=='BODY'){return;}var D=sn.childNodes[0]||sn.nextSibling||sn.previousSibling||sn.parentNode;a=new Roo.htmleditor.FilterKeepChildren({tag:false}
+);a.replaceTag(sn);B.removeAllRanges();B.addRange(A);this.editorcore.fireEditorEvent(false);},updateToolbar:function(A,ev,B){var ty=this.constructor.types;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;
+}Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e){e.classList.remove('roo-ed-selection');});var C=this.editorcore.getAllAncestors();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.selectedNode;this.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.button_groups[tn])=='undefined'){this.button_groups[tn]=this.buildBlockToolbar(F);
+}this.selectedNode=db;E=F.friendly_name;C=this.editorcore.getAllAncestors();}}if(this.active_group!==false&&this.active_group.name==tn&&D==this.selectedNode&&ev!==false){return;}if(tn=='BODY'){this.deleteBtn.hide();this.hide();this.hideActiveGroup();return;
+}if(this.active_group){this.hideActiveGroup();}this.showActiveGroup(tn);this.show();this.deleteBtn.show();},hideActiveGroup:function(){this.hide();if(this.active_group===false){return;}this.active_group.forEach(function(e){e.hide();});this.active_group=false;
+},showActiveGroup:function(tn){if(typeof(this.button_groups[tn])=='undefined'){return;}this.active_group=this.button_groups[tn];this.active_group.forEach(function(e){e.show();});if(this.selectedNode.hasAttribute('data-block')){var A=Roo.htmleditor.Block.factory(this.selectedNode);
+this.active_group.forEach(function(e){e.setValue(this.selectedNode.getAttribute(A[e.name]));},this);return;}this.active_group.forEach(function(e){if(typeof(e.attrname)=='undefined'){return;}e.setValue(this.selectedNode.getAttribute(e.attrname));},this);}}
+);
 // Roo/bootstrap/form/Markdown.js
 Roo.bootstrap.form.Markdown=function(A){Roo.bootstrap.form.Markdown.superclass.constructor.call(this,A);};Roo.extend(Roo.bootstrap.form.Markdown,Roo.bootstrap.form.TextArea,{editing:false,initEvents:function(){Roo.bootstrap.form.TextArea.prototype.initEvents.call(this);
 this.markdownEl=this.el.createChild({cls:'roo-markdown-area'});this.inputEl().addClass('d-none');if(this.getValue()==''){this.markdownEl.dom.innerHTML=String.format('<span class="roo-placeholder">{0}</span>',this.placeholder||'');}else{this.markdownEl.dom.innerHTML=Roo.Markdown.toHtml(Roo.util.Format.htmlEncode(this.getValue()));