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             smenu = {
345                 text: "Other;",
346                 cls: 'x-edit-none',
347                 menu : {
348                     items : this.specialElements
349                 }
350             };
351             
352             //tb.add(smenu);
353             
354             
355         }
356         
357         if (this.btns) {
358             for(var i =0; i< this.btns.length;i++) {
359                 var b = this.btns[i];
360                 b.cls =  'x-edit-none';
361                 b.scope = editor;
362                 tb.add(b);
363             }
364         
365         }
366         
367         
368         
369         // disable everything...
370         
371         this.tb.items.each(function(item){
372            if(item.id != editor.frameId+ '-sourceedit'){
373                 item.disable();
374             }
375         });
376         this.rendered = true;
377         
378         // the all the btns;
379         editor.on('editorevent', this.updateToolbar, this);
380         // other toolbars need to implement this..
381         //editor.on('editmodechange', this.updateToolbar, this);
382     },
383     
384     
385     
386     /**
387      * Protected method that will not generally be called directly. It triggers
388      * a toolbar update by reading the markup state of the current selection in the editor.
389      */
390     updateToolbar: function(){
391
392         if(!this.editor.activated){
393             this.editor.onFirstFocus();
394             return;
395         }
396
397         var btns = this.tb.items.map, 
398             doc = this.editor.doc,
399             frameId = this.editor.frameId;
400
401         if(!this.disable.font && !Roo.isSafari){
402             /*
403             var name = (doc.queryCommandValue('FontName')||this.editor.defaultFont).toLowerCase();
404             if(name != this.fontSelect.dom.value){
405                 this.fontSelect.dom.value = name;
406             }
407             */
408         }
409         if(!this.disable.format){
410             btns[frameId + '-bold'].toggle(doc.queryCommandState('bold'));
411             btns[frameId + '-italic'].toggle(doc.queryCommandState('italic'));
412             btns[frameId + '-underline'].toggle(doc.queryCommandState('underline'));
413         }
414         if(!this.disable.alignments){
415             btns[frameId + '-justifyleft'].toggle(doc.queryCommandState('justifyleft'));
416             btns[frameId + '-justifycenter'].toggle(doc.queryCommandState('justifycenter'));
417             btns[frameId + '-justifyright'].toggle(doc.queryCommandState('justifyright'));
418         }
419         if(!Roo.isSafari && !this.disable.lists){
420             btns[frameId + '-insertorderedlist'].toggle(doc.queryCommandState('insertorderedlist'));
421             btns[frameId + '-insertunorderedlist'].toggle(doc.queryCommandState('insertunorderedlist'));
422         }
423         
424         var ans = this.editor.getAllAncestors();
425         if (this.formatCombo) {
426             
427             
428             var store = this.formatCombo.store;
429             this.formatCombo.setValue("");
430             for (var i =0; i < ans.length;i++) {
431                 if (ans[i] && store.query('tag',ans[i].tagName.toLowerCase(), false).length) {
432                     // select it..
433                     this.formatCombo.setValue(ans[i].tagName.toLowerCase());
434                     break;
435                 }
436             }
437         }
438         
439         
440         
441         // hides menus... - so this cant be on a menu...
442         Roo.menu.MenuMgr.hideAll();
443
444         //this.editorsyncValue();
445     },
446    
447     
448     createFontOptions : function(){
449         var buf = [], fs = this.fontFamilies, ff, lc;
450         for(var i = 0, len = fs.length; i< len; i++){
451             ff = fs[i];
452             lc = ff.toLowerCase();
453             buf.push(
454                 '<option value="',lc,'" style="font-family:',ff,';"',
455                     (this.defaultFont == lc ? ' selected="true">' : '>'),
456                     ff,
457                 '</option>'
458             );
459         }
460         return buf.join('');
461     },
462     
463     toggleSourceEdit : function(sourceEditMode){
464         if(sourceEditMode === undefined){
465             sourceEditMode = !this.sourceEditMode;
466         }
467         this.sourceEditMode = sourceEditMode === true;
468         var btn = this.tb.items.get(this.editor.frameId +'-sourceedit');
469         // just toggle the button?
470         if(btn.pressed !== this.editor.sourceEditMode){
471             btn.toggle(this.editor.sourceEditMode);
472             return;
473         }
474         
475         if(this.sourceEditMode){
476             this.tb.items.each(function(item){
477                 if(item.cmd != 'sourceedit'){
478                     item.disable();
479                 }
480             });
481           
482         }else{
483             if(this.initialized){
484                 this.tb.items.each(function(item){
485                     item.enable();
486                 });
487             }
488             
489         }
490         // tell the editor that it's been pressed..
491         this.editor.toggleSourceEdit(sourceEditMode);
492        
493     },
494      /**
495      * Object collection of toolbar tooltips for the buttons in the editor. The key
496      * is the command id associated with that button and the value is a valid QuickTips object.
497      * For example:
498 <pre><code>
499 {
500     bold : {
501         title: 'Bold (Ctrl+B)',
502         text: 'Make the selected text bold.',
503         cls: 'x-html-editor-tip'
504     },
505     italic : {
506         title: 'Italic (Ctrl+I)',
507         text: 'Make the selected text italic.',
508         cls: 'x-html-editor-tip'
509     },
510     ...
511 </code></pre>
512     * @type Object
513      */
514     buttonTips : {
515         bold : {
516             title: 'Bold (Ctrl+B)',
517             text: 'Make the selected text bold.',
518             cls: 'x-html-editor-tip'
519         },
520         italic : {
521             title: 'Italic (Ctrl+I)',
522             text: 'Make the selected text italic.',
523             cls: 'x-html-editor-tip'
524         },
525         underline : {
526             title: 'Underline (Ctrl+U)',
527             text: 'Underline the selected text.',
528             cls: 'x-html-editor-tip'
529         },
530         increasefontsize : {
531             title: 'Grow Text',
532             text: 'Increase the font size.',
533             cls: 'x-html-editor-tip'
534         },
535         decreasefontsize : {
536             title: 'Shrink Text',
537             text: 'Decrease the font size.',
538             cls: 'x-html-editor-tip'
539         },
540         backcolor : {
541             title: 'Text Highlight Color',
542             text: 'Change the background color of the selected text.',
543             cls: 'x-html-editor-tip'
544         },
545         forecolor : {
546             title: 'Font Color',
547             text: 'Change the color of the selected text.',
548             cls: 'x-html-editor-tip'
549         },
550         justifyleft : {
551             title: 'Align Text Left',
552             text: 'Align text to the left.',
553             cls: 'x-html-editor-tip'
554         },
555         justifycenter : {
556             title: 'Center Text',
557             text: 'Center text in the editor.',
558             cls: 'x-html-editor-tip'
559         },
560         justifyright : {
561             title: 'Align Text Right',
562             text: 'Align text to the right.',
563             cls: 'x-html-editor-tip'
564         },
565         insertunorderedlist : {
566             title: 'Bullet List',
567             text: 'Start a bulleted list.',
568             cls: 'x-html-editor-tip'
569         },
570         insertorderedlist : {
571             title: 'Numbered List',
572             text: 'Start a numbered list.',
573             cls: 'x-html-editor-tip'
574         },
575         createlink : {
576             title: 'Hyperlink',
577             text: 'Make the selected text a hyperlink.',
578             cls: 'x-html-editor-tip'
579         },
580         sourceedit : {
581             title: 'Source Edit',
582             text: 'Switch to source editing mode.',
583             cls: 'x-html-editor-tip'
584         }
585     },
586     // private
587     onDestroy : function(){
588         if(this.rendered){
589             
590             this.tb.items.each(function(item){
591                 if(item.menu){
592                     item.menu.removeAll();
593                     if(item.menu.el){
594                         item.menu.el.destroy();
595                     }
596                 }
597                 item.destroy();
598             });
599              
600         }
601     },
602     onFirstFocus: function() {
603         this.tb.items.each(function(item){
604            item.enable();
605         });
606     }
607 });
608
609
610
611