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     ],
123      /**
124      * @cfg {String} defaultFont default font to use.
125      */
126     defaultFont: 'tahoma',
127    
128     fontSelect : false,
129     
130     
131     formatCombo : false,
132     
133     init : function(editor)
134     {
135         this.editor = editor;
136         
137         
138         var fid = editor.frameId;
139         var etb = this;
140         function btn(id, toggle, handler){
141             var xid = fid + '-'+ id ;
142             return {
143                 id : xid,
144                 cmd : id,
145                 cls : 'x-btn-icon x-edit-'+id,
146                 enableToggle:toggle !== false,
147                 scope: editor, // was editor...
148                 handler:handler||editor.relayBtnCmd,
149                 clickEvent:'mousedown',
150                 tooltip: etb.buttonTips[id] || undefined, ///tips ???
151                 tabIndex:-1
152             };
153         }
154         
155         
156         
157         var tb = new Roo.Toolbar(editor.wrap.dom.firstChild);
158         this.tb = tb;
159          // stop form submits
160         tb.el.on('click', function(e){
161             e.preventDefault(); // what does this do?
162         });
163
164         if(!this.disable.font) { // && !Roo.isSafari){
165             /* why no safari for fonts 
166             editor.fontSelect = tb.el.createChild({
167                 tag:'select',
168                 tabIndex: -1,
169                 cls:'x-font-select',
170                 html: this.createFontOptions()
171             });
172             
173             editor.fontSelect.on('change', function(){
174                 var font = editor.fontSelect.dom.value;
175                 editor.relayCmd('fontname', font);
176                 editor.deferFocus();
177             }, editor);
178             
179             tb.add(
180                 editor.fontSelect.dom,
181                 '-'
182             );
183             */
184             
185         };
186         if(!this.disable.formats){
187             this.formatCombo = new Roo.form.ComboBox({
188                 store: new Roo.data.SimpleStore({
189                     id : 'tag',
190                     fields: ['tag'],
191                     data : this.formats // from states.js
192                 }),
193                 blockFocus : true,
194                 name : '',
195                 //autoCreate : {tag: "div",  size: "20"},
196                 displayField:'tag',
197                 typeAhead: false,
198                 mode: 'local',
199                 editable : false,
200                 triggerAction: 'all',
201                 emptyText:'Add tag',
202                 selectOnFocus:true,
203                 width:135,
204                 listeners : {
205                     'select': function(c, r, i) {
206                         editor.insertTag(r.get('tag'));
207                         editor.focus();
208                     }
209                 }
210
211             });
212             tb.addField(this.formatCombo);
213             
214         }
215         
216         if(!this.disable.format){
217             tb.add(
218                 btn('bold'),
219                 btn('italic'),
220                 btn('underline')
221             );
222         };
223         if(!this.disable.fontSize){
224             tb.add(
225                 '-',
226                 
227                 
228                 btn('increasefontsize', false, editor.adjustFont),
229                 btn('decreasefontsize', false, editor.adjustFont)
230             );
231         };
232         
233         
234         if(!this.disable.colors){
235             tb.add(
236                 '-', {
237                     id:editor.frameId +'-forecolor',
238                     cls:'x-btn-icon x-edit-forecolor',
239                     clickEvent:'mousedown',
240                     tooltip: this.buttonTips['forecolor'] || undefined,
241                     tabIndex:-1,
242                     menu : new Roo.menu.ColorMenu({
243                         allowReselect: true,
244                         focus: Roo.emptyFn,
245                         value:'000000',
246                         plain:true,
247                         selectHandler: function(cp, color){
248                             editor.execCmd('forecolor', Roo.isSafari || Roo.isIE ? '#'+color : color);
249                             editor.deferFocus();
250                         },
251                         scope: editor,
252                         clickEvent:'mousedown'
253                     })
254                 }, {
255                     id:editor.frameId +'backcolor',
256                     cls:'x-btn-icon x-edit-backcolor',
257                     clickEvent:'mousedown',
258                     tooltip: this.buttonTips['backcolor'] || undefined,
259                     tabIndex:-1,
260                     menu : new Roo.menu.ColorMenu({
261                         focus: Roo.emptyFn,
262                         value:'FFFFFF',
263                         plain:true,
264                         allowReselect: true,
265                         selectHandler: function(cp, color){
266                             if(Roo.isGecko){
267                                 editor.execCmd('useCSS', false);
268                                 editor.execCmd('hilitecolor', color);
269                                 editor.execCmd('useCSS', true);
270                                 editor.deferFocus();
271                             }else{
272                                 editor.execCmd(Roo.isOpera ? 'hilitecolor' : 'backcolor', 
273                                     Roo.isSafari || Roo.isIE ? '#'+color : color);
274                                 editor.deferFocus();
275                             }
276                         },
277                         scope:editor,
278                         clickEvent:'mousedown'
279                     })
280                 }
281             );
282         };
283         // now add all the items...
284         
285
286         if(!this.disable.alignments){
287             tb.add(
288                 '-',
289                 btn('justifyleft'),
290                 btn('justifycenter'),
291                 btn('justifyright')
292             );
293         };
294
295         //if(!Roo.isSafari){
296             if(!this.disable.links){
297                 tb.add(
298                     '-',
299                     btn('createlink', false, editor.createLink)    /// MOVE TO HERE?!!?!?!?!
300                 );
301             };
302
303             if(!this.disable.lists){
304                 tb.add(
305                     '-',
306                     btn('insertorderedlist'),
307                     btn('insertunorderedlist')
308                 );
309             }
310             if(!this.disable.sourceEdit){
311                 tb.add(
312                     '-',
313                     btn('sourceedit', true, function(btn){
314                         this.toggleSourceEdit(btn.pressed);
315                     })
316                 );
317             }
318         //}
319         
320         var smenu = { };
321         // special menu.. - needs to be tidied up..
322         if (!this.disable.special) {
323             smenu = {
324                 text: "&#169;",
325                 cls: 'x-edit-none',
326                 
327                 menu : {
328                     items : []
329                 }
330             };
331             for (var i =0; i < this.specialChars.length; i++) {
332                 smenu.menu.items.push({
333                     
334                     html: this.specialChars[i],
335                     handler: function(a,b) {
336                         editor.insertAtCursor(String.fromCharCode(a.html.replace('&#','').replace(';', '')));
337                         //editor.insertAtCursor(a.html);
338                         
339                     },
340                     tabIndex:-1
341                 });
342             }
343             
344             
345             tb.add(smenu);
346             
347             
348         }
349          
350         if (!this.disable.specialElements) {
351             var semenu = {
352                 text: "Other;",
353                 cls: 'x-edit-none',
354                 menu : {
355                     items : []
356                 }
357             };
358             for (var i =0; i < this.specialElements.length; i++) {
359                 semenu.menu.items.push(
360                     Roo.apply({ 
361                         handler: function(a,b) {
362                             editor.insertAtCursor(this.ihtml);
363                         }
364                     }, this.specialElements[i])
365                 );
366                     
367             }
368             
369             tb.add(semenu);
370             
371             
372         }
373          
374         
375         if (this.btns) {
376             for(var i =0; i< this.btns.length;i++) {
377                 var b = Roo.factory(this.btns[i],Roo.form);
378                 b.cls =  'x-edit-none';
379                 b.scope = editor;
380                 tb.add(b);
381             }
382         
383         }
384         
385         
386         
387         // disable everything...
388         
389         this.tb.items.each(function(item){
390            if(item.id != editor.frameId+ '-sourceedit'){
391                 item.disable();
392             }
393         });
394         this.rendered = true;
395         
396         // the all the btns;
397         editor.on('editorevent', this.updateToolbar, this);
398         // other toolbars need to implement this..
399         //editor.on('editmodechange', this.updateToolbar, this);
400     },
401     
402     
403     
404     /**
405      * Protected method that will not generally be called directly. It triggers
406      * a toolbar update by reading the markup state of the current selection in the editor.
407      */
408     updateToolbar: function(){
409
410         if(!this.editor.activated){
411             this.editor.onFirstFocus();
412             return;
413         }
414
415         var btns = this.tb.items.map, 
416             doc = this.editor.doc,
417             frameId = this.editor.frameId;
418
419         if(!this.disable.font && !Roo.isSafari){
420             /*
421             var name = (doc.queryCommandValue('FontName')||this.editor.defaultFont).toLowerCase();
422             if(name != this.fontSelect.dom.value){
423                 this.fontSelect.dom.value = name;
424             }
425             */
426         }
427         if(!this.disable.format){
428             btns[frameId + '-bold'].toggle(doc.queryCommandState('bold'));
429             btns[frameId + '-italic'].toggle(doc.queryCommandState('italic'));
430             btns[frameId + '-underline'].toggle(doc.queryCommandState('underline'));
431         }
432         if(!this.disable.alignments){
433             btns[frameId + '-justifyleft'].toggle(doc.queryCommandState('justifyleft'));
434             btns[frameId + '-justifycenter'].toggle(doc.queryCommandState('justifycenter'));
435             btns[frameId + '-justifyright'].toggle(doc.queryCommandState('justifyright'));
436         }
437         if(!Roo.isSafari && !this.disable.lists){
438             btns[frameId + '-insertorderedlist'].toggle(doc.queryCommandState('insertorderedlist'));
439             btns[frameId + '-insertunorderedlist'].toggle(doc.queryCommandState('insertunorderedlist'));
440         }
441         
442         var ans = this.editor.getAllAncestors();
443         if (this.formatCombo) {
444             
445             
446             var store = this.formatCombo.store;
447             this.formatCombo.setValue("");
448             for (var i =0; i < ans.length;i++) {
449                 if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
450                     // select it..
451                     this.formatCombo.setValue(ans[i].tagName.toLowerCase());
452                     break;
453                 }
454             }
455         }
456         
457         
458         
459         // hides menus... - so this cant be on a menu...
460         Roo.menu.MenuMgr.hideAll();
461
462         //this.editorsyncValue();
463     },
464    
465     
466     createFontOptions : function(){
467         var buf = [], fs = this.fontFamilies, ff, lc;
468         
469         
470         
471         for(var i = 0, len = fs.length; i< len; i++){
472             ff = fs[i];
473             lc = ff.toLowerCase();
474             buf.push(
475                 '<option value="',lc,'" style="font-family:',ff,';"',
476                     (this.defaultFont == lc ? ' selected="true">' : '>'),
477                     ff,
478                 '</option>'
479             );
480         }
481         return buf.join('');
482     },
483     
484     toggleSourceEdit : function(sourceEditMode){
485         if(sourceEditMode === undefined){
486             sourceEditMode = !this.sourceEditMode;
487         }
488         this.sourceEditMode = sourceEditMode === true;
489         var btn = this.tb.items.get(this.editor.frameId +'-sourceedit');
490         // just toggle the button?
491         if(btn.pressed !== this.editor.sourceEditMode){
492             btn.toggle(this.editor.sourceEditMode);
493             return;
494         }
495         
496         if(this.sourceEditMode){
497             this.tb.items.each(function(item){
498                 if(item.cmd != 'sourceedit'){
499                     item.disable();
500                 }
501             });
502           
503         }else{
504             if(this.initialized){
505                 this.tb.items.each(function(item){
506                     item.enable();
507                 });
508             }
509             
510         }
511         // tell the editor that it's been pressed..
512         this.editor.toggleSourceEdit(sourceEditMode);
513        
514     },
515      /**
516      * Object collection of toolbar tooltips for the buttons in the editor. The key
517      * is the command id associated with that button and the value is a valid QuickTips object.
518      * For example:
519 <pre><code>
520 {
521     bold : {
522         title: 'Bold (Ctrl+B)',
523         text: 'Make the selected text bold.',
524         cls: 'x-html-editor-tip'
525     },
526     italic : {
527         title: 'Italic (Ctrl+I)',
528         text: 'Make the selected text italic.',
529         cls: 'x-html-editor-tip'
530     },
531     ...
532 </code></pre>
533     * @type Object
534      */
535     buttonTips : {
536         bold : {
537             title: 'Bold (Ctrl+B)',
538             text: 'Make the selected text bold.',
539             cls: 'x-html-editor-tip'
540         },
541         italic : {
542             title: 'Italic (Ctrl+I)',
543             text: 'Make the selected text italic.',
544             cls: 'x-html-editor-tip'
545         },
546         underline : {
547             title: 'Underline (Ctrl+U)',
548             text: 'Underline the selected text.',
549             cls: 'x-html-editor-tip'
550         },
551         increasefontsize : {
552             title: 'Grow Text',
553             text: 'Increase the font size.',
554             cls: 'x-html-editor-tip'
555         },
556         decreasefontsize : {
557             title: 'Shrink Text',
558             text: 'Decrease the font size.',
559             cls: 'x-html-editor-tip'
560         },
561         backcolor : {
562             title: 'Text Highlight Color',
563             text: 'Change the background color of the selected text.',
564             cls: 'x-html-editor-tip'
565         },
566         forecolor : {
567             title: 'Font Color',
568             text: 'Change the color of the selected text.',
569             cls: 'x-html-editor-tip'
570         },
571         justifyleft : {
572             title: 'Align Text Left',
573             text: 'Align text to the left.',
574             cls: 'x-html-editor-tip'
575         },
576         justifycenter : {
577             title: 'Center Text',
578             text: 'Center text in the editor.',
579             cls: 'x-html-editor-tip'
580         },
581         justifyright : {
582             title: 'Align Text Right',
583             text: 'Align text to the right.',
584             cls: 'x-html-editor-tip'
585         },
586         insertunorderedlist : {
587             title: 'Bullet List',
588             text: 'Start a bulleted list.',
589             cls: 'x-html-editor-tip'
590         },
591         insertorderedlist : {
592             title: 'Numbered List',
593             text: 'Start a numbered list.',
594             cls: 'x-html-editor-tip'
595         },
596         createlink : {
597             title: 'Hyperlink',
598             text: 'Make the selected text a hyperlink.',
599             cls: 'x-html-editor-tip'
600         },
601         sourceedit : {
602             title: 'Source Edit',
603             text: 'Switch to source editing mode.',
604             cls: 'x-html-editor-tip'
605         }
606     },
607     // private
608     onDestroy : function(){
609         if(this.rendered){
610             
611             this.tb.items.each(function(item){
612                 if(item.menu){
613                     item.menu.removeAll();
614                     if(item.menu.el){
615                         item.menu.el.destroy();
616                     }
617                 }
618                 item.destroy();
619             });
620              
621         }
622     },
623     onFirstFocus: function() {
624         this.tb.items.each(function(item){
625            item.enable();
626         });
627     }
628 });
629
630
631
632