da924c874c22039bd3fccd842ed696be6b2df57a
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / htmlarea / plugins / DefaultClean / default-clean.js
1 /***************************************************************
2 * Copyright notice
3 *
4 * (c) 2008-2009 Stanislas Rolland <typo3(arobas)sjbr.ca>
5 * All rights reserved
6 *
7 * This script is part of the TYPO3 project. The TYPO3 project is
8 * free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * The GNU General Public License can be found at
14 * http://www.gnu.org/copyleft/gpl.html.
15 * A copy is found in the textfile GPL.txt and important notices to the license
16 * from the author is found in LICENSE.txt distributed with these scripts.
17 *
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 /**
27 * Default Clean Plugin for TYPO3 htmlArea RTE
28 *
29 * TYPO3 SVN ID: $Id$
30 */
31 DefaultClean = HTMLArea.Plugin.extend({
32
33 constructor : function(editor, pluginName) {
34 this.base(editor, pluginName);
35 },
36
37 /*
38 * This function gets called by the class constructor
39 */
40 configurePlugin : function(editor) {
41
42 this.pageTSConfiguration = this.editorConfiguration.buttons.cleanword;
43
44 /*
45 * Registering plugin "About" information
46 */
47 var pluginInformation = {
48 version : "1.2",
49 developer : "Stanislas Rolland",
50 developerUrl : "http://www.sjbr.ca/",
51 copyrightOwner : "Stanislas Rolland",
52 sponsor : "SJBR",
53 sponsorUrl : "http://www.sjbr.ca/",
54 license : "GPL"
55 };
56 this.registerPluginInformation(pluginInformation);
57
58 /*
59 * Registering the (hidden) button
60 */
61 var buttonId = "CleanWord";
62 var buttonConfiguration = {
63 id : buttonId,
64 tooltip : this.localize(buttonId + "-Tooltip"),
65 action : "onButtonPress",
66 hide : true
67 };
68 this.registerButton(buttonConfiguration);
69 },
70
71 /*
72 * This function gets called when the button was pressed.
73 *
74 * @param object editor: the editor instance
75 * @param string id: the button id or the key
76 *
77 * @return boolean false if action is completed
78 */
79 onButtonPress : function (editor, id, target) {
80 // Could be a button or its hotkey
81 var buttonId = this.translateHotKey(id);
82 buttonId = buttonId ? buttonId : id;
83
84 this.clean();
85 return false;
86 },
87
88 onGenerate : function () {
89 var doc = this.editor._doc;
90 // Function reference used on paste with older versions of Mozilla/Firefox in which onPaste is not fired
91 this.cleanLaterFunctRef = this.makeFunctionReference("clean");
92 HTMLArea._addEvents((HTMLArea.is_ie ? doc.body : doc), ["paste","dragdrop","drop"], DefaultClean.wordCleanHandler, true);
93 },
94
95 clean : function () {
96 function clearClass(node) {
97 var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig,' ');
98 if(newc != node.className) {
99 node.className = newc;
100 if(!/\S/.test(node.className)) {
101 if (!HTMLArea.is_opera) {
102 node.removeAttribute("class");
103 if (HTMLArea.is_ie) {
104 node.removeAttribute("className");
105 }
106 } else {
107 node.className = '';
108 }
109 }
110 }
111 }
112 function clearStyle(node) {
113 if (HTMLArea.is_ie) var style = node.style.cssText;
114 else var style = node.getAttribute("style");
115 if (style) {
116 var declarations = style.split(/\s*;\s*/);
117 for (var i = declarations.length; --i >= 0;) {
118 if(/^mso|^tab-stops/i.test(declarations[i]) || /^margin\s*:\s*0..\s+0..\s+0../i.test(declarations[i])) declarations.splice(i,1);
119 }
120 node.setAttribute("style", declarations.join("; "));
121 }
122 }
123 function stripTag(el) {
124 if(HTMLArea.is_ie) {
125 el.outerHTML = HTMLArea.htmlEncode(el.innerText);
126 } else {
127 var txt = document.createTextNode(HTMLArea.getInnerText(el));
128 el.parentNode.insertBefore(txt,el);
129 el.parentNode.removeChild(el);
130 }
131 }
132 function checkEmpty(el) {
133 if(/^(span|b|strong|i|em|font)$/i.test(el.nodeName) && !el.firstChild) el.parentNode.removeChild(el);
134 }
135 function parseTree(root) {
136 var tag = root.nodeName.toLowerCase(), next;
137 switch (root.nodeType) {
138 case 1:
139 if (/^(meta|style|title|link)$/.test(tag)) {
140 root.parentNode.removeChild(root);
141 return false;
142 break;
143 }
144 case 3:
145 case 9:
146 case 11:
147 if ((HTMLArea.is_ie && root.scopeName != 'HTML') || (!HTMLArea.is_ie && /:/.test(tag)) || /o:p/.test(tag)) {
148 stripTag(root);
149 return false;
150 } else {
151 clearClass(root);
152 clearStyle(root);
153 for (var i=root.firstChild;i;i=next) {
154 next = i.nextSibling;
155 if (i.nodeType != 3 && parseTree(i)) { checkEmpty(i); }
156 }
157 }
158 return true;
159 break;
160 default:
161 root.parentNode.removeChild(root);
162 return false;
163 break;
164 }
165 }
166 parseTree(this.editor._doc.body);
167 }
168 });
169
170 /*
171 * Closure avoidance for IE
172 */
173 DefaultClean.cleanLater = function (editorNumber) {
174 var editor = RTEarea[editorNumber].editor;
175 editor.getPluginInstance("Default").clean();
176 };
177
178 /*
179 * Handler for paste, dragdrop and drop events
180 */
181 DefaultClean.wordCleanHandler = function (ev) {
182 if (!ev) var ev = window.event;
183 var target = ev.target ? ev.target : ev.srcElement;
184 var owner = target.ownerDocument ? target.ownerDocument : target;
185 if (HTMLArea.is_ie) { // IE5.5 does not report any ownerDocument
186 while (owner.parentElement) { owner = owner.parentElement; }
187 }
188 var editor = RTEarea[owner._editorNo].editor;
189
190 // If we dropped an image dragged from the TYPO3 Image plugin, let's close the dialog window
191 if (typeof(HTMLArea.Dialog) != "undefined" && HTMLArea.Dialog.TYPO3Image) {
192 HTMLArea.Dialog.TYPO3Image.close();
193 } else {
194 window.setTimeout("DefaultClean.cleanLater(\'" + editor._editorNumber + "\');", 250);
195 }
196 };
197