Roo/form/HtmlEditor/ToolbarStandard.js
[roojs1] / Roo / form / HtmlEditor / ToolbarStandard.js
1 // <script type="text/javascript">
2 /*
3  * Based on
4  * Ext JS Library 1.1.1
5  * Copyright(c) 2006-2007, Ext JS, LLC.
6  *  
7  
8  */
9
10 /**
11  * @class Roo.form.HtmlEditorToolbar1
12  * Basic Toolbar
13  * 
14  * Usage:
15  *
16  new Roo.form.HtmlEditor({
17     ....
18     toolbars : [
19         new Roo.form.HtmlEditorToolbar1({
20             disable : { fonts: 1 , format: 1, ..., ... , ...],
21             btns : [ .... ]
22         })
23     }
24      
25  * 
26  * @cfg {Object} disable List of elements to disable..
27  * @cfg {Array} btns List of additional buttons.
28  * 
29  * 
30  * NEEDS Extra CSS? 
31  * .x-html-editor-tb .x-edit-none .x-btn-text { background: none; }
32  */
33  
34 Roo.form.HtmlEditor.ToolbarStandard = function(config)
35 {
36     
37     Roo.apply(this, config);
38     
39     // default disabled, based on 'good practice'..
40     this.disable = this.disable || {};
41     Roo.applyIf(this.disable, {
42         fontSize : true,
43         colors : true,
44         specialElements : true
45     });
46     
47     
48     //Roo.form.HtmlEditorToolbar1.superclass.constructor.call(this, editor.wrap.dom.firstChild, [], config);
49     // dont call parent... till later.
50 }
51
52 Roo.apply(Roo.form.HtmlEditor.ToolbarStandard.prototype,  {
53     
54     tb: false,
55     
56     rendered: false,
57     
58     editor : false,
59     /**
60      * @cfg {Object} disable  List of toolbar elements to disable
61          
62      */
63     disable : false,
64       /**
65      * @cfg {Array} fontFamilies An array of available font families
66      */
67     fontFamilies : [
68         'Arial',
69         'Courier New',
70         'Tahoma',
71         'Times New Roman',
72         'Verdana'
73     ],
74     
75     specialChars : [
76            "&#169;",
77           "&#174;",     
78           "&#8482;",    
79           "&#163;" ,    
80          // "&#8212;",    
81           "&#8230;",    
82           "&#247;" ,    
83         //  "&#225;" ,     ?? a acute?
84            "&#8364;"    , //Euro
85        //   "&#8220;"    ,
86         //  "&#8221;"    ,
87         //  "&#8226;"    ,
88           "&#176;"  //   , // degrees
89
90          // "&#233;"     , // e ecute
91          // "&#250;"     , // u ecute?
92     ],
93     
94     specialElements : [
95         {
96             text: "Insert Table",
97             xtype: 'MenuItem',
98             xns : Roo.Menu,
99             ihtml :  '<table><tr><td>Cell</td></tr></table>' 
100                 
101         },
102         {    
103             text: "Insert Image",
104             xtype: 'MenuItem',
105             xns : Roo.Menu,
106             ihtml : '<img src="about:blank"/>'
107             
108         }
109         
110          
111     ],
112     
113     
114     inputElements : [ 
115             "form", "input:text", "input:hidden", "input:checkbox", "input:radio", "input:password", 
116             "input:submit", "input:button", "select", "textarea", "label" ],
117     formats : [
118         ["p"] ,  
119         ["h1"],["h2"],["h3"],["h4"],["h5"],["h6"], 
120         ["pre"],[ "code"], 
121         ["abbr"],[ "acronym"],[ "address"],[ "cite"],[ "samp"],[ "var"],
122         ['div'],['span']
123     ],
124      /**
125      * @cfg {String} defaultFont default font to use.
126      */
127     defaultFont: 'tahoma',
128    
129     fontSelect : false,
130     
131     
132     formatCombo : false,
133     
134     init : function(editor)
135     {
136         this.editor = editor;
137         
138         
139         var fid = editor.frameId;
140         var etb = this;
141         function btn(id, toggle, handler){
142             var xid = fid + '-'+ id ;
143             return {
144                 id : xid,
145                 cmd : id,
146                 cls : 'x-btn-icon x-edit-'+id,
147                 enableToggle:toggle !== false,
148                 scope: editor, // was editor...
149                 handler:handler||editor.relayBtnCmd,
150                 clickEvent:'mousedown',
151                 tooltip: etb.buttonTips[id] || undefined, ///tips ???
152                 tabIndex:-1
153             };
154         }
155         
156         
157         
158         var tb = new Roo.Toolbar(editor.wrap.dom.firstChild);
159         this.tb = tb;
160          // stop form submits
161         tb.el.on('click', function(e){
162             e.preventDefault(); // what does this do?
163         });
164
165         if(!this.disable.font) { // && !Roo.isSafari){
166             /* why no safari for fonts 
167             editor.fontSelect = tb.el.createChild({
168                 tag:'select',
169                 tabIndex: -1,
170                 cls:'x-font-select',
171                 html: this.createFontOptions()
172             });
173             
174             editor.fontSelect.on('change', function(){
175                 var font = editor.fontSelect.dom.value;
176                 editor.relayCmd('fontname', font);
177                 editor.deferFocus();
178             }, editor);
179             
180             tb.add(
181                 editor.fontSelect.dom,
182                 '-'
183             );
184             */
185             
186         };
187         if(!this.disable.formats){
188             this.formatCombo = new Roo.form.ComboBox({
189                 store: new Roo.data.SimpleStore({
190                     id : 'tag',
191                     fields: ['tag'],
192                     data : this.formats // from states.js
193                 }),
194                 blockFocus : true,
195                 name : '',
196                 //autoCreate : {tag: "div",  size: "20"},
197                 displayField:'tag',
198                 typeAhead: false,
199                 mode: 'local',
200                 editable : false,
201                 triggerAction: 'all',
202                 emptyText:'Add tag',
203                 selectOnFocus:true,
204                 width:135,
205                 listeners : {
206                     'select': function(c, r, i) {
207                         editor.insertTag(r.get('tag'));
208                         editor.focus();
209                     }
210                 }
211
212             });
213             tb.addField(this.formatCombo);
214             
215         }
216         
217         if(!this.disable.format){
218             tb.add(
219                 btn('bold'),
220                 btn('italic'),
221                 btn('underline')
222             );
223         };
224         if(!this.disable.fontSize){
225             tb.add(
226                 '-',
227                 
228                 
229                 btn('increasefontsize', false, editor.adjustFont),
230                 btn('decreasefontsize', false, editor.adjustFont)
231             );
232         };
233         
234         
235         if(!this.disable.colors){
236             tb.add(
237                 '-', {
238                     id:editor.frameId +'-forecolor',
239                     cls:'x-btn-icon x-edit-forecolor',
240                     clickEvent:'mousedown',
241                     tooltip: this.buttonTips['forecolor'] || undefined,
242                     tabIndex:-1,
243                     menu : new Roo.menu.ColorMenu({
244                         allowReselect: true,
245                         focus: Roo.emptyFn,
246                         value:'000000',
247                         plain:true,
248                         selectHandler: function(cp, color){
249                             editor.execCmd('forecolor', Roo.isSafari || Roo.isIE ? '#'+color : color);
250                             editor.deferFocus();
251                         },
252                         scope: editor,
253                         clickEvent:'mousedown'
254                     })
255                 }, {
256                     id:editor.frameId +'backcolor',
257                     cls:'x-btn-icon x-edit-backcolor',
258                     clickEvent:'mousedown',
259                     tooltip: this.buttonTips['backcolor'] || undefined,
260                     tabIndex:-1,
261                     menu : new Roo.menu.ColorMenu({
262                         focus: Roo.emptyFn,
263                         value:'FFFFFF',
264                         plain:true,
265                         allowReselect: true,
266                         selectHandler: function(cp, color){
267                             if(Roo.isGecko){
268                                 editor.execCmd('useCSS', false);
269                                 editor.execCmd('hilitecolor', color);
270                                 editor.execCmd('useCSS', true);
271                                 editor.deferFocus();
272                             }else{
273                                 editor.execCmd(Roo.isOpera ? 'hilitecolor' : 'backcolor', 
274                                     Roo.isSafari || Roo.isIE ? '#'+color : color);
275                                 editor.deferFocus();
276                             }
277                         },
278                         scope:editor,
279                         clickEvent:'mousedown'
280                     })
281                 }
282             );
283         };
284         // now add all the items...
285         
286
287         if(!this.disable.alignments){
288             tb.add(
289                 '-',
290                 btn('justifyleft'),
291                 btn('justifycenter'),
292                 btn('justifyright')
293             );
294         };
295
296         //if(!Roo.isSafari){
297             if(!this.disable.links){
298                 tb.add(
299                     '-',
300                     btn('createlink', false, editor.createLink)    /// MOVE TO HERE?!!?!?!?!
301                 );
302             };
303
304             if(!this.disable.lists){
305                 tb.add(
306                     '-',
307                     btn('insertorderedlist'),
308                     btn('insertunorderedlist')
309                 );
310             }
311             if(!this.disable.sourceEdit){
312                 tb.add(
313                     '-',
314                     btn('sourceedit', true, function(btn){
315                         this.toggleSourceEdit(btn.pressed);
316                     })
317                 );
318             }
319         //}
320         
321         var smenu = { };
322         // special menu.. - needs to be tidied up..
323         if (!this.disable.special) {
324             smenu = {
325                 text: "&#169;",
326                 cls: 'x-edit-none',
327                 
328                 menu : {
329                     items : []
330                 }
331             };
332             for (var i =0; i < this.specialChars.length; i++) {
333                 smenu.menu.items.push({
334                     
335                     html: this.specialChars[i],
336                     handler: function(a,b) {
337                         editor.insertAtCursor(String.fromCharCode(a.html.replace('&#','').replace(';', '')));
338                         //editor.insertAtCursor(a.html);
339                         
340                     },
341                     tabIndex:-1
342                 });
343             }
344             
345             
346             tb.add(smenu);
347             
348             
349         }
350          
351         if (!this.disable.specialElements) {
352             var semenu = {
353                 text: "Other;",
354                 cls: 'x-edit-none',
355                 menu : {
356                     items : []
357                 }
358             };
359             for (var i =0; i < this.specialElements.length; i++) {
360                 semenu.menu.items.push(
361                     Roo.apply({ 
362                         handler: function(a,b) {
363                             editor.insertAtCursor(this.ihtml);
364                         }
365                     }, this.specialElements[i])
366                 );
367                     
368             }
369             
370             tb.add(semenu);
371             
372             
373         }
374          
375         
376         if (this.btns) {
377             for(var i =0; i< this.btns.length;i++) {
378                 var b = Roo.factory(this.btns[i],Roo.form);
379                 b.cls =  'x-edit-none';
380                 b.scope = editor;
381                 tb.add(b);
382             }
383         
384         }
385         
386         
387         
388         // disable everything...
389         
390         this.tb.items.each(function(item){
391            if(item.id != editor.frameId+ '-sourceedit'){
392                 item.disable();
393             }
394         });
395         this.rendered = true;
396         
397         // the all the btns;
398         editor.on('editorevent', this.updateToolbar, this);
399         // other toolbars need to implement this..
400         //editor.on('editmodechange', this.updateToolbar, this);
401     },
402     
403     
404     
405     /**
406      * Protected method that will not generally be called directly. It triggers
407      * a toolbar update by reading the markup state of the current selection in the editor.
408      */
409     updateToolbar: function(){
410
411         if(!this.editor.activated){
412             this.editor.onFirstFocus();
413             return;
414         }
415
416         var btns = this.tb.items.map, 
417             doc = this.editor.doc,
418             frameId = this.editor.frameId;
419
420         if(!this.disable.font && !Roo.isSafari){
421             /*
422             var name = (doc.queryCommandValue('FontName')||this.editor.defaultFont).toLowerCase();
423             if(name != this.fontSelect.dom.value){
424                 this.fontSelect.dom.value = name;
425             }
426             */
427         }
428         if(!this.disable.format){
429             btns[frameId + '-bold'].toggle(doc.queryCommandState('bold'));
430             btns[frameId + '-italic'].toggle(doc.queryCommandState('italic'));
431             btns[frameId + '-underline'].toggle(doc.queryCommandState('underline'));
432         }
433         if(!this.disable.alignments){
434             btns[frameId + '-justifyleft'].toggle(doc.queryCommandState('justifyleft'));
435             btns[frameId + '-justifycenter'].toggle(doc.queryCommandState('justifycenter'));
436             btns[frameId + '-justifyright'].toggle(doc.queryCommandState('justifyright'));
437         }
438         if(!Roo.isSafari && !this.disable.lists){
439             btns[frameId + '-insertorderedlist'].toggle(doc.queryCommandState('insertorderedlist'));
440             btns[frameId + '-insertunorderedlist'].toggle(doc.queryCommandState('insertunorderedlist'));
441         }
442         
443         var ans = this.editor.getAllAncestors();
444         if (this.formatCombo) {
445             
446             
447             var store = this.formatCombo.store;
448             this.formatCombo.setValue("");
449             for (var i =0; i < ans.length;i++) {
450                 if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
451                     // select it..
452                     this.formatCombo.setValue(ans[i].tagName.toLowerCase());
453                     break;
454                 }
455             }
456         }
457         
458         
459         
460         // hides menus... - so this cant be on a menu...
461         Roo.menu.MenuMgr.hideAll();
462
463         //this.editorsyncValue();
464     },
465    
466     
467     createFontOptions : function(){
468         var buf = [], fs = this.fontFamilies, ff, lc;
469         
470         
471         
472         for(var i = 0, len = fs.length; i< len; i++){
473             ff = fs[i];
474             lc = ff.toLowerCase();
475             buf.push(
476                 '<option value="',lc,'" style="font-family:',ff,';"',
477                     (this.defaultFont == lc ? ' selected="true">' : '>'),
478                     ff,
479                 '</option>'
480             );
481         }
482         return buf.join('');
483     },
484     
485     toggleSourceEdit : function(sourceEditMode){
486         if(sourceEditMode === undefined){
487             sourceEditMode = !this.sourceEditMode;
488         }
489         this.sourceEditMode = sourceEditMode === true;
490         var btn = this.tb.items.get(this.editor.frameId +'-sourceedit');
491         // just toggle the button?
492         if(btn.pressed !== this.editor.sourceEditMode){
493             btn.toggle(this.editor.sourceEditMode);
494             return;
495         }
496         
497         if(this.sourceEditMode){
498             this.tb.items.each(function(item){
499                 if(item.cmd != 'sourceedit'){
500                     item.disable();
501                 }
502             });
503           
504         }else{
505             if(this.initialized){
506                 this.tb.items.each(function(item){
507                     item.enable();
508                 });
509             }
510             
511         }
512         // tell the editor that it's been pressed..
513         this.editor.toggleSourceEdit(sourceEditMode);
514        
515     },
516      /**
517      * Object collection of toolbar tooltips for the buttons in the editor. The key
518      * is the command id associated with that button and the value is a valid QuickTips object.
519      * For example:
520 <pre><code>
521 {
522     bold : {
523         title: 'Bold (Ctrl+B)',
524         text: 'Make the selected text bold.',
525         cls: 'x-html-editor-tip'
526     },
527     italic : {
528         title: 'Italic (Ctrl+I)',
529         text: 'Make the selected text italic.',
530         cls: 'x-html-editor-tip'
531     },
532     ...
533 </code></pre>
534     * @type Object
535      */
536     buttonTips : {
537         bold : {
538             title: 'Bold (Ctrl+B)',
539             text: 'Make the selected text bold.',
540             cls: 'x-html-editor-tip'
541         },
542         italic : {
543             title: 'Italic (Ctrl+I)',
544             text: 'Make the selected text italic.',
545             cls: 'x-html-editor-tip'
546         },
547         underline : {
548             title: 'Underline (Ctrl+U)',
549             text: 'Underline the selected text.',
550             cls: 'x-html-editor-tip'
551         },
552         increasefontsize : {
553             title: 'Grow Text',
554             text: 'Increase the font size.',
555             cls: 'x-html-editor-tip'
556         },
557         decreasefontsize : {
558             title: 'Shrink Text',
559             text: 'Decrease the font size.',
560             cls: 'x-html-editor-tip'
561         },
562         backcolor : {
563             title: 'Text Highlight Color',
564             text: 'Change the background color of the selected text.',
565             cls: 'x-html-editor-tip'
566         },
567         forecolor : {
568             title: 'Font Color',
569             text: 'Change the color of the selected text.',
570             cls: 'x-html-editor-tip'
571         },
572         justifyleft : {
573             title: 'Align Text Left',
574             text: 'Align text to the left.',
575             cls: 'x-html-editor-tip'
576         },
577         justifycenter : {
578             title: 'Center Text',
579             text: 'Center text in the editor.',
580             cls: 'x-html-editor-tip'
581         },
582         justifyright : {
583             title: 'Align Text Right',
584             text: 'Align text to the right.',
585             cls: 'x-html-editor-tip'
586         },
587         insertunorderedlist : {
588             title: 'Bullet List',
589             text: 'Start a bulleted list.',
590             cls: 'x-html-editor-tip'
591         },
592         insertorderedlist : {
593             title: 'Numbered List',
594             text: 'Start a numbered list.',
595             cls: 'x-html-editor-tip'
596         },
597         createlink : {
598             title: 'Hyperlink',
599             text: 'Make the selected text a hyperlink.',
600             cls: 'x-html-editor-tip'
601         },
602         sourceedit : {
603             title: 'Source Edit',
604             text: 'Switch to source editing mode.',
605             cls: 'x-html-editor-tip'
606         }
607     },
608     // private
609     onDestroy : function(){
610         if(this.rendered){
611             
612             this.tb.items.each(function(item){
613                 if(item.menu){
614                     item.menu.removeAll();
615                     if(item.menu.el){
616                         item.menu.el.destroy();
617                     }
618                 }
619                 item.destroy();
620             });
621              
622         }
623     },
624     onFirstFocus: function() {
625         this.tb.items.each(function(item){
626            item.enable();
627         });
628     }
629 });
630
631
632
633