]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - themes/default/Wikiwyg/Wikiwyg/Wysiwyg.js
Allow bold, italics or underlined for numbers
[SourceForge/phpwiki.git] / themes / default / Wikiwyg / Wikiwyg / Wysiwyg.js
1 /*==============================================================================
2 This Wikiwyg mode supports a DesignMode wysiwyg editor with toolbar buttons
3
4 COPYRIGHT:
5
6     Copyright (c) 2005 Socialtext Corporation 
7     655 High Street
8     Palo Alto, CA 94301 U.S.A.
9     All rights reserved.
10
11 Wikiwyg is free software. 
12
13 This library is free software; you can redistribute it and/or modify it
14 under the terms of the GNU Lesser General Public License as published by
15 the Free Software Foundation; either version 2.1 of the License, or (at
16 your option) any later version.
17
18 This library is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
21 General Public License for more details.
22
23     http://www.gnu.org/copyleft/lesser.txt
24
25  =============================================================================*/
26
27 proto = new Subclass('Wikiwyg.Wysiwyg', 'Wikiwyg.Mode');
28
29 proto.classtype = 'wysiwyg';
30 proto.modeDescription = 'Wysiwyg';
31
32 proto.config = {
33     useParentStyles: true,
34     useStyleMedia: 'wikiwyg',
35     iframeId: null,
36     iframeObject: null,
37     disabledToolbarButtons: [],
38     editHeightMinimum: 150,
39     editHeightAdjustment: 1.3,
40     editHeightOffset: 500,
41     clearRegex: null
42 };
43     
44 proto.initializeObject = function() {
45     this.edit_iframe = this.get_edit_iframe();
46     this.div = this.edit_iframe;
47     this.set_design_mode_early();
48 }
49
50 proto.set_design_mode_early = function() { // Se IE, below
51     // Unneeded for Gecko
52 }
53
54 proto.fromHtml = function(html) {
55     this.set_inner_html(html);
56 }
57
58 // Added to allow wysiwyg mode by default
59 proto.fromWikitext = function(wikitext) {
60   var editiframe = this.get_edit_document();
61
62   this.wikiwyg.call_action('wikiwyg_wikitext_to_html', wikitext, 
63                            function(html) {editiframe.body.innerHTML = html;} );
64 }
65
66 proto.toHtml = function(func) {
67   func(this.get_inner_html());
68 }
69
70 // This is needed to work around the broken IMGs in Firefox design mode.
71 // Works harmlessly on IE, too.
72 // TODO - IMG URLs that don't match /^\//
73 proto.fix_up_relative_imgs = function() {
74     var base = location.href.replace(/(.*?:\/\/.*?\/).*/, '$1');
75     var imgs = this.get_edit_document().getElementsByTagName('img');
76     for (var ii = 0; ii < imgs.length; ++ii)
77         imgs[ii].src = imgs[ii].src.replace(/^\//, base);
78 }
79
80 proto.enableThis = function() {
81     this.superfunc('enableThis').call(this);
82     this.edit_iframe.style.border = '1px black solid';
83     this.edit_iframe.width = '100%';
84     this.setHeightOf(this.edit_iframe);
85     this.fix_up_relative_imgs();
86     this.get_edit_document().designMode = 'on';
87     // XXX - Doing stylesheets in initializeObject might get rid of blue flash
88     //    this.apply_stylesheets();
89     this.enable_keybindings();
90     this.clear_inner_html();
91 }
92
93 proto.clear_inner_html = function() {
94     var inner_html = this.get_inner_html();
95     var clear = this.config.clearRegex;
96     if (clear && inner_html.match(clear))
97         this.set_inner_html('');
98 }
99
100 proto.get_keybinding_area = function() {
101     return this.get_edit_document();
102 }
103
104 proto.get_edit_iframe = function() {
105     var iframe;
106     if (this.config.iframeId) {
107         iframe = document.getElementById(this.config.iframeId);
108         iframe.iframe_hack = true;
109     }
110     else if (this.config.iframeObject) {
111         iframe = this.config.iframeObject;
112         iframe.iframe_hack = true;
113     }
114     else {
115         // XXX in IE need to wait a little while for iframe to load up
116         iframe = document.createElement('iframe');
117     }
118     return iframe;
119 }
120
121 proto.get_edit_window = function() { // See IE, below
122     return this.edit_iframe.contentWindow;
123 }
124
125 proto.get_edit_document = function() { // See IE, below
126     return this.get_edit_window().document;
127 }
128
129 proto.get_inner_html = function() {
130     return this.get_edit_document().body.innerHTML;
131 }
132 proto.set_inner_html = function(html) {
133     this.get_edit_document().body.innerHTML = html;
134 }
135
136 proto.apply_stylesheets = function(styles) {
137     var styles = document.styleSheets;
138     var head   = this.get_edit_document().getElementsByTagName("head")[0];
139
140     for (var i = 0; i < styles.length; i++) {
141         var style = styles[i];
142
143         if (style.href == location.href)
144             this.apply_inline_stylesheet(style, head);
145         else
146             if (this.should_link_stylesheet(style))
147                 this.apply_linked_stylesheet(style, head);
148     }
149 }
150
151 proto.apply_inline_stylesheet = function(style, head) {
152     // TODO: figure this out
153 }
154
155 proto.should_link_stylesheet = function(style, head) {
156         var media = style.media;
157         var config = this.config;
158         var media_text = media.mediaText ? media.mediaText : media;
159         var use_parent =
160              ((!media_text || media_text == 'screen') &&
161              config.useParentStyles);
162         var use_style = (media_text && (media_text == config.useStyleMedia));
163         if (!use_parent && !use_style) // TODO: simplify
164             return false;
165         else
166             return true;
167 }
168
169 proto.apply_linked_stylesheet = function(style, head) {
170     var link = Wikiwyg.createElementWithAttrs(
171         'link', {
172             href:  style.href,
173             type:  style.type,
174             media: 'screen',
175             rel:   'STYLESHEET'
176         }, this.get_edit_document()
177     );
178     head.appendChild(link);
179 }
180
181 proto.process_command = function(command) {
182     if (this['do_' + command])
183         this['do_' + command](command);
184     if (! Wikiwyg.is_ie)
185         this.get_edit_window().focus();
186 }
187
188 proto.exec_command = function(command, option) {
189     this.get_edit_document().execCommand(command, false, option);
190 }
191
192 proto.format_command = function(command) {
193     this.exec_command('formatblock', '<' + command + '>');
194 }
195
196 proto.do_bold = proto.exec_command;
197 proto.do_italic = proto.exec_command;
198 proto.do_underline = proto.exec_command;
199 proto.do_strike = function() {
200     this.exec_command('strikethrough');
201 }
202 proto.do_hr = function() {
203     this.exec_command('inserthorizontalrule');
204 }
205 proto.do_ordered = function() {
206     this.exec_command('insertorderedlist');
207 }
208 proto.do_unordered = function() {
209     this.exec_command('insertunorderedlist');
210 }
211 proto.do_indent = proto.exec_command;
212 proto.do_outdent = proto.exec_command;
213
214 proto.do_h1 = proto.format_command;
215 proto.do_h2 = proto.format_command;
216 proto.do_h3 = proto.format_command;
217 proto.do_h4 = proto.format_command;
218 proto.do_h5 = proto.format_command;
219 proto.do_h6 = proto.format_command;
220 proto.do_pre = proto.format_command;
221 proto.do_p = proto.format_command;
222
223 proto.do_table = function() {
224   var rows = prompt("Number of rows", '2');
225   if(rows == null)
226     return;
227   var cols = prompt("Number of columns", '2');
228   if(cols == null)
229     return;
230
231     // Test if variables are valid numbers
232     if( isNaN(rows) == true || isNaN(cols) == true 
233         ||(rows = parseInt(rows).toFixed(0)) <= 0
234         ||(cols = parseInt(cols).toFixed(0)) <= 0)
235       {
236         alert("Please enter positive numbers");
237         return false;
238       }
239
240     var html = 
241     '<table border="5"><tbody>';
242   
243     for(i=0; i<rows;i++) {
244       html = html + "<tr>";
245       for(var j=0;j<cols;j++) {
246         html = html + "<td>&nbsp;</td>";
247        }
248       html = html + "</tr>";
249     }
250
251     html = html + "<tbody></table>";
252    
253     if (! Wikiwyg.is_ie)
254         this.get_edit_window().focus();
255     this.insert_table(html);
256 }
257
258 proto.insert_table = function(html) { // See IE
259     this.exec_command('inserthtml', html);
260 }
261
262 proto.do_toc = function() {
263     var html = '<p><div style="background-color:#D3D3D3;font-size:smaller;">'+
264                'Wikitext { <br> &lt;?plugin  CreateToc  ?&gt; <br>}</div></p>';
265     this.insert_html(html);
266 }
267
268 proto.do_wikitext = function() {
269     var html = '<p><div style="background-color:#D3D3D3;font-size:smaller;">'+
270                'Wikitext { <br>  <br>}</div></p>';
271     this.insert_html(html);
272 }
273
274 proto.insert_html = function(html) { // See IE
275     this.exec_command('inserthtml', html);
276 }
277
278 proto.do_link = function() {
279     var selection = this.get_link_selection_text();
280     if (! selection) return;
281
282     var url = "";
283     var url_selection = "";
284
285     if(Wikiwyg.is_ie) {
286       url_selection = this.get_edit_document().selection.createRange().htmlText;
287     }
288     else {
289       if(this.get_edit_window().getSelection())
290         url_selection = this.get_edit_window().getSelection();
291     }
292
293     // If IE, 
294     if(Wikiwyg.is_ie) {
295       var tmp_match = url_selection.match(/href=.*/m);
296       if(tmp_match!=null) {
297         var toreplace = /.*href=\"(.*?)\".*/m;
298         url = tmp_match.toString().replace(toreplace,'$1');
299       }
300     }
301     else {
302       // If gecko
303       if(url_selection.focusNode.innerHTML) {
304         var reg_match = new RegExp('(href=\".*?\".*?'
305                                     +unescape(selection)
306                                     +').*?\/a\>','m');
307         var tmp_match = url_selection.focusNode.innerHTML.match(reg_match);
308         if(tmp_match!=null) {
309           var toreplace = /.*href=\"(.*?)\".*/m;
310           url = tmp_match.toString().replace(toreplace,'$1');
311         }
312       }
313     }
314
315     url = prompt('Enter the URL. No URL will remove the link.',unescape(url));
316     if(url==null)
317       return;
318     else if (url) {
319       this.exec_command('Unlink');
320       this.exec_command('CreateLink',url);
321       this.exec_command('ForeColor','blue');
322     }
323     else if(!url) {// No URL entered by the user
324       this.exec_command('Unlink');
325       this.exec_command('ForeColor','black');
326     }
327 }
328
329 proto.get_selection_text = function() { // See IE, below
330     return this.get_edit_window().getSelection().toString();
331 }
332
333 proto.get_link_selection_text = function() {
334     var selection = this.get_selection_text();
335     if (! selection) {
336         alert("Please select the text you would like to turn into a link.");
337         return;
338     }
339     return selection;
340 }
341
342 proto.do_sup = function() {
343   this.exec_command('SuperScript');
344 }
345
346 proto.do_sub = function() {
347   this.exec_command('SubScript');
348 }
349
350 proto.do_preview = function() {
351     this.wikiwyg.previewChanges_button();
352 }
353
354 proto.do_save_button = function() {
355     this.wikiwyg.saveChanges_button();
356 }
357
358 /*==============================================================================
359 Support for Internet Explorer in Wikiwyg.Wysiwyg
360  =============================================================================*/
361 if (Wikiwyg.is_ie) {
362
363 proto.set_design_mode_early = function(wikiwyg) {
364     // XXX - need to know if iframe is ready yet...
365     this.get_edit_document().designMode = 'on';
366 }
367
368 proto.get_edit_window = function() {
369     return this.edit_iframe;
370 }
371
372 proto.get_edit_document = function() {
373     return this.edit_iframe.contentWindow.document;
374 }
375
376 proto.get_selection_text = function() {
377     var selection = this.get_edit_document().selection;
378     if (selection != null)
379         return selection.createRange().htmlText;
380     return '';
381 }
382
383 proto.insert_table = function(html) {
384     var doc = this.get_edit_document();
385     var range = this.get_edit_document().selection.createRange();
386
387     if(range.parentElement().isContentEditable == false){
388       alert("Please click where you want to insert the table"); 
389       return;
390     }
391
392     if (range.boundingTop == 2 && range.boundingLeft == 2)
393         return;
394     range.pasteHTML(html);
395     range.collapse(false);
396     range.select();
397 }
398
399 proto.insert_html = function(html) {
400     var doc = this.get_edit_document();
401     var range = this.get_edit_document().selection.createRange();
402
403     if(range.parentElement().isContentEditable == false){
404       alert("Please click in the edit area"); 
405       return;
406     }
407
408     if (range.boundingTop == 2 && range.boundingLeft == 2)
409         return;
410     range.pasteHTML(html);
411     range.collapse(false);
412     range.select();
413 }
414
415 // Use IE's design mode default key bindings for now.
416 proto.enable_keybindings = function() {}
417
418 } // end of global if