/[drupal]/contributions/modules/htmlbox/htmlbox.js
ViewVC logotype

Contents of /contributions/modules/htmlbox/htmlbox.js

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.8 - (show annotations) (download) (as text)
Thu Jul 17 20:53:24 2008 UTC (16 months, 1 week ago) by poetro
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +6 -6 lines
File MIME type: text/javascript
Updating to the latest and greatest
CSS fix for http://drupal.org/node/283346
New Drag-and-Drop feature to compose the Button order
Little JS fixes
1 // $Id: htmlbox.js,v 1.1.2.1 2008/07/03 23:41:45 poetro Exp $
2
3 /**
4 * Copyright (c) 2008 Peter Galiba <pgaliba@nowpublic.com>
5 *
6 * This file is free software: you may copy, redistribute and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 * This file is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * This file incorporates work covered by the following copyright and
20 * permission notice:
21 *
22 * Copyright (c) 2008 Remiya Solutions (http://remiya.com)
23 *
24 * Permission to use, copy, modify, and/or distribute this software
25 * for any purpose with or without fee is hereby granted, provided
26 * that the above copyright notice and this permission notice appear
27 * in all copies.
28 *
29 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
30 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
31 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
32 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
33 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
34 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
35 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
36 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37 */
38
39 $.fn.htmlbox = function() {
40 if (undefined === window.glob_ha) {
41 glob_ha = [];
42 }
43
44 var d = {
45 buttons: [],
46 rows: [],
47 images: [],
48 dir: "./images/",
49 output: "xhtml"
50 };
51
52 var xhtml = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body>INITIAL_CONTENT</body></html>';
53
54 if (!$(this).attr("id")) {
55 $(this).attr("id", "jqha_"+ glob_ha.length);
56 d.id = "jqha_"+ glob_ha.length;
57 glob_ha[glob_ha] = glob_ha;
58 } else {
59 d.id = $(this).attr("id");
60 }
61
62 if (undefined === glob_ha[d.id]) {
63 glob_ha[d.id] = this;
64 }
65
66 /**
67 * Initialize the editor
68 * @param is_init Specifies, whether the editor should initialize at once, or after some timeout.
69 */
70 this.init = function(is_init) {
71 var exception;
72 if ($(this).size() === 0) {
73 return this;
74 }
75 // START: Timeout to allow creation of DesignMode
76 if (undefined === is_init) {
77 setTimeout("glob_ha['"+ d.id +"'].init(true)", 250);
78 return false;
79 }
80 // END: Timeout to allow creation of DesignMode
81
82 if (Drupal !== undefined && Drupal.settings != undefined && Drupal.settings.htmlbox !== undefined) {
83 this.newline_removal = Drupal.settings.htmlbox.newline_removal;
84 }
85 else {
86 this.newline_removal = true;
87 }
88
89 // Prepare the HTMLBox area
90 var w = $(this).width();
91 var h = $(this).height();
92 $(this).wrap("<div class='htmlbox' style='width: "+ w +"px; height:"+ h +"px;'><div class='htmlbox-area'></div></div>");
93 // START: Appending toolbar
94 $(this).parent().append(toolbar());
95 $("."+ d.id +"_tb").css('width', w-6 +"px").find("button").each(function() {
96 $(this).mouseover(function() {
97 $(this).css("border", "1px solid #BFCAFF").css("background-color", "#EFF2FF");
98 });
99 $(this).mouseout(function() {
100 $(this).css("border", "1px solid #E9EAEF").css("background-color", "transparent");
101 });
102 }).end().find("select").each(function() {
103 $(this).css("border", "1px solid #E9EAEF").css("background-color", "transparent").css("margin", "2px 2px 3px 2px");
104 if ($.browser.mozilla) {
105 $(this).css("padding", "0").css("position", "relative").css("top", "-2px");
106 }
107 });
108 // END: Appending toolbar
109
110 try {
111 var iframe = document.createElement("IFRAME");
112 var doc = null;
113 $(iframe).attr("width", "100%").css("height", h +"px").attr("id", d.id +"_html").css("border", "none");
114 $(this).parent().prepend(iframe);
115 } catch(eIframe) {
116 alert("This rich text component is not supported by your browser.");
117 $(this).show();
118 return false;
119 }
120
121 d.iframe = iframe;
122 var idoc = iframe.contentWindow.document;
123 if ($.browser.msie === false) {
124 idoc.body.contentEditable = true;
125 } else {
126 setTimeout(function() { try {$(idoc.body).css('border', 'none'); } catch (exception) {}}, 10);
127 }
128
129 this.initResizing($(iframe));
130 this.reAlign();
131
132 // Prepare the text
133 var text = $.trim($(this).val());
134 text = xhtml.replace(/INITIAL_CONTENT/, ($.browser.mozilla && text === "") ? '' : text);
135
136 if ($.browser.mozilla) {
137 idoc.open('text/html', 'replace');
138 idoc.write(text);
139 idoc.close();
140 } else {
141 idoc.write(text);
142 }
143
144 try {
145 idoc.designMode = "on";
146 idoc.execCommand("undo", false, null);
147 }
148 catch (exception) {
149 try {
150 $(idoc).focus(function() {
151 try {
152 this.designMode = "on";
153 } catch (exception) {}
154 });
155 } catch (exception) {}
156 }
157
158 // START: Adding events
159 var keyupHandler = function(e) {
160 var html = ($("#"+ d.id).is(":visible")) ? $("#"+ d.id).val() : html = idoc.body.innerHTML;
161 html = (typeof HTMLtoXML === 'function') ? HTMLtoXML(html) : html;
162 $("#"+ d.id).val(html);
163 };
164
165 try {
166 if (idoc.attachEvent) {
167 idoc.attachEvent("onkeyup", keyupHandler);
168 } else {
169 idoc.addEventListener("keyup", keyupHandler, false);
170 }
171 }
172 catch (exception) {}
173
174 $(idoc).keypress = function (e) {
175 switch ((e.which) ? e.which : e.keyCode) {
176 case 13: // ENTER
177 if (!$.browser.opera && !e.ctrlKey && !e.shiftKey) {
178 try {
179 var el = ta.getEventElement(iframe.contentWindow, e);
180 if (el.nodeName == "BODY") {
181 glob_ha[d.id].cmd("formatblock", "<p>");
182 }
183 }
184 catch (exception) {}
185 }
186 break;
187 case 61: // =
188 if (e.ctrlKey) {
189 if (e.shiftKey) {
190 glob_ha[d.id].cmd("superscript");
191 }
192 else {
193 glob_ha[d.id].cmd("subscript");
194 }
195 }
196 break;
197 case 66: // B
198 if (e.ctrlKey && !e.shiftKey) {
199 glob_ha[d.id].cmd("bold");
200 }
201 break;
202 case 73: // I
203 if (e.ctrlKey && !e.shiftKey) {
204 glob_ha[d.id].cmd("italic");
205 }
206 break;
207 case 74: // J
208 if (e.ctrlKey && !e.shiftKey) {
209 glob_ha[d.id].cmd("unlink");
210 }
211 break;
212 case 75: // K
213 if (e.ctrlKey && !e.shiftKey) {
214 glob_ha[d.id].cmd("createlink");
215 }
216 break;
217 case 85: // U
218 if (e.ctrlKey && !e.shiftKey) {
219 glob_ha[d.id].cmd("italic");
220 }
221 break;
222 default:
223 break;
224 }
225 };
226 // END: Adding events
227 $(this).hide();
228 };
229
230 this.reAlign = function() {
231 var toolbar = $(this).parents("div.htmlbox:first").find("div.htmlbox-toolbar");
232 var width = 0;
233 toolbar.children().each(function () {
234 width += parseInt($(this).width(), 10) + parseInt($(this).css("margin-left"), 10) + parseInt($(this).css("margin-right"), 10);
235 }).end();
236 var height = 27;
237 var tWidth = toolbar.width();
238 while (width > toolbar.width()) {
239 height += 27;
240 toolbar.css("height", height +"px");
241 width -= tWidth;
242 }
243 $(this).parents("div.htmlbox:first").css('padding-top', (height + 3) +"px");
244 };
245
246 /**
247 * Fetch the current cursor's / selection's parent item.
248 * @param contentWindow The IFRAME / Window the cursor is in.
249 * @param e JavaScript Event object.
250 */
251 this.getEventElement = function(contentWindow, e) {
252 var eTarget; // Current Real cursor position DOM Element
253 var selection; // Selection object
254 var range; // Range object
255 if (window.getSelection) {
256 selection = contentWindow.getSelection();
257 eTarget = (e && e.type=='mouseup') ? e.target :
258 ((selection.anchorNode.nodeName == '#text') ? selection.anchorNode.parentNode : selection.anchorNode);
259 }
260 else {
261 selection = contentWindow.document.selection;
262 range = selection.createRange();
263 eTarget = (e && e.type=='mouseup') ? e.srcElement :
264 ((selection.type == "Control") ? range.item(0) : selection.parentElement());
265 }
266 return eTarget;
267 };
268
269 /**
270 * Initalize and apply the regular textarea resizing capability of Drupal to the HTMLBox
271 */
272 this.initResizing = function(iframe) {
273 var grippie = $(this).parents('div.resizable-textarea:first').find('div.grippie:last');
274 // If we have the grippie, replace it's functionality
275 if (grippie.size()) {
276 var textarea = $(this);
277 var htmlbox = $(this).parents('div.htmlbox:first');
278
279 function startDrag(e) {
280 staticOffset = textarea.height() - Drupal.mousePosition(e).y;
281 $(document).mousemove(performDrag).mouseup(endDrag);
282 return false;
283 }
284
285 function performDrag(e) {
286 var height = Math.max(32, staticOffset + Drupal.mousePosition(e).y) + 'px';
287 textarea.height(height);
288 iframe.height(height);
289 htmlbox.height(height);
290 return false;
291 }
292
293 function endDrag(e) {
294 $(document).unmousemove(performDrag).unmouseup(endDrag);
295 }
296
297 grippie.unbind('mousedown').mousedown(startDrag);
298 }
299 };
300
301 /**
302 * Generate a toolbar based on the added buttons / separators
303 */
304 var toolbar = function() {
305 var h = "";
306 var colors = ['white', 'FFFFFF', 'ivory', 'FFFFF0', 'lightyellow', 'FFFFE0', 'yellow', 'FFFF00', 'snow', 'FFFAFA', 'floralwhite', 'FFFAF0', 'lemonchiffon', 'FFFACD', 'cornsilk', 'FFF8DC', 'seashell', 'FFF5EE', 'lavenderblush', 'FFF0F5', 'papayawhip', 'FFEFD5', 'blanchedalmond', 'FFEBCD', 'mistyrose', 'F FE4E1', 'bisque', 'FFE4C4', 'moccasin', 'FFE4B5', 'navajowhite', 'FFDEAD', 'peachpuff', 'FFDAB9', 'gold', 'FFD700', 'pink', 'FFC0CB', 'lightpink ', 'FFB6C1', 'orange', 'FFA500', 'lightsalmon', 'FFA07A', 'darkorange', 'FF8C00', 'coral', 'FF7F50', 'hotpink', 'FF69B4', 'tomato', 'FF6347', 'orangered', 'FF4500', 'deeppink', 'FF1493', 'magenta', 'FF00FF', 'fuchsia', 'FF00FF', 'red', 'FF0000', 'oldlace', 'FDF5E6', 'lightgoldenrodyellow', 'FAFAD2', ' linen', 'FAF0E6', 'antiquewhite', 'FAEBD7', 'salmon', 'FA8072', 'ghostwhite', 'F8F8FF', 'mintcream', 'F5FFFA', 'whitesmoke', 'F5F5F5', 'beige', ' F5F5DC', 'wheat', 'F5DEB3', 'sandybrown', 'F4A460', 'azure', 'F0FFFF', 'honeydew', 'F0FFF0', 'aliceblue', 'F0F8FF', 'khaki', 'F0E68C', 'lightcoral ', 'F08080', 'palegoldenrod', 'EEE8AA', 'violet', 'EE82EE', 'darksalmon', 'E9967A', 'lavender', 'E6E6FA', 'lightcyan', 'E0FFFF', 'burlywood', 'DEB887', 'plum', 'DDA0DD', 'gainsboro', 'DCDCDC', 'crimson', 'DC143C', 'palevioletred', 'DB7093', 'goldenrod', 'DAA520', 'orchid', 'DA70D6', 'thistle', 'D8BFD8', 'lightgrey', 'D3D3D3', 'tan', 'D2B48C', 'chocolate', 'D2691E', 'peru', 'CD853F', 'indianred', 'CD5C5C', 'mediumvioletred', 'C71585', 'silver', 'C0C0C0', 'darkkhaki', 'BDB76B', 'rosybrown', 'BC8F8F', 'mediumorchid', 'BA55D3', 'darkgoldenrod', 'B8860B', 'firebrick', 'B22222', 'powderblue', 'B0E0E6', 'lightsteelblue', 'B0C4DE', 'paleturquoise', 'AFEEEE', 'greenyellow', 'ADFF2F', 'lightblue', 'ADD8E6', 'darkgray', 'A9A9A9', 'brown', 'A52A2A', 'sienna', "A0522D", 'yellowgreen', "9ACD32", 'darkorchid', '9932CC', 'palegreen', '98FB98', 'darkviolet', '9400D3', 'mediumpurple', '9370DB', 'lightgreen', '90EE90', 'darkseagreen', '8FBC8F', 'saddlebrown', '8B4513', 'darkmagenta', '8B008B', 'darkred', '8B0000', 'blueviolet', '8A2BE2', 'lightskyblue', '87CEFA', 'skyblue', '87CEEB', 'gray', '808080', 'olive', '808000', 'purple', '800080', 'maroon', '800000', 'aquamarine', '7FFFD4', 'chartreuse', '7FFF00', 'lawngreen', '7CFC00', 'mediumslateblue', '7B68EE', 'lightslategray', '778899', 'slategray', '708090', 'olivedrab', '6B8E23', 'slateblue', '6A5ACD', 'dimgray', '696969', 'mediumaquamarine', '66CDAA', 'cornflowerblue', '6495ED', 'cadetblue', '5F9EA0', 'darkolivegreen', '556B2F', 'indigo', '4B0082', 'mediumturquoise', '48D1CC', 'darkslateblue', '483D8B', 'steelblue', '4682B4', 'royalblue', '4169E1', 'turquoise', '40E0D0', 'mediumseagreen', '3CB371', 'limegreen', '32CD32', 'darkslategray', '2F4F4F', 'seagreen', '2E8B57', 'forestgreen', '228B22', 'lightseagreen', '20B2AA', 'dodgerblue', '1E90FF', 'midnightblue', '191970', 'cyan', '00FFFF', 'aqua', '00FFFF', 'springgreen', '00FF7F', 'lime', '00FF00', 'mediumspringgreen', '00FA9A', 'darkturquoise', '00CED1', 'deepskyblue', '00BFFF', 'darkcyan', "008B8B", 'teal', "008080", 'green', '008000', 'darkgreen', '006400', 'blue', '0000FF', 'mediumblue', '0000CD', 'darkblue', '00008B', 'navy', '000080', 'black', '000000'];
307
308 for (var k = 1; k < d.rows.length; k++) {
309 if (undefined === d.rows[k]) {
310 continue;
311 }
312
313 var buttons = d.rows[k].split(",");
314 h += "<div class='"+ d.id +"_tb htmlbox-toolbar'>";
315
316 /**
317 * Add a toolbar item to the toolbar generating string.
318 * @param type The item type to add. Available options are
319 * - button: a button. This case the event is 'onclick'
320 * - select: a dropdown select box. This case the event is 'onchange'
321 * @param cmd The command to execute when the event happens.
322 * @param title Optional title for the tooltip.
323 * @param data Based on the type:
324 * - button: The class for the span to add the button image.
325 * - select: Available <option>s as a string.
326 * @return An HTML string.
327 */
328 var addToolbarItem = function (type, cmd, title, data, arg) {
329 switch (type) {
330 case 'button':
331 return '<button type="button" onclick="glob_ha[\''+ d.id +'\'].cmd(\''+ cmd + (arg !== undefined ? '\',\''+ arg : '') +'\')" title="'+ title +'"><span class="htmlbox-'+ data +'">&nbsp;</span></button>';
332 case 'select':
333 return '<select id="'+ d.id +'_'+ cmd +'" onchange="glob_ha[\''+ d.id +'\'].cmd(\''+ cmd +'\',this.options[this.selectedIndex].value);this.selectedIndex=0;">'+ data +'</select>';
334 default:
335 return '';
336 }
337 };
338 var m, options;
339 for (var i = 0; i < (buttons.length + 1); i++) {
340 switch (d.buttons[buttons[i]]) {
341 case "cut":
342 h += addToolbarItem("button", "cut", "cut", "cut");
343 break;
344 case "copy":
345 h += addToolbarItem("button", "copy", "copy", "copy");
346 break;
347 case "paste":
348 h += addToolbarItem("button", "cut", "paste", "paste");
349 break;
350 case "undo":
351 h += addToolbarItem("button", "undo", "undo", "undo");
352 break;
353 case "redo":
354 h += addToolbarItem("button", "redo", "redo", "redo");
355 break;
356 case "bold":
357 h += addToolbarItem("button", "bold", "bold", "b");
358 break;
359 case "italic":
360 h += addToolbarItem("button", "italic", "italic", "i");
361 break;
362 case "underline":
363 h += addToolbarItem("button", "underline", "undelrine", "u");
364 break;
365 case "sup":
366 h += addToolbarItem("button", "superscript", "superscript", "sup");
367 break;
368 case "sub":
369 h += addToolbarItem("button", "subscript", "subscript", "sub");
370 break;
371 case "left":
372 h += addToolbarItem("button", "justifyleft", "align left", "left");
373 break;
374 case "center":
375 h += addToolbarItem("button", "justifycenter", "align center", "center");
376 break;
377 case "right":
378 h += addToolbarItem("button", "justifyright", "align right", "right");
379 break;
380 case "justify":
381 h += addToolbarItem("button", "justifyfull", "justify", "justify");
382 break;
383 case "ol":
384 h += addToolbarItem("button", "insertorderedlist", "ordered list", "ol");
385 break;
386 case "ul":
387 h += addToolbarItem("button", "insertunorderedlist", "unordered list", "ul");
388 break;
389 case "indent":
390 h += addToolbarItem("button", "indent", "indent", "indent");
391 break;
392 case "outdent":
393 h += addToolbarItem("button", "outdent", "outdent", "outdent");
394 break;
395 case "hyperlink":
396 h += addToolbarItem("button", "createlink", "hyperlink", "hyperlink");
397 h += addToolbarItem("button", "unlink", "remove hyperlink", "unlink");
398 break;
399 case "image":
400 h += addToolbarItem("button", "insertimage", "image", "img");
401 break;
402 case "html":
403 h += addToolbarItem("button", "html", "html source", "html");
404 break;
405 case "separator_dots":
406 h += "<span class='separator_dots' title='separator_dots'>&nbsp;</span>";
407 break;
408 case "separator_basic":
409 h += "<span class='separator_basic' title='separator_basic'>&nbsp;</span>";
410 break;
411 case "fontsize":
412 h += addToolbarItem("select", "fontsize", "font size", '<option value="" selected="selected">- font size -</option><option value="1">1</option><option value="2">2</option><option value="3">3</option><option value="4">4</option><option value="5">5</option><option value="6">6</option><option value="7">7</option>');
413 break;
414 case "fontfamily":
415 h += addToolbarItem("select", "fontname", "font name", '<option value="" selected="selected">- font -</option><option value="arial" style="font-family:arial;">Arial</option><option value="courier" style="font-family:courier;">Courier</option><option value="cursive" style="font-family:cursive;">Cursive</option><option value="georgia" style="font-family:georgia;">Georgia</option><option value="monospace" style="font-family:monospace;">Monospace</option><option value="tahoma" style="font-family:tahoma;">Tahoma</option><option value="verdana" style="font-family:verdana;">Verdana</option>');
416 break;
417 case "fontcolor":
418 options = '<option value="" selected="selected">- color -</option>';
419 for (m = 0; m < colors.length; m++) {
420 if (1 === (m & 1)) {
421 continue;
422 }
423 options += "<option value='"+ colors[m] +"' style='background:"+ colors[m] +";color:"+ colors[m] +";'>"+ colors[m] +"</option>";
424 }
425 h += addToolbarItem("select", "fontcolor", "font color", options);
426 break;
427 case "highlight":
428 options = '<option value="" selected="selected">- highlight -</option>';
429 for (m = 0; m < colors.length; m++) {
430 if (1 === (m & 1)) {
431 continue;
432 }
433 options += "<option value='"+ colors[m] +"' style='background:"+ colors[m] +";color:"+ colors[m] +";'>"+ colors[m] +"</option>";
434 }
435 h += addToolbarItem("select", "backcolor", "background color", options);
436 break;
437 case "headers":
438 options = '<option value="" selected="selected">- headers -</option>';
439 for (m = 1; m <= 6; m++) {
440 options += "<option value='&lt;H"+ m +"&gt;'>H"+ m +"</option>";
441 }
442 h += addToolbarItem("select", "formatblock", "Header format", options);
443 break;
444 case "p":
445 h += addToolbarItem("button", "formatblock", "p", "paragraph", "<P>");
446 break;
447 case "code":
448 h += addToolbarItem("button", "formatblock", "code", "code", "<CODE>");
449 break;
450 case "pre":
451 h += addToolbarItem("button", "formatblock", "preformatted", "pre", "<PRE>");
452 break;
453 default:
454 break;
455 }
456 }
457 h += "</div>";
458 }
459 return h;
460 };
461
462 /**
463 * Handle commands fired from the buttons.
464 * @param cmd The command to execute.
465 * @param arg1 Optional arguments for the command.
466 */
467 this.cmd = function(cmd, arg1) {
468 // When user clicks toolbar button make sure it always targets its respective WYSIWYG
469 d.iframe.contentWindow.focus();
470 var idoc = d.iframe.contentWindow.document;
471 if ($.browser.mozilla) {
472 idoc.execCommand("styleWithCSS", false, false);
473 }
474 if (cmd === "html") {
475 var text = this.get_html();
476 if ($("#"+ d.id).is(":visible")) {
477 $("#"+ d.id).hide();
478 $("#"+ d.id +"_html").show();
479 if ($.browser.opera) {
480 $(window).scrollTop($('body').scrollTop());
481 }
482 this.set_text(text);
483 } else {
484 $("#"+ d.id).show();
485 $("#"+ d.id +"_html").hide();
486 this.set_text(text);
487 $("#"+ d.id).focus();
488 }
489 } else if (cmd === "createlink") {
490 arg1 = $.trim(prompt("Paste Web Address URL Here:", "http://"));
491 if (arg1 !== "") {
492 idoc.execCommand(cmd, false, arg1);
493 }
494 else {
495 idoc.execCommand("unlink", false, null);
496 }
497 } else if (cmd === "insertimage") {
498 idoc.execCommand(cmd, false, prompt("Paste Image URL Here:", "http://"));
499 } else if (cmd === "fontsize") {
500 idoc.execCommand(cmd, false, arg1);
501 } else if (cmd === "backcolor") {
502 if ($.browser.msie) {
503 idoc.execCommand("backcolor", false, arg1);
504 } else {
505 idoc.execCommand("hilitecolor", false, arg1);
506 }
507 } else if (cmd === "fontcolor") {
508 idoc.execCommand("forecolor", false, arg1);
509 } else if (cmd === "fontname") {
510 idoc.execCommand(cmd, false, arg1);
511 } else if (cmd === "formatblock") {
512 idoc.execCommand(cmd, false, arg1);
513 } else if(cmd==="cut") {
514 if ($.browser.msie === false) {
515 alert("Available in IExplore only.\nUse CTRL+X to cut text!");
516 } else {
517 idoc.execCommand('Cut');
518 }
519 } else if (cmd==="copy"){
520 if ($.browser.msie === false) {
521 alert("Available in IExplore only.\nUse CTRL+C to copy text!");
522 } else {
523 idoc.execCommand('Copy');
524 }
525 } else if (cmd==="paste") {
526 if($.browser.msie === false) {
527 alert("Available in IExplore only.\nUse CTRL+V to paste text!");
528 } else {
529 idoc.execCommand('Paste');
530 }
531 } else {
532 idoc.execCommand(cmd, false, null);
533 }
534
535 if ($("#"+ d.id).is(":visible") === false) {
536 $("#"+ d.id).val(this.get_html());
537 }
538 return true;
539 };
540
541 /**
542 * Get text (HTML) of the textarea, or the HTML editor, which ever is visible.
543 * @return The text (HTML) of the textarea, or the HTML editor, which ever is visible.
544 */
545 this.get_text = function() {
546 if ($("#"+ d.id).is(":visible")) {
547 return $("#"+ d.id).val();
548 }
549
550 var text;
551
552 if ($.browser.msie) {
553 text = d.iframe.contentWindow.document.body.innerText;
554 } else {
555 var html = d.iframe.contentWindow.document.body.ownerDocument.createRange();
556 html.selectNodeContents(d.iframe.contentWindow.document.body);
557 text = html;
558 }
559
560 return text;
561 };
562
563 /**
564 * Set text (HTML) of the textarea, or the HTML editor, which ever is visible.
565 * @param txt The text (HTML) to replace the current content.
566 * @return The currently selected object for chaining.
567 */
568 this.set_text = function(txt) {
569 var text = (undefined === txt) ? "": txt;
570 if ($("#"+ d.id).is(":visible")) {
571 $("#"+ d.id).val(text);
572 } else if ($.browser.mozilla || $.browser.safari) {
573 if ($.trim(text) === "") {
574 text = "&nbsp;";
575 }
576 text = xhtml.replace(/INITIAL_CONTENT/, text);
577 d.iframe.contentWindow.document.open('text/html', 'replace');
578 d.iframe.contentWindow.document.write(text);
579 d.iframe.contentWindow.document.close();
580 } else {
581 d.iframe.contentWindow.document.body.innerText = "";
582 if (text !== "") {
583 d.iframe.contentWindow.document.write(text);
584 }
585 }
586
587 return this;
588 };
589 /**
590 * Clean up some unwanted HTML items, by replacing them.
591 *
592 * Currently it replaces <span style=...> to it's <strong> and <em> counterpart.
593 */
594 this._mozcleanup = function () {
595 if ($(this).size() === 0) {
596 return;
597 }
598
599 if ($(this).attr("style") && $(this).attr("style").match(/font-weight:\s*bold\s*/i)) {
600 if ($(this).attr("style").match(/font-style:\s*italic\s*/i)) {
601 $(this).replaceWith('<em><strong>'+ this.innerHTML +'</strong></em>');
602 }
603 else {
604 $(this).replaceWith('<strong>'+ this.innerHTML +'</strong>');
605 }
606 }
607 else {
608 if ($(this).attr("style") && $(this).attr("style").match(/font-style:\s*italic\s*/i)) {
609 $(this).replaceWith('<em>'+ this.innerHTML +'</em>');
610 }
611 else {
612 $(this).replaceWith(this.innerHTML);
613 }
614 }
615 };
616
617 /**
618 * Clean up some unwanted HTML items, by replacing them.
619 *
620 * Currently it replaces <b> and <i> items with <strong> and <em>
621 */
622 this._cleanup = function () {
623 if ($(this).size() === 0) {
624 return;
625 }
626
627 if ($(this).is('b')) {
628 $(this).replaceWith('<strong>'+ this.innerHTML +'</strong>');
629 }
630 else if ($(this).is('i')){
631 $(this).replaceWith('<em>'+ this.innerHTML +'</em>');
632 }
633 };
634
635 /**
636 * Get HTML out of the textarea, or from the HTML editor, which ever is visible.
637 */
638 this.get_html = function() {
639 var html;
640
641 if ($("#"+ d.id).is(":visible")) {
642 html = $("#"+ d.id).val();
643 } else {
644 html = d.iframe.contentWindow.document.body.innerHTML;
645 if (html.match(/<span[^>]*\s+style=[^>]*>/)) {
646 html = $(document.createElement("DIV")).html(html).find('span span').each(this._mozcleanup).end().find('span').each(this._mozcleanup).end().get(0).innerHTML;
647 }
648 html = $(document.createElement("DIV")).html(html).find('i, b').each(this._cleanup).end().get(0).innerHTML;
649
650 html = html.replace(/<(em|strong|span)[^>]*>(\s*)<\/\1>/ig, '$2').replace(/<\/(em|strong)><\1[^>]*>/ig, '').replace(/<br(?:\s+[^>]+)?>/ig, '<br />');
651 if (this.newline_removal) {
652 html = html.replace(/[\n\r]+/g, ' ');
653 }
654 }
655
656 if (typeof HTMLtoXML === 'function') {
657 html = HTMLtoXML(html);
658 }
659
660 return html;
661 };
662
663 /**
664 * Add a button (or separator @see separator()) to the editor.
665 * @param name Name of the button (or separator).
666 * @param row The row, where the button (or separator) should be added (Optional, default is 1).
667 * @return The currently selected object for chaining.
668 */
669 this.button = function(name, row) {
670 d.buttons[d.buttons.length] = name;
671
672 if (undefined === row) {
673 if (undefined === d.rows[1]) {
674 d.rows[1] = "";
675 }
676 d.rows[1] = d.rows[1] +","+ (d.buttons.length - 1);
677 } else {
678 if (undefined === d.rows[row]) {
679 d.rows[row] = "";
680 }
681 d.rows[row] = d.rows[row] +","+ (d.buttons.length - 1);
682 }
683
684 return this;
685 };
686
687 /**
688 * Add a separator to the editor.
689 * @param type Type of the separator (Optional, default is 'basic').
690 * @param row The row, where the separator should be added (Optional, default is 1).
691 * @return The currently selected object for chaining.
692 */
693 this.separator = function(type, row) {
694 if (undefined === type) {
695 type = "basic";
696 }
697
698 return this.button("separator_"+ type, row);
699 };
700 // For chaining
701 return this;
702 };
703
704 // In case we are using an old jQuery we'll need the replaceWith function.
705 jQuery.fn.replaceWith = function(value) {
706 return this.after( value ).remove();
707 };

  ViewVC Help
Powered by ViewVC 1.1.2