1 /*==============================================================================
2 This Wikiwyg mode supports a DesignMode wysiwyg editor with toolbar buttons
6 Copyright (c) 2005 Socialtext Corporation
8 Palo Alto, CA 94301 U.S.A.
11 Wikiwyg is free software.
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.
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.
23 http://www.gnu.org/copyleft/lesser.txt
25 =============================================================================*/
27 proto = new Subclass('Wikiwyg.Wysiwyg', 'Wikiwyg.Mode');
29 proto.classtype = 'wysiwyg';
30 proto.modeDescription = 'Wysiwyg';
33 useParentStyles: true,
34 useStyleMedia: 'wikiwyg',
37 disabledToolbarButtons: [],
38 editHeightMinimum: 150,
39 editHeightAdjustment: 1.3,
43 proto.initializeObject = function() {
44 this.edit_iframe = this.get_edit_iframe();
45 this.div = this.edit_iframe;
46 this.set_design_mode_early();
49 proto.set_design_mode_early = function() { // Se IE, below
53 proto.fromHtml = function(html) {
55 html = html.replace(/\n/g,'<br>') ;
56 this.set_inner_html(html);
59 proto.toHtml = function(func) {
60 func(this.get_inner_html());
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);
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();
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('');
93 proto.get_keybinding_area = function() {
94 return this.get_edit_document();
97 proto.get_edit_iframe = function() {
99 if (this.config.iframeId) {
100 iframe = document.getElementById(this.config.iframeId);
101 iframe.iframe_hack = true;
103 else if (this.config.iframeObject) {
104 iframe = this.config.iframeObject;
105 iframe.iframe_hack = true;
108 // XXX in IE need to wait a little while for iframe to load up
109 iframe = document.createElement('iframe');
114 proto.get_edit_window = function() { // See IE, below
115 return this.edit_iframe.contentWindow;
118 proto.get_edit_document = function() { // See IE, below
119 return this.get_edit_window().document;
122 proto.get_inner_html = function() {
123 return this.get_edit_document().body.innerHTML;
125 proto.set_inner_html = function(html) {
126 this.get_edit_document().body.innerHTML = html;
129 proto.apply_stylesheets = function(styles) {
130 var styles = document.styleSheets;
131 var head = this.get_edit_document().getElementsByTagName("head")[0];
133 for (var i = 0; i < styles.length; i++) {
134 var style = styles[i];
136 if (style.href == location.href)
137 this.apply_inline_stylesheet(style, head);
139 if (this.should_link_stylesheet(style))
140 this.apply_linked_stylesheet(style, head);
144 proto.apply_inline_stylesheet = function(style, head) {
145 // TODO: figure this out
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;
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
162 proto.apply_linked_stylesheet = function(style, head) {
163 var link = Wikiwyg.createElementWithAttrs(
169 }, this.get_edit_document()
171 head.appendChild(link);
174 proto.process_command = function(command) {
175 if (this['do_' + command])
176 this['do_' + command](command);
178 this.get_edit_window().focus();
181 proto.exec_command = function(command, option) {
182 this.get_edit_document().execCommand(command, false, option);
185 proto.format_command = function(command) {
186 this.exec_command('formatblock', '<' + command + '>');
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');
195 proto.do_hr = function() {
196 this.exec_command('inserthorizontalrule');
198 proto.do_ordered = function() {
199 this.exec_command('insertorderedlist');
201 proto.do_unordered = function() {
202 this.exec_command('insertunorderedlist');
204 proto.do_indent = proto.exec_command;
205 proto.do_outdent = proto.exec_command;
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;
216 proto.do_table = function() {
218 '<table border="5"><tbody>' +
222 '<tr><td> </td><td> </td><td> </td></tr>' +
223 '<tr><td> </td><td> </td><td> </td></tr>' +
226 this.get_edit_window().focus();
227 this.insert_table(html);
230 proto.insert_table = function(html) { // See IE
231 this.exec_command('inserthtml', html);
234 proto.do_link = function() {
235 var selection = this.get_link_selection_text();
236 if (! selection) return;
238 var match = selection.match(/(.*?)\b((?:http|https|ftp|irc):\/\/\S+)(.*)/);
240 if (match[1] || match[3]) return null;
244 url = '?' + escape(selection);
246 this.exec_command('createlink', url);
249 proto.get_selection_text = function() { // See IE, below
250 return this.get_edit_window().getSelection().toString();
253 proto.get_link_selection_text = function() {
254 var selection = this.get_selection_text();
256 alert("Please select the text you would like to turn into a link.");
262 /*==============================================================================
263 Support for Internet Explorer in Wikiwyg.Wysiwyg
264 =============================================================================*/
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';
272 proto.get_edit_window = function() {
273 return this.edit_iframe;
276 proto.get_edit_document = function() {
277 return this.edit_iframe.contentWindow.document;
280 proto.get_selection_text = function() {
281 var selection = this.get_edit_document().selection;
282 if (selection != null)
283 return selection.createRange().htmlText;
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)
292 range.pasteHTML(html);
293 range.collapse(false);
297 // Use IE's design mode default key bindings for now.
298 proto.enable_keybindings = function() {}
300 } // end of global if