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