d54e2fee87f3cd19f2db52bad62bdf098656ef3e
[roojs1] / Roo / bootstrap / form / HtmlEditorToolbar / Standard.js
1   
2 /**
3  * @class Roo.bootstrap.form.HtmlEditorToolbar.Standard
4  * @parent Roo.bootstrap.form.HtmlEditor
5  * @extends Roo.bootstrap.nav.Simplebar
6  * Basic Toolbar
7  * 
8  * @example
9  * Usage:
10  *
11  new Roo.bootstrap.form.HtmlEditor({
12     ....
13     toolbars : [
14         new Roo.bootstrap.form.HtmlEditorToolbar.Standard({
15             disable : { fonts: 1 , format: 1, ..., ... , ...],
16             btns : [ .... ]
17         })
18     }
19      
20  * 
21  * @cfg {Object} disable List of elements to disable..
22  * @cfg {Array} btns List of additional buttons.
23  * 
24  * 
25  * NEEDS Extra CSS? 
26  * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
27  */
28  
29 Roo.bootstrap.form.HtmlEditorToolbar.Standard = function(config)
30 {
31     
32     Roo.apply(this, config);
33     
34     // default disabled, based on 'good practice'..
35     this.disable = this.disable || {};
36     Roo.applyIf(this.disable, {
37         fontSize : true,
38         colors : true,
39         specialElements : true
40     });
41     Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.constructor.call(this, config);
42     
43     this.editor = config.editor;
44     this.editorcore = config.editor.editorcore;
45     
46     this.buttons   = new Roo.util.MixedCollection(false, function(o) { return o.btnid; });
47     
48     //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
49     // dont call parent... till later.
50 }
51 Roo.extend(Roo.bootstrap.form.HtmlEditorToolbar.Standard, Roo.bootstrap.nav.Simplebar,  {
52      
53     bar : true,
54     
55     editor : false,
56     editorcore : false,
57     
58     
59     formats : [
60         "p" ,  
61         "h1","h2","h3","h4","h5","h6", 
62         "pre", "code", 
63         "abbr", "acronym", "address", "cite", "samp", "var",
64         'div','span'
65     ],
66     
67     
68     deleteBtn: false,
69     
70     onRender : function(ct, position)
71     {
72        // Roo.log("Call onRender: " + this.xtype);
73         
74        Roo.bootstrap.form.HtmlEditorToolbar.Standard.superclass.onRender.call(this, ct, position);
75        Roo.log(this.el);
76        this.el.dom.style.marginBottom = '0';
77        var _this = this;
78        var editorcore = this.editorcore;
79        var editor= this.editor;
80        
81        var children = [];
82        var btn = function(id, cmd , toggle, handler, html){
83        
84             var  event = toggle ? 'toggle' : 'click';
85        
86             var a = {
87                 size : 'sm',
88                 xtype: 'Button',
89                 xns: Roo.bootstrap,
90                 //glyphicon : id,
91                 btnid : id,
92                 fa: id,
93                 cmd : cmd, // why id || cmd
94                 enableToggle: toggle !== false,
95                 html : html || '',
96                 pressed : toggle ? false : null,
97                 listeners : {}
98             };
99             a.listeners[toggle ? 'toggle' : 'click'] = function() {
100                 handler ? handler.call(_this,this) :_this.onBtnClick.call(_this, cmd ||  id);
101             };
102             children.push(a);
103             return a;
104        }
105        
106     //    var cb_box = function...
107         
108         var style = {
109                 xtype: 'Button',
110                 size : 'sm',
111                 xns: Roo.bootstrap,
112                 fa : 'font',
113                 //html : 'submit'
114                 menu : {
115                     xtype: 'Menu',
116                     xns: Roo.bootstrap,
117                     items:  []
118                 }
119         };
120         Roo.each(this.formats, function(f) {
121             style.menu.items.push({
122                 xtype :'MenuItem',
123                 xns: Roo.bootstrap,
124                 html : '<'+ f+' style="margin:2px">'+f +'</'+ f+'>',
125                 tagname : f,
126                 listeners : {
127                     click : function()
128                     {
129                         editorcore.insertTag(this.tagname);
130                         editor.focus();
131                     }
132                 }
133                 
134             });
135         });
136         children.push(style);   
137         
138         btn('bold',         false,true);
139         btn('italic',       false,true);
140         btn('align-left',   'justifyleft',true);
141         btn('align-center', 'justifycenter',true);
142         btn('align-right' , 'justifyright',true);
143         btn('link', false, true, function(btn) {
144             
145             Roo.bootstrap.MessageBox.prompt(
146                 "Add / Edit Link URL",
147                 "Enter the URL for the link",
148                 function(pressed, url) {
149                     if (pressed != 'ok') {
150                         return;
151                     }
152                     
153                     if(url && url.match(/http(s):\/\/.+/)) {
154                         this.editorcore.relayCmd('createlink', url);
155                     }
156                 }
157             );
158         });
159         btn('list','insertunorderedlist',true);
160         btn('list-ol','insertorderedlist',true);
161
162         btn('pencil', false,true, function(btn){
163                 Roo.log(this);
164                 this.toggleSourceEdit(btn.pressed);
165         });
166         
167         if (this.editor.btns.length > 0) {
168             for (var i = 0; i<this.editor.btns.length; i++) {
169                 children.push(this.editor.btns[i]);
170             }
171         }
172         
173         
174          
175         this.xtype = 'NavSimplebar'; // why?
176         
177         for(var i=0;i< children.length;i++) {
178             
179             this.buttons.add(this.addxtypeChild(children[i]));
180             
181         }
182         this.buildToolbarDelete();
183
184         editor.on('editorevent', this.updateToolbar, this);
185     },
186     
187     buildToolbarDelete : function()
188     {
189         
190        /* this.addxtypeChild({
191             xtype : 'Element',
192             xns : Roo.bootstrap,
193             cls : 'roo-htmleditor-fill'
194         });
195         */
196         this.deleteBtn = this.addxtypeChild({
197             size : 'sm',
198             xtype: 'Button',
199             xns: Roo.bootstrap,
200             fa: 'trash',
201             listeners : {
202                 click : this.onDelete.createDelegate(this)
203             }
204         });
205         this.deleteBtn.hide();     
206         
207     },
208     
209     
210     onBtnClick : function(id)
211     {
212        this.editorcore.relayCmd(id);
213        this.editorcore.focus();
214     },
215     
216     /**
217      * Protected method that will not generally be called directly. It triggers
218      * a toolbar update by reading the markup state of the current selection in the editor.
219      */
220     updateToolbar: function(editor ,ev, sel){
221
222         if(!this.editorcore.activated){
223             this.editor.onFirstFocus(); // is this neeed?
224             return;
225         }
226
227         var btns = this.buttons; 
228         var doc = this.editorcore.doc;
229         var hasToggle  = false;
230         btns.each(function(e) {
231             if (e.enableToggle && e.cmd) {
232                 hasToggle = hasToggle  || doc.queryCommandState(e.cmd);
233                 e.setActive(doc.queryCommandState(e.cmd));
234             }
235         }, this);
236         
237         
238         if (ev &&
239             (ev.type == 'mouseup' || ev.type == 'click' ) &&
240             ev.target && ev.target.tagName != 'BODY' ) { // && ev.target.tagName == 'IMG') {
241             // they have click on an image...
242             // let's see if we can change the selection...
243             sel = ev.target;
244             
245         }
246         var tn = sel && sel.tagName.toUpperCase() || '';
247         if (sel && tn != 'A') {
248             var asel = sel.closest('A');
249             if (asel) {
250                 sel = asel;
251             }
252         }
253        
254         btns.get('link').setActive(tn == 'A');
255         
256         Roo.bootstrap.menu.Manager.hideAll();
257         
258         
259         
260         Array.from(this.editorcore.doc.body.querySelectorAll('.roo-ed-selection')).forEach(function(e) {
261             e.classList.remove('roo-ed-selection');
262         });
263         
264         
265         // handle delete button..
266         if (hasToggle || (tn.length && tn == 'BODY')) {
267             this.deleteBtn.hide();
268             return;
269             
270         }
271         this.deleteBtn.show();
272         
273         
274         
275         //this.editorsyncValue();
276     },
277     onFirstFocus: function() {
278         this.buttons.each(function(item){
279            item.enable();
280         });
281     },
282     
283     onDelete : function()
284     {
285         var range = this.editorcore.createRange();
286         var selection = this.editorcore.getSelection();
287         var sn = this.selectedNode;
288         range.setStart(sn,0);
289         range.setEnd(sn,0); 
290         
291         
292         if (sn.hasAttribute('data-block')) {
293             var block = Roo.htmleditor.Block.factory(tb.selectedNode);
294             if (block) {
295                 block.removeNode();
296                 selection.removeAllRanges();
297                 selection.addRange(range);
298                 this.updateToolbar(null, null, null);
299             }   
300              
301         }
302         if (!sn) {
303             return; // should not really happen..
304         }
305         if (sn && sn.tagName == 'BODY') {
306             return;
307         }
308         var stn =  sn.childNodes[0] || sn.nextSibling || sn.previousSibling || sn.parentNode;
309         
310         // remove and keep parents.
311         a = new Roo.htmleditor.FilterKeepChildren({tag : false});
312         a.replaceTag(sn);
313         
314         selection.removeAllRanges();
315         selection.addRange(range);
316         this.editorcore.fireEditorEvent(false);
317         
318         
319     },
320     
321     
322     toggleSourceEdit : function(sourceEditMode){
323         
324           
325         if(sourceEditMode){
326             Roo.log("disabling buttons");
327            this.buttons.each( function(item){
328                 if(item.cmd != 'pencil'){
329                     item.disable();
330                 }
331             });
332           
333         }else{
334             Roo.log("enabling buttons");
335             if(this.editorcore.initialized){
336                 this.buttons.each( function(item){
337                     item.enable();
338                 });
339             }
340             
341         }
342         Roo.log("calling toggole on editor");
343         // tell the editor that it's been pressed..
344         this.editor.toggleSourceEdit(sourceEditMode);
345        
346     }
347 });
348
349
350
351