Administrator
2023-04-21 195945efc5db921a4c9eb8cf9421c172273293f5
提交 | 用户 | 时间
58d006 1 /**
A 2  <b>Wysiwyg</b>. A wrapper for Bootstrap wyswiwyg plugin.
3  It's just a wrapper so you still need to include Bootstrap wysiwyg script first.
4 */
5 (function($ , undefined) {
6     $.fn.ace_wysiwyg = function($options , undefined) {
7         var options = $.extend( {
8             speech_button:true,
9             wysiwyg:{}
10         }, $options);
11
12         var color_values = [
13             '#ac725e','#d06b64','#f83a22','#fa573c','#ff7537','#ffad46',
14             '#42d692','#16a765','#7bd148','#b3dc6c','#fbe983','#fad165',
15             '#92e1c0','#9fe1e7','#9fc6e7','#4986e7','#9a9cff','#b99aff',
16             '#c2c2c2','#cabdbf','#cca6ac','#f691b2','#cd74e6','#a47ae2',
17             '#444444'
18         ]
19
20         var button_defaults =
21         {
22             'font' : {
23                 values:['Arial', 'Courier', 'Comic Sans MS', 'Helvetica', 'Open Sans', 'Tahoma', 'Verdana'],
24                 icon:'fa fa-font',
25                 title:'Font'
26             },
27             'fontSize' : {
28                 values:{5:'Huge', 3:'Normal', 1:'Small'},
29                 icon:'fa fa-text-height',
30                 title:'Font Size'
31             },
32             'bold' : {
33                 icon : 'fa fa-bold',
34                 title : 'Bold (Ctrl/Cmd+B)'
35             },
36             'italic' : {
37                 icon : 'fa fa-italic',
38                 title : 'Italic (Ctrl/Cmd+I)'
39             },
40             'strikethrough' : {
41                 icon : 'fa fa-strikethrough',
42                 title : 'Strikethrough'
43             },
44             'underline' : {
45                 icon : 'fa fa-underline',
46                 title : 'Underline'
47             },
48             'insertunorderedlist' : {
49                 icon : 'fa fa-list-ul',
50                 title : 'Bullet list'
51             },
52             'insertorderedlist' : {
53                 icon : 'fa fa-list-ol',
54                 title : 'Number list'
55             },
56             'outdent' : {
57                 icon : 'fa fa-outdent',
58                 title : 'Reduce indent (Shift+Tab)'
59             },
60             'indent' : {
61                 icon : 'fa fa-indent',
62                 title : 'Indent (Tab)'
63             },
64             'justifyleft' : {
65                 icon : 'fa fa-align-left',
66                 title : 'Align Left (Ctrl/Cmd+L)'
67             },
68             'justifycenter' : {
69                 icon : 'fa fa-align-center',
70                 title : 'Center (Ctrl/Cmd+E)'
71             },
72             'justifyright' : {
73                 icon : 'fa fa-align-right',
74                 title : 'Align Right (Ctrl/Cmd+R)'
75             },
76             'justifyfull' : {
77                 icon : 'fa fa-align-justify',
78                 title : 'Justify (Ctrl/Cmd+J)'
79             },
80             'createLink' : {
81                 icon : 'fa fa-link',
82                 title : 'Hyperlink',
83                 button_text : 'Add',
84                 placeholder : 'URL',
85                 button_class : 'btn-primary'
86             },
87             'unlink' : {
88                 icon : 'fa fa-chain-broken',
89                 title : 'Remove Hyperlink'
90             },
91             'insertImage' : {
92                 icon : 'fa fa-picture-o',
93                 title : 'Insert picture',
94                 button_text : '<i class="'+ ace.vars['icon'] + 'fa fa-file"></i> Choose Image &hellip;',
95                 placeholder : 'Image URL',
96                 button_insert : 'Insert',
97                 button_class : 'btn-success',
98                 button_insert_class : 'btn-primary',
99                 choose_file: true //show the choose file button?
100             },
101             'foreColor' : {
102                 values : color_values,
103                 title : 'Change Color'
104             },
105             'backColor' : {
106                 values : color_values,
107                 title : 'Change Background Color'
108             },
109             'undo' : {
110                 icon : 'fa fa-undo',
111                 title : 'Undo (Ctrl/Cmd+Z)'
112             },
113             'redo' : {
114                 icon : 'fa fa-repeat',
115                 title : 'Redo (Ctrl/Cmd+Y)'
116             },
117             'viewSource' : {
118                 icon : 'fa fa-code',
119                 title : 'View Source'
120             }
121         }
122         
123         var toolbar_buttons =
124         options.toolbar ||
125         [
126             'font',
127             null,
128             'fontSize',
129             null,
130             'bold',
131             'italic',
132             'strikethrough',
133             'underline',
134             null,
135             'insertunorderedlist',
136             'insertorderedlist',
137             'outdent',
138             'indent',
139             null,
140             'justifyleft',
141             'justifycenter',
142             'justifyright',
143             'justifyfull',
144             null,
145             'createLink',
146             'unlink',
147             null,
148             'insertImage',
149             null,
150             'foreColor',
151             null,
152             'undo',
153             'redo',
154             null,
155             'viewSource'
156         ]
157
158
159         this.each(function() {
160             var toolbar = ' <div class="wysiwyg-toolbar btn-toolbar center"> <div class="btn-group"> ';
161
162             for(var tb in toolbar_buttons) if(toolbar_buttons.hasOwnProperty(tb)) {
163                 var button = toolbar_buttons[tb];
164                 if(button === null){
165                     toolbar += ' </div> <div class="btn-group"> ';
166                     continue;
167                 }
168                 
169                 if(typeof button == "string" && button in button_defaults) {
170                     button = button_defaults[button];
171                     button.name = toolbar_buttons[tb];
172                 } else if(typeof button == "object" && button.name in button_defaults) {
173                     button = $.extend(button_defaults[button.name] , button);
174                 }
175                 else continue;
176                 
177                 var className = "className" in button ? button.className : 'btn-default';
178                 switch(button.name) {
179                     case 'font':
180                         toolbar += ' <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i><i class="' + ace.vars['icon'] + 'fa fa-angle-down icon-on-right"></i></a> ';
181                         toolbar += ' <ul class="dropdown-menu dropdown-light dropdown-caret">';
182                         for(var font in button.values)
183                             if(button.values.hasOwnProperty(font))
184                                 toolbar += ' <li><a data-edit="fontName ' + button.values[font] +'" style="font-family:\''+ button.values[font]  +'\'">'+button.values[font]  + '</a></li> '
185                         toolbar += ' </ul>';
186                     break;
187
188                     case 'fontSize':
189                         toolbar += ' <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i>&nbsp;<i class="'+ ace.vars['icon'] + 'fa fa-angle-down icon-on-right"></i></a> ';
190                         toolbar += ' <ul class="dropdown-menu dropdown-light dropdown-caret"> ';
191                         for(var size in button.values)
192                             if(button.values.hasOwnProperty(size))
193                                 toolbar += ' <li><a data-edit="fontSize '+size+'"><font size="'+size+'">'+ button.values[size] +'</font></a></li> '
194                         toolbar += ' </ul> ';
195                     break;
196
197                     case 'createLink':
198                         toolbar += ' <div class="btn-group"> <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
199                         toolbar += ' <div class="dropdown-menu dropdown-caret dropdown-menu-right">\
200                              <div class="input-group">\
201                                 <input class="form-control" placeholder="'+button.placeholder+'" type="text" data-edit="'+button.name+'" />\
202                                 <span class="input-group-btn">\
203                                     <button class="btn btn-sm '+button.button_class+'" type="button">'+button.button_text+'</button>\
204                                 </span>\
205                              </div>\
206                         </div> </div>';
207                     break;
208
209                     case 'insertImage':
210                         toolbar += ' <div class="btn-group"> <a class="btn btn-sm '+className+' dropdown-toggle" data-toggle="dropdown" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
211                         toolbar += ' <div class="dropdown-menu dropdown-caret dropdown-menu-right">\
212                              <div class="input-group">\
213                                 <input class="form-control" placeholder="'+button.placeholder+'" type="text" data-edit="'+button.name+'" />\
214                                 <span class="input-group-btn">\
215                                     <button class="btn btn-sm '+button.button_insert_class+'" type="button">'+button.button_insert+'</button>\
216                                 </span>\
217                              </div>';
218                             if( button.choose_file && 'FileReader' in window ) toolbar +=
219                              '<div class="space-2"></div>\
220                              <label class="center block no-margin-bottom">\
221                                 <button class="btn btn-sm '+button.button_class+' wysiwyg-choose-file" type="button">'+button.button_text+'</button>\
222                                 <input type="file" data-edit="'+button.name+'" />\
223                               </label>'
224                         toolbar += ' </div> </div>';
225                     break;
226
227                     case 'foreColor':
228                     case 'backColor':
229                         toolbar += ' <select class="hide wysiwyg_colorpicker" title="'+button.title+'"> ';
230                         $.each(button.values, function (_, color) {
231                             toolbar += ' <option value="' + color + '">' + color + '</option> ';
232                         });
233                         toolbar += ' </select> ';
234                         toolbar += ' <input style="display:none;" disabled class="hide" type="text" data-edit="'+button.name+'" /> ';
235                     break;
236
237                     case 'viewSource':
238                         toolbar += ' <a class="btn btn-sm '+className+'" data-view="source" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
239                     break;
240                     default:
241                         toolbar += ' <a class="btn btn-sm '+className+'" data-edit="'+button.name+'" title="'+button.title+'"><i class="'+ ace.vars['icon'] + button.icon+'"></i></a> ';
242                     break;
243                 }
244             }
245             toolbar += ' </div> ';
246             ////////////
247             var speech_input;
248             if (options.speech_button && 'onwebkitspeechchange' in (speech_input = document.createElement('input'))) {
249                 toolbar += ' <input class="wysiwyg-speech-input" type="text" data-edit="inserttext" x-webkit-speech />';
250             }
251             speech_input = null;
252             ////////////
253             toolbar += ' </div> ';
254
255
256             //if we have a function to decide where to put the toolbar, then call that
257             if(options.toolbar_place) toolbar = options.toolbar_place.call(this, toolbar);
258             //otherwise put it just before our DIV
259             else toolbar = $(this).before(toolbar).prev();
260
261             toolbar.find('a[title]').tooltip({animation:false, container:'body'});
262             toolbar.find('.dropdown-menu input[type=text]').on('click', function() {return false})
263             .on('change', function() {$(this).closest('.dropdown-menu').siblings('.dropdown-toggle').dropdown('toggle')})
264             .on('keydown', function (e) {
265                 if(e.which == 27) {
266                     this.value = '';
267                     $(this).change();
268                 }
269                 else if(e.which == 13) {
270                     e.preventDefault();
271                     e.stopPropagation();
272                     $(this).change();
273                 }
274             });
275             
276             toolbar.find('input[type=file]').prev().on(ace.click_event, function (e) { 
277                 $(this).next().click();
278             });
279             toolbar.find('.wysiwyg_colorpicker').each(function() {
280                 $(this).ace_colorpicker({pull_right:true}).change(function(){
281                     $(this).nextAll('input').eq(0).val(this.value).change();
282                 }).next().find('.btn-colorpicker').tooltip({title: this.title, animation:false, container:'body'})
283             });
284             
285             
286             var self = $(this);
287             //view source
288             var view_source = false;
289             toolbar.find('a[data-view=source]').on('click', function(e){
290                 e.preventDefault();
291                 
292                 if(!view_source) {
293                     $('<textarea />')
294                     .css({'width':self.outerWidth(), 'height':self.outerHeight()})
295                     .val(self.html())
296                     .insertAfter(self)
297                     self.hide();
298                     
299                     $(this).addClass('active');
300                 }
301                 else {
302                     var textarea = self.next();
303                     self.html(textarea.val()).show();
304                     textarea.remove();
305                     
306                     $(this).removeClass('active');
307                 }
308                 
309                 view_source = !view_source;
310             });
311
312
313             var $options = $.extend({}, { activeToolbarClass: 'active' , toolbarSelector : toolbar }, options.wysiwyg || {})
314             $(this).wysiwyg( $options );
315         });
316
317         return this;
318     }
319
320
321 })(window.jQuery);
322