'); - content = content.replace(/\r\r/g, '
'); - content = content.replace(/\n\n/g, '
'); + // Process contents + process(n.innerHTML); - // Has paragraphs - if ((pos = content.indexOf('
')) != -1) { - this.editor.execCommand("Delete"); + return tinymce.dom.Event.cancel(e); + } else { + or = ed.selection.getRng(); - var node = this.editor.selection.getNode(); + // Move caret into hidden div + n = n.firstChild; + rng = ed.getDoc().createRange(); + rng.setStart(n, 0); + rng.setEnd(n, 1); + sel.setRng(rng); - // Get list of elements to break - var breakElms = []; + // Wait a while and grab the pasted contents + window.setTimeout(function() { + var n = dom.get('_mcePaste'), h; - do { - if (node.nodeType == 1) { - // Don't break tables and break at body - if (node.nodeName == "TD" || node.nodeName == "BODY") - break; - - breakElms[breakElms.length] = node; - } - } while(node = node.parentNode); + // Webkit clones the _mcePaste div for some odd reason so this will ensure that we get the real new div not the old empty one + n.id = '_mceRemoved'; + dom.remove(n); + n = dom.get('_mcePaste') || n; - var before = "", after = "
"; - before += content.substring(0, pos); + // Grab the HTML contents + // We need to look for a apple style wrapper on webkit it also adds a div wrapper if you copy/paste the body of the editor + // It's amazing how strange the contentEditable mode works in WebKit + h = (dom.select('> span.Apple-style-span div', n)[0] || dom.select('> span.Apple-style-span', n)[0] || n).innerHTML; - for (var i=0; i";
- content = before + content.substring(pos+7) + after;
- }
- }
+ // Restore the old selection
+ if (or)
+ sel.setRng(or);
- if (this.editor.getParam("paste_create_linebreaks", true)) {
- content = content.replace(/\r\n/g, ' $1 " + middot + "$1 <\/p>/gi, ""); // Remove pagebreaks
- content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks
+ process([
+ //gi, // Word comments
+ /<\/?(img|font|meta|link|style|div|v:\w+)[^>]*>/gi, // Remove some tags including VML content
+ /<\\?\?xml[^>]*>/gi, // XML namespace declarations
+ /<\/?o:[^>]*>/gi, // MS namespaced elements
');
- content = content.replace(/\r/g, '
');
- content = content.replace(/\n/g, '
');
- }
- }
+ process(h);
+ }, 0);
+ }
+ };
- this.editor.execCommand("mceInsertRawHTML", false, content);
+ // Check if we should use the new auto process method
+ if (ed.getParam('paste_auto_cleanup_on_paste', true)) {
+ // Is it's Opera or older FF use key handler
+ if (tinymce.isOpera || /Firefox\/2/.test(navigator.userAgent)) {
+ ed.onKeyDown.add(function(ed, e) {
+ if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45))
+ grabContent(e);
+ });
+ } else {
+ // Grab contents on paste event on Gecko and WebKit
+ ed.onPaste.addToTop(function(ed, e) {
+ return grabContent(e);
+ });
+ }
}
- },
- _insertWordContent : function(content) {
- var t = this, ed = t.editor;
+ // Block all drag/drop events
+ if (ed.getParam('paste_block_drop')) {
+ ed.onInit.add(function() {
+ ed.dom.bind(ed.getBody(), ['dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag'], function(e) {
+ e.preventDefault();
+ e.stopPropagation();
- if (content && content.length > 0) {
- // Cleanup Word content
- var bull = String.fromCharCode(8226);
- var middot = String.fromCharCode(183);
+ return false;
+ });
+ });
+ }
- if (ed.getParam('paste_insert_word_content_callback'))
- content = ed.execCallback('paste_insert_word_content_callback', 'before', content);
+ // Add legacy support
+ t._legacySupport();
+ },
- var rl = ed.getParam("paste_replace_list", '\u2122,TM,\u2026,...,\x93|\x94|\u201c|\u201d,",\x60|\x91|\x92|\u2018|\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
- for (var i=0; i
", "gi"), "
]+>/g, ""); // Header elements
+ //console.log('Before preprocess:' + o.content);
- if (this.editor.getParam("paste_remove_spans", true))
- content = content.replace(/<\/?span[^>]*>/gi, "");
+ function process(items) {
+ each(items, function(v) {
+ // Remove or replace
+ if (v.constructor == RegExp)
+ h = h.replace(v, '');
+ else
+ h = h.replace(v[0], v[1]);
+ });
+ };
- if (this.editor.getParam("paste_remove_styles", true))
- content = content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)', 'gi'), "<$1$3");
+ // Process away some basic content
+ process([
+ /^\s*( )+/g, // nbsp entities at the start of contents
+ /( |
]*>)+\s*$/g // nbsp entities at the end of contents
+ ]);
- content = content.replace(/<\/?font[^>]*>/gi, "");
+ // Detect Word content and process it more aggressive
+ if (/(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/.test(h)) {
+ o.wordContent = true; // Mark the pasted contents as word specific content
+ //console.log('Word contents detected.');
- // Strips class attributes.
- switch (this.editor.getParam("paste_strip_class_attributes", "all")) {
- case "all":
- content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");
- break;
-
- case "mso":
- content = content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)', 'gi'), "<$1$3");
- break;
+ if (ed.getParam('paste_convert_middot_lists', true)) {
+ process([
+ [//gi, '$&__MCE_ITEM__'], // Convert supportLists to a list item marker
+ [/(]+:\s*symbol[^>]+>)/gi, '$1__MCE_ITEM__'], // Convert symbol spans to list items
+ [/(]+mso-list:[^>]+>)/gi, '$1__MCE_ITEM__'] // Convert mso-list to item marker
+ ]);
}
- content = content.replace(new RegExp('href="?' + this._reEscape("" + document.location) + '', 'gi'), 'href="' + this.editor.documentBaseURI.getURI());
- content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");
- content = content.replace(/<\\?\?xml[^>]*>/gi, "");
- content = content.replace(/<\/?\w+:[^>]*>/gi, "");
- content = content.replace(/-- page break --\s* into for line-though
+ /