|
1 /** |
|
2 * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $ |
|
3 * |
|
4 * @author Moxiecode |
|
5 * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved. |
|
6 */ |
|
7 |
|
8 /* Import plugin specific language pack */ |
|
9 tinyMCE.importPluginLanguagePack('paste'); |
|
10 |
|
11 var TinyMCE_PastePlugin = { |
|
12 getInfo : function() { |
|
13 return { |
|
14 longname : 'Paste text/word', |
|
15 author : 'Moxiecode Systems AB', |
|
16 authorurl : 'http://tinymce.moxiecode.com', |
|
17 infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste', |
|
18 version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion |
|
19 }; |
|
20 }, |
|
21 |
|
22 initInstance : function(inst) { |
|
23 if (tinyMCE.isMSIE && tinyMCE.getParam("paste_auto_cleanup_on_paste", false)) |
|
24 tinyMCE.addEvent(inst.getBody(), "paste", TinyMCE_PastePlugin._handlePasteEvent); |
|
25 }, |
|
26 |
|
27 handleEvent : function(e) { |
|
28 // Force paste dialog if non IE browser |
|
29 if (!tinyMCE.isRealIE && tinyMCE.getParam("paste_auto_cleanup_on_paste", false) && e.ctrlKey && e.keyCode == 86 && e.type == "keydown") { |
|
30 window.setTimeout('tinyMCE.selectedInstance.execCommand("mcePasteText",true)', 1); |
|
31 return tinyMCE.cancelEvent(e); |
|
32 } |
|
33 |
|
34 return true; |
|
35 }, |
|
36 |
|
37 getControlHTML : function(cn) { |
|
38 switch (cn) { |
|
39 case "pastetext": |
|
40 return tinyMCE.getButtonHTML(cn, 'lang_paste_text_desc', '{$pluginurl}/images/pastetext.gif', 'mcePasteText', true); |
|
41 |
|
42 case "pasteword": |
|
43 return tinyMCE.getButtonHTML(cn, 'lang_paste_word_desc', '{$pluginurl}/images/pasteword.gif', 'mcePasteWord', true); |
|
44 |
|
45 case "selectall": |
|
46 return tinyMCE.getButtonHTML(cn, 'lang_selectall_desc', '{$pluginurl}/images/selectall.gif', 'mceSelectAll', true); |
|
47 } |
|
48 |
|
49 return ''; |
|
50 }, |
|
51 |
|
52 execCommand : function(editor_id, element, command, user_interface, value) { |
|
53 switch (command) { |
|
54 case "mcePasteText": |
|
55 if (user_interface) { |
|
56 if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && !tinyMCE.getParam('paste_use_dialog', false)) |
|
57 TinyMCE_PastePlugin._insertText(clipboardData.getData("Text"), true); |
|
58 else { |
|
59 var template = new Array(); |
|
60 template['file'] = '../../plugins/paste/pastetext.htm'; // Relative to theme |
|
61 template['width'] = 450; |
|
62 template['height'] = 400; |
|
63 var plain_text = ""; |
|
64 tinyMCE.openWindow(template, {editor_id : editor_id, plain_text: plain_text, resizable : "yes", scrollbars : "no", inline : "yes", mceDo : 'insert'}); |
|
65 } |
|
66 } else |
|
67 TinyMCE_PastePlugin._insertText(value['html'], value['linebreaks']); |
|
68 |
|
69 return true; |
|
70 |
|
71 case "mcePasteWord": |
|
72 if (user_interface) { |
|
73 if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && !tinyMCE.getParam('paste_use_dialog', false)) { |
|
74 TinyMCE_PastePlugin._insertWordContent(TinyMCE_PastePlugin._clipboardHTML()); |
|
75 } else { |
|
76 var template = new Array(); |
|
77 template['file'] = '../../plugins/paste/pasteword.htm'; // Relative to theme |
|
78 template['width'] = 450; |
|
79 template['height'] = 400; |
|
80 var plain_text = ""; |
|
81 tinyMCE.openWindow(template, {editor_id : editor_id, plain_text: plain_text, resizable : "yes", scrollbars : "no", inline : "yes", mceDo : 'insert'}); |
|
82 } |
|
83 } else |
|
84 TinyMCE_PastePlugin._insertWordContent(value); |
|
85 |
|
86 return true; |
|
87 |
|
88 case "mceSelectAll": |
|
89 tinyMCE.execInstanceCommand(editor_id, 'selectall'); |
|
90 return true; |
|
91 |
|
92 } |
|
93 |
|
94 // Pass to next handler in chain |
|
95 return false; |
|
96 }, |
|
97 |
|
98 // Private plugin internal methods |
|
99 |
|
100 _handlePasteEvent : function(e) { |
|
101 switch (e.type) { |
|
102 case "paste": |
|
103 var html = TinyMCE_PastePlugin._clipboardHTML(); |
|
104 var r, inst = tinyMCE.selectedInstance; |
|
105 |
|
106 // Removes italic, strong etc, the if was needed due to bug #1437114 |
|
107 if (inst && (r = inst.getRng()) && r.text.length > 0) |
|
108 tinyMCE.execCommand('delete'); |
|
109 |
|
110 if (html && html.length > 0) |
|
111 tinyMCE.execCommand('mcePasteWord', false, html); |
|
112 |
|
113 tinyMCE.cancelEvent(e); |
|
114 return false; |
|
115 } |
|
116 |
|
117 return true; |
|
118 }, |
|
119 |
|
120 _insertText : function(content, bLinebreaks) { |
|
121 if (content && content.length > 0) { |
|
122 if (bLinebreaks) { |
|
123 // Special paragraph treatment |
|
124 if (tinyMCE.getParam("paste_create_paragraphs", true)) { |
|
125 var rl = tinyMCE.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(','); |
|
126 for (var i=0; i<rl.length; i+=2) |
|
127 content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]); |
|
128 |
|
129 content = tinyMCE.regexpReplace(content, "\r\n\r\n", "</p><p>", "gi"); |
|
130 content = tinyMCE.regexpReplace(content, "\r\r", "</p><p>", "gi"); |
|
131 content = tinyMCE.regexpReplace(content, "\n\n", "</p><p>", "gi"); |
|
132 |
|
133 // Has paragraphs |
|
134 if ((pos = content.indexOf('</p><p>')) != -1) { |
|
135 tinyMCE.execCommand("Delete"); |
|
136 |
|
137 var node = tinyMCE.selectedInstance.getFocusElement(); |
|
138 |
|
139 // Get list of elements to break |
|
140 var breakElms = new Array(); |
|
141 |
|
142 do { |
|
143 if (node.nodeType == 1) { |
|
144 // Don't break tables and break at body |
|
145 if (node.nodeName == "TD" || node.nodeName == "BODY") |
|
146 break; |
|
147 |
|
148 breakElms[breakElms.length] = node; |
|
149 } |
|
150 } while(node = node.parentNode); |
|
151 |
|
152 var before = "", after = "</p>"; |
|
153 before += content.substring(0, pos); |
|
154 |
|
155 for (var i=0; i<breakElms.length; i++) { |
|
156 before += "</" + breakElms[i].nodeName + ">"; |
|
157 after += "<" + breakElms[(breakElms.length-1)-i].nodeName + ">"; |
|
158 } |
|
159 |
|
160 before += "<p>"; |
|
161 content = before + content.substring(pos+7) + after; |
|
162 } |
|
163 } |
|
164 |
|
165 if (tinyMCE.getParam("paste_create_linebreaks", true)) { |
|
166 content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi"); |
|
167 content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi"); |
|
168 content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi"); |
|
169 } |
|
170 } |
|
171 |
|
172 tinyMCE.execCommand("mceInsertRawHTML", false, content); |
|
173 } |
|
174 }, |
|
175 |
|
176 _insertWordContent : function(content) { |
|
177 if (content && content.length > 0) { |
|
178 // Cleanup Word content |
|
179 var bull = String.fromCharCode(8226); |
|
180 var middot = String.fromCharCode(183); |
|
181 var cb; |
|
182 |
|
183 if ((cb = tinyMCE.getParam("paste_insert_word_content_callback", "")) != "") |
|
184 content = eval(cb + "('before', content)"); |
|
185 |
|
186 var rl = tinyMCE.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(','); |
|
187 for (var i=0; i<rl.length; i+=2) |
|
188 content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]); |
|
189 |
|
190 if (tinyMCE.getParam("paste_convert_headers_to_strong", false)) { |
|
191 content = content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>', 'gi'), '<p><b>$1</b></p>'); |
|
192 } |
|
193 |
|
194 content = content.replace(new RegExp('tab-stops: list [0-9]+.0pt">', 'gi'), '">' + "--list--"); |
|
195 content = content.replace(new RegExp(bull + "(.*?)<BR>", "gi"), "<p>" + middot + "$1</p>"); |
|
196 content = content.replace(new RegExp('<SPAN style="mso-list: Ignore">', 'gi'), "<span>" + bull); // Covert to bull list |
|
197 content = content.replace(/<o:p><\/o:p>/gi, ""); |
|
198 content = content.replace(new RegExp('<br style="page-break-before: always;.*>', 'gi'), '-- page break --'); // Replace pagebreaks |
|
199 content = content.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), ""); // Word comments |
|
200 |
|
201 if (tinyMCE.getParam("paste_remove_spans", true)) |
|
202 content = content.replace(/<\/?span[^>]*>/gi, ""); |
|
203 |
|
204 if (tinyMCE.getParam("paste_remove_styles", true)) |
|
205 content = content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)', 'gi'), "<$1$3"); |
|
206 |
|
207 content = content.replace(/<\/?font[^>]*>/gi, ""); |
|
208 |
|
209 // Strips class attributes. |
|
210 switch (tinyMCE.getParam("paste_strip_class_attributes", "all")) { |
|
211 case "all": |
|
212 content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3"); |
|
213 break; |
|
214 |
|
215 case "mso": |
|
216 content = content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)', 'gi'), "<$1$3"); |
|
217 break; |
|
218 } |
|
219 |
|
220 content = content.replace(new RegExp('href="?' + TinyMCE_PastePlugin._reEscape("" + document.location) + '', 'gi'), 'href="' + tinyMCE.settings['document_base_url']); |
|
221 content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3"); |
|
222 content = content.replace(/<\\?\?xml[^>]*>/gi, ""); |
|
223 content = content.replace(/<\/?\w+:[^>]*>/gi, ""); |
|
224 content = content.replace(/-- page break --\s*<p> <\/p>/gi, ""); // Remove pagebreaks |
|
225 content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks |
|
226 |
|
227 // content = content.replace(/\/? */gi, ""); |
|
228 // content = content.replace(/<p> <\/p>/gi, ''); |
|
229 |
|
230 if (!tinyMCE.settings['force_p_newlines']) { |
|
231 content = content.replace('', '' ,'gi'); |
|
232 content = content.replace('</p>', '<br /><br />' ,'gi'); |
|
233 } |
|
234 |
|
235 if (!tinyMCE.isMSIE && !tinyMCE.settings['force_p_newlines']) { |
|
236 content = content.replace(/<\/?p[^>]*>/gi, ""); |
|
237 } |
|
238 |
|
239 content = content.replace(/<\/?div[^>]*>/gi, ""); |
|
240 |
|
241 // Convert all middlot lists to UL lists |
|
242 if (tinyMCE.getParam("paste_convert_middot_lists", true)) { |
|
243 var div = document.createElement("div"); |
|
244 div.innerHTML = content; |
|
245 |
|
246 // Convert all middot paragraphs to li elements |
|
247 var className = tinyMCE.getParam("paste_unindented_list_class", "unIndentedList"); |
|
248 |
|
249 while (TinyMCE_PastePlugin._convertMiddots(div, "--list--")) ; // bull |
|
250 while (TinyMCE_PastePlugin._convertMiddots(div, middot, className)) ; // Middot |
|
251 while (TinyMCE_PastePlugin._convertMiddots(div, bull)) ; // bull |
|
252 |
|
253 content = div.innerHTML; |
|
254 } |
|
255 |
|
256 // Replace all headers with strong and fix some other issues |
|
257 if (tinyMCE.getParam("paste_convert_headers_to_strong", false)) { |
|
258 content = content.replace(/<h[1-6]> <\/h[1-6]>/gi, '<p> </p>'); |
|
259 content = content.replace(/<h[1-6]>/gi, '<p><b>'); |
|
260 content = content.replace(/<\/h[1-6]>/gi, '</b></p>'); |
|
261 content = content.replace(/<b> <\/b>/gi, '<b> </b>'); |
|
262 content = content.replace(/^( )*/gi, ''); |
|
263 } |
|
264 |
|
265 content = content.replace(/--list--/gi, ""); // Remove --list-- |
|
266 |
|
267 if ((cb = tinyMCE.getParam("paste_insert_word_content_callback", "")) != "") |
|
268 content = eval(cb + "('after', content)"); |
|
269 |
|
270 // Insert cleaned content |
|
271 tinyMCE.execCommand("mceInsertContent", false, content); |
|
272 |
|
273 if (tinyMCE.getParam('paste_force_cleanup_wordpaste', true)) |
|
274 window.setTimeout('tinyMCE.execCommand("mceCleanup");', 1); // Do normal cleanup detached from this thread |
|
275 } |
|
276 }, |
|
277 |
|
278 _reEscape : function(s) { |
|
279 var l = "?.\\*[](){}+^$:"; |
|
280 var o = ""; |
|
281 |
|
282 for (var i=0; i<s.length; i++) { |
|
283 var c = s.charAt(i); |
|
284 |
|
285 if (l.indexOf(c) != -1) |
|
286 o += '\\' + c; |
|
287 else |
|
288 o += c; |
|
289 } |
|
290 |
|
291 return o; |
|
292 }, |
|
293 |
|
294 _convertMiddots : function(div, search, class_name) { |
|
295 var mdot = String.fromCharCode(183); |
|
296 var bull = String.fromCharCode(8226); |
|
297 |
|
298 var nodes = div.getElementsByTagName("p"); |
|
299 var prevul; |
|
300 for (var i=0; i<nodes.length; i++) { |
|
301 var p = nodes[i]; |
|
302 |
|
303 // Is middot |
|
304 if (p.innerHTML.indexOf(search) == 0) { |
|
305 var ul = document.createElement("ul"); |
|
306 |
|
307 if (class_name) |
|
308 ul.className = class_name; |
|
309 |
|
310 // Add the first one |
|
311 var li = document.createElement("li"); |
|
312 li.innerHTML = p.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--| ', "gi"), ''); |
|
313 ul.appendChild(li); |
|
314 |
|
315 // Add the rest |
|
316 var np = p.nextSibling; |
|
317 while (np) { |
|
318 // If the node is whitespace, then |
|
319 // ignore it and continue on. |
|
320 if (np.nodeType == 3 && new RegExp('^\\s$', 'm').test(np.nodeValue)) { |
|
321 np = np.nextSibling; |
|
322 continue; |
|
323 } |
|
324 |
|
325 if (search == mdot) { |
|
326 if (np.nodeType == 1 && new RegExp('^o(\\s+| )').test(np.innerHTML)) { |
|
327 // Second level of nesting |
|
328 if (!prevul) { |
|
329 prevul = ul; |
|
330 ul = document.createElement("ul"); |
|
331 prevul.appendChild(ul); |
|
332 } |
|
333 np.innerHTML = np.innerHTML.replace(/^o/, ''); |
|
334 } else { |
|
335 // Pop the stack if we're going back up to the first level |
|
336 if (prevul) { |
|
337 ul = prevul; |
|
338 prevul = null; |
|
339 } |
|
340 // Not element or middot paragraph |
|
341 if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0) |
|
342 break; |
|
343 } |
|
344 } else { |
|
345 // Not element or middot paragraph |
|
346 if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0) |
|
347 break; |
|
348 } |
|
349 |
|
350 var cp = np.nextSibling; |
|
351 var li = document.createElement("li"); |
|
352 li.innerHTML = np.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--| ', "gi"), ''); |
|
353 np.parentNode.removeChild(np); |
|
354 ul.appendChild(li); |
|
355 np = cp; |
|
356 } |
|
357 |
|
358 p.parentNode.replaceChild(ul, p); |
|
359 |
|
360 return true; |
|
361 } |
|
362 } |
|
363 |
|
364 return false; |
|
365 }, |
|
366 |
|
367 _clipboardHTML : function() { |
|
368 var div = document.getElementById('_TinyMCE_clipboardHTML'); |
|
369 |
|
370 if (!div) { |
|
371 var div = document.createElement('DIV'); |
|
372 div.id = '_TinyMCE_clipboardHTML'; |
|
373 |
|
374 with (div.style) { |
|
375 visibility = 'hidden'; |
|
376 overflow = 'hidden'; |
|
377 position = 'absolute'; |
|
378 width = 1; |
|
379 height = 1; |
|
380 } |
|
381 |
|
382 document.body.appendChild(div); |
|
383 } |
|
384 |
|
385 div.innerHTML = ''; |
|
386 var rng = document.body.createTextRange(); |
|
387 rng.moveToElementText(div); |
|
388 rng.execCommand('Paste'); |
|
389 var html = div.innerHTML; |
|
390 div.innerHTML = ''; |
|
391 return html; |
|
392 } |
|
393 }; |
|
394 |
|
395 tinyMCE.addPlugin("paste", TinyMCE_PastePlugin); |