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