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