]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - themes/default/Wikiwyg/Wikiwyg/Wysiwyg.js
added wysiwyg_editor-1.3a feature by Jean-Nicolas GEREONE <jean-nicolas.gereone@st...
[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     clearRegex: null
41 };
42     
43 proto.initializeObject = function() {
44     this.edit_iframe = this.get_edit_iframe();
45     this.div = this.edit_iframe;
46     this.set_design_mode_early();
47 }
48
49 proto.set_design_mode_early = function() { // Se IE, below
50     // Unneeded for Gecko
51 }
52
53 proto.fromHtml = function(html) {
54
55     html = html.replace(/\n/g,'<br>') ;
56     this.set_inner_html(html);
57 }
58
59 proto.toHtml = function(func) {
60   func(this.get_inner_html());
61 }
62
63 // This is needed to work around the broken IMGs in Firefox design mode.
64 // Works harmlessly on IE, too.
65 // TODO - IMG URLs that don't match /^\//
66 proto.fix_up_relative_imgs = function() {
67     var base = location.href.replace(/(.*?:\/\/.*?\/).*/, '$1');
68     var imgs = this.get_edit_document().getElementsByTagName('img');
69     for (var ii = 0; ii < imgs.length; ++ii)
70         imgs[ii].src = imgs[ii].src.replace(/^\//, base);
71 }
72
73 proto.enableThis = function() {
74     this.superfunc('enableThis').call(this);
75     this.edit_iframe.style.border = '1px black solid';
76     this.edit_iframe.width = '100%';
77     this.setHeightOf(this.edit_iframe);
78     this.fix_up_relative_imgs();
79     this.get_edit_document().designMode = 'on';
80     // XXX - Doing stylesheets in initializeObject might get rid of blue flash
81     this.apply_stylesheets();
82     this.enable_keybindings();
83     this.clear_inner_html();
84 }
85
86 proto.clear_inner_html = function() {
87     var inner_html = this.get_inner_html();
88     var clear = this.config.clearRegex;
89     if (clear && inner_html.match(clear))
90         this.set_inner_html('');
91 }
92
93 proto.get_keybinding_area = function() {
94     return this.get_edit_document();
95 }
96
97 proto.get_edit_iframe = function() {
98     var iframe;
99     if (this.config.iframeId) {
100         iframe = document.getElementById(this.config.iframeId);
101         iframe.iframe_hack = true;
102     }
103     else if (this.config.iframeObject) {
104         iframe = this.config.iframeObject;
105         iframe.iframe_hack = true;
106     }
107     else {
108         // XXX in IE need to wait a little while for iframe to load up
109         iframe = document.createElement('iframe');
110     }
111     return iframe;
112 }
113
114 proto.get_edit_window = function() { // See IE, below
115     return this.edit_iframe.contentWindow;
116 }
117
118 proto.get_edit_document = function() { // See IE, below
119     return this.get_edit_window().document;
120 }
121
122 proto.get_inner_html = function() {
123     return this.get_edit_document().body.innerHTML;
124 }
125 proto.set_inner_html = function(html) {
126     this.get_edit_document().body.innerHTML = html;
127 }
128
129 proto.apply_stylesheets = function(styles) {
130     var styles = document.styleSheets;
131     var head   = this.get_edit_document().getElementsByTagName("head")[0];
132
133     for (var i = 0; i < styles.length; i++) {
134         var style = styles[i];
135
136         if (style.href == location.href)
137             this.apply_inline_stylesheet(style, head);
138         else
139             if (this.should_link_stylesheet(style))
140                 this.apply_linked_stylesheet(style, head);
141     }
142 }
143
144 proto.apply_inline_stylesheet = function(style, head) {
145     // TODO: figure this out
146 }
147
148 proto.should_link_stylesheet = function(style, head) {
149         var media = style.media;
150         var config = this.config;
151         var media_text = media.mediaText ? media.mediaText : media;
152         var use_parent =
153              ((!media_text || media_text == 'screen') &&
154              config.useParentStyles);
155         var use_style = (media_text && (media_text == config.useStyleMedia));
156         if (!use_parent && !use_style) // TODO: simplify
157             return false;
158         else
159             return true;
160 }
161
162 proto.apply_linked_stylesheet = function(style, head) {
163     var link = Wikiwyg.createElementWithAttrs(
164         'link', {
165             href:  style.href,
166             type:  style.type,
167             media: 'screen',
168             rel:   'STYLESHEET'
169         }, this.get_edit_document()
170     );
171     head.appendChild(link);
172 }
173
174 proto.process_command = function(command) {
175     if (this['do_' + command])
176         this['do_' + command](command);
177     if (! Wikiwyg.is_ie)
178         this.get_edit_window().focus();
179 }
180
181 proto.exec_command = function(command, option) {
182     this.get_edit_document().execCommand(command, false, option);
183 }
184
185 proto.format_command = function(command) {
186     this.exec_command('formatblock', '<' + command + '>');
187 }
188
189 proto.do_bold = proto.exec_command;
190 proto.do_italic = proto.exec_command;
191 proto.do_underline = proto.exec_command;
192 proto.do_strike = function() {
193     this.exec_command('strikethrough');
194 }
195 proto.do_hr = function() {
196     this.exec_command('inserthorizontalrule');
197 }
198 proto.do_ordered = function() {
199     this.exec_command('insertorderedlist');
200 }
201 proto.do_unordered = function() {
202     this.exec_command('insertunorderedlist');
203 }
204 proto.do_indent = proto.exec_command;
205 proto.do_outdent = proto.exec_command;
206
207 proto.do_h1 = proto.format_command;
208 proto.do_h2 = proto.format_command;
209 proto.do_h3 = proto.format_command;
210 proto.do_h4 = proto.format_command;
211 proto.do_h5 = proto.format_command;
212 proto.do_h6 = proto.format_command;
213 proto.do_pre = proto.format_command;
214 proto.do_p = proto.format_command;
215
216 proto.do_table = function() {
217     var html =
218         '<table border="5"><tbody>' +
219         '<tr><td>A</td>' +
220             '<td>B</td>' +
221             '<td>C</td></tr>' +
222         '<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>' +
223         '<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>' +
224         '</tbody></table>';
225     if (! Wikiwyg.is_ie)
226         this.get_edit_window().focus();
227     this.insert_table(html);
228 }
229
230 proto.insert_table = function(html) { // See IE
231     this.exec_command('inserthtml', html);
232 }
233
234 proto.do_link = function() {
235     var selection = this.get_link_selection_text();
236     if (! selection) return;
237     var url;
238     var match = selection.match(/(.*?)\b((?:http|https|ftp|irc):\/\/\S+)(.*)/);
239     if (match) {
240         if (match[1] || match[3]) return null;
241         url = match[2];
242     }
243     else {
244         url = '?' + escape(selection); 
245     }
246     this.exec_command('createlink', url);
247 }
248
249 proto.get_selection_text = function() { // See IE, below
250     return this.get_edit_window().getSelection().toString();
251 }
252
253 proto.get_link_selection_text = function() {
254     var selection = this.get_selection_text();
255     if (! selection) {
256         alert("Please select the text you would like to turn into a link.");
257         return;
258     }
259     return selection;
260 }
261
262 /*==============================================================================
263 Support for Internet Explorer in Wikiwyg.Wysiwyg
264  =============================================================================*/
265 if (Wikiwyg.is_ie) {
266
267 proto.set_design_mode_early = function(wikiwyg) {
268     // XXX - need to know if iframe is ready yet...
269     this.get_edit_document().designMode = 'on';
270 }
271
272 proto.get_edit_window = function() {
273     return this.edit_iframe;
274 }
275
276 proto.get_edit_document = function() {
277     return this.edit_iframe.contentWindow.document;
278 }
279
280 proto.get_selection_text = function() {
281     var selection = this.get_edit_document().selection;
282     if (selection != null)
283         return selection.createRange().htmlText;
284     return '';
285 }
286
287 proto.insert_table = function(html) {
288     var doc = this.get_edit_document();
289     var range = this.get_edit_document().selection.createRange();
290     if (range.boundingTop == 2 && range.boundingLeft == 2)
291         return;
292     range.pasteHTML(html);
293     range.collapse(false);
294     range.select();
295 }
296
297 // Use IE's design mode default key bindings for now.
298 proto.enable_keybindings = function() {}
299
300 } // end of global if