diff --git a/Source/MooEditable/MooEditable.CleanPaste.js b/Source/MooEditable/MooEditable.CleanPaste.js index 9c29b25..531cd4c 100644 --- a/Source/MooEditable/MooEditable.CleanPaste.js +++ b/Source/MooEditable/MooEditable.CleanPaste.js @@ -5,13 +5,16 @@ name: MooEditable.CleanPaste description: Extends MooEditable to insert text copied from other editors like word without all that messy style-information. -updates in this version: Improved Internet Explorer handling to break text on to new lines. Improved handling of some styles from newer versions of MS Word to remove extra style tags that were remaining. +updates in previous version: Improved Internet Explorer handling to break text on to new lines. Improved handling of some styles from newer versions of MS Word to remove extra style tags that were remaining. (David) + +updates in this version: Fixed CleanPaste in Safari (Jo) license: MIT-style license authors: -- André Fiedler +- AndrŽ Fiedler - David Bennett +- Jo Carter requires: - MooEditable @@ -26,7 +29,7 @@ usage: @@ -36,28 +39,40 @@ provides: [MooEditable.CleanPaste] ... */ -(function(){ +(function () { MooEditable = Class.refactor(MooEditable, { - - Extends: MooEditable, + + // @FIXED: Removed because inferred by above and breaks MooEditable completely with MooTools 1.3. + // Extends: MooEditable, - attach: function(){ + attach: function () { var ret = this.previous(); this.doc.body.addListener('paste', this.cleanPaste.bind(this)); return ret; }, - cleanPaste: function(e){ + cleanPaste: function (e) { var txtPastet = e.clipboardData && e.clipboardData.getData ? e.clipboardData.getData('text/html') : // Standard window.clipboardData && window.clipboardData.getData ? window.clipboardData.getData('Text') : // MS false; - if(!!txtPastet) { // IE and Safari - if(window.clipboardData) this.selection.insertContent(this.cleanHtml(txtPastet, 1)); // IE - else this.selection.insertContent(this.cleanHtml(txtPastet)); // Safari - new Event(e).stop(); + + // @FIXED: If !MS and data is not html - try this (ie. pasting plain text) + if ((!txtPastet || '' === txtPastet.trim()) && e.clipboardData && e.clipboardData.getData) { + txtPastet = e.clipboardData.getData('Text'); + } + + if (!!txtPastet) { // IE and Safari + if (window.clipboardData) { + this.selection.insertContent(this.cleanHtml(txtPastet, 1)); // IE + } + else { + this.selection.insertContent(this.cleanHtml(txtPastet)); // Safari + } + + new Event(e).stop(); } else { // no clipboard data available this.selection.insertContent(' '); @@ -68,127 +83,185 @@ provides: [MooEditable.CleanPaste] return this; }, - replaceMarkerWithPastedText: function(){ - var txtPastet = this.doc.body.get('html'); - var txtPastetClean = this.cleanHtml(txtPastet); + replaceMarkerWithPastedText: function () { + var txtPastetClean = this.cleanHtml(this.doc.body.get('html')); this.doc.body.set('html', this.txtMarked); - var node = this.doc.body.getElementById('INSERTION_MARKER'); - this.selection.selectNode(node); + this.selection.selectNode(this.doc.body.getElementById('INSERTION_MARKER')); this.selection.insertContent(txtPastetClean); return this; }, - cleanHtml: function(html, isie){ - if(isie) { - html = "

" + html + "<\/p>"; - html = html.replace(/\n/g, "<\/p>

"); - } - else { - - html = html.replace(/\s*<\/o:p>/g, ''); - html = html.replace(/[\s\S]*?<\/o:p>/g, ' '); - - // remove mso-xxx styles. - html = html.replace(/\s*mso-[^:]+:[^;'"]+;?/gi, ''); - - // remove margin styles. - html = html.replace(/\s*MARGIN: 0cm 0cm 0pt\s*;/gi, ''); - html = html.replace(/\s*MARGIN: 0cm 0cm 0pt\s*"/gi, "\""); - - html = html.replace(/\s*TEXT-INDENT: 0cm\s*;/gi, ''); - html = html.replace(/\s*TEXT-INDENT: 0cm\s*"/gi, "\""); - - html = html.replace(/\s*TEXT-ALIGN: [^\s;]+;?"/gi, "\""); - - html = html.replace(/\s*PAGE-BREAK-BEFORE: [^\s;]+;?"/gi, "\""); - - html = html.replace(/\s*FONT-VARIANT: [^\s;]+;?"/gi, "\""); - - html = html.replace(/\s*tab-stops:[^;"]*;?/gi, ''); - html = html.replace(/\s*tab-stops:[^"]*/gi, ''); - - // remove FONT face attributes. - html = html.replace(/\s*face="[^"]*"/gi, ''); - html = html.replace(/\s*face=[^ >]*/gi, ''); - - html = html.replace(/\s*FONT-FAMILY:[^;"]*;?/gi, ''); - - // remove class attributes - html = html.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3"); - - // remove styles. - html = html.replace(/<(\w[^>]*) style="([^\"]*)"([^>]*)/gi, "<$1$3"); - html = html.replace(/<(\w[^>]*) style='([^\']*)'([^>]*)/gi, "<$1$3"); - - // remove style, meta and link tags - html = html.replace(/]*>[\s\S]*?<\/STYLE[^>]*>/gi, ''); - html = html.replace(/<(?:META|LINK)[^>]*>\s*/gi, ''); - - // remove empty styles. - html = html.replace(/\s*style="\s*"/gi, ''); - - html = html.replace(/]*>\s* \s*<\/SPAN>/gi, ' '); - - html = html.replace(/]*><\/SPAN>/gi, ''); - - // remove lang attributes - html = html.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3"); - - html = html.replace(/([\s\S]*?)<\/SPAN>/gi, '$1'); - - html = html.replace(/([\s\S]*?)<\/FONT>/gi, '$1'); - - // remove XML elements and declarations - html = html.replace(/<\\?\?xml[^>]*>/gi, ''); - - // remove w: tags with contents. - html = html.replace(/]*>[\s\S]*?<\/w:[^>]*>/gi, ''); - - // remove tags with XML namespace declarations: <\/o:p> - html = html.replace(/<\/?\w+:[^>]*>/gi, ''); - - // remove comments [SF BUG-1481861]. - html = html.replace(/<\!--[\s\S]*?-->/g, ''); - - html = html.replace(/<(U|I|STRIKE)> <\/\1>/g, ' '); - - html = html.replace(/\s*<\/H\d>/gi, ''); - - // remove "display:none" tags. - html = html.replace(/<(\w+)[^>]*\sstyle="[^"]*DISPLAY\s?:\s?none[\s \S]*?<\/\1>/ig, ''); - - // remove language tags - html = html.replace(/<(\w[^>]*) language=([^ |>]*)([^>]*)/gi, "<$1$3"); - - // remove onmouseover and onmouseout events (from MS word comments effect) - html = html.replace(/<(\w[^>]*) onmouseover="([^\"]*)"([^>]*)/gi, "<$1$3"); - html = html.replace(/<(\w[^>]*) onmouseout="([^\"]*)"([^>]*)/gi, "<$1$3"); - - // the original tag send from word is something like this: - html = html.replace(/]*)>/gi, ''); - - // word likes to insert extra tags, when using IE. (Wierd). - html = html.replace(/<(H\d)>]*>([\s\S]*?)<\/FONT><\/\1>/gi, '<$1>$2<\/$1>'); - html = html.replace(/<(H\d)>([\s\S]*?)<\/EM><\/\1>/gi, '<$1>$2<\/$1>'); - - // remove "bad" tags - html = html.replace(/<\s+[^>]*>/gi, ''); - - // remove empty tags (three times, just to be sure). - // This also removes any empty anchor - html = html.replace(/<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, ''); - html = html.replace(/<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, ''); - html = html.replace(/<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, ''); - - // Convert

to
- if (!this.options.paragraphise) { - html.replace(/

/gi, '
'); - html.replace(/<\\p>/gi, ''); - } + cleanHtml: function (html, isie) { + if (isie) { + if (!this.options.paragraphise) { + html = html.replace(/\n/g, "
"); + } + else { + html = "

" + html + "<\/p>"; + html = html.replace(/\n/g, "<\/p>

"); + html = html.replace(/

\s<\/p>/gi, ''); } - return html; + alert(html); + } + else { + // @FIXED: Safari pastes in styles with ' not " - fixed to not be broken in safari + // @FIXED: Word pastes in Safari + + // remove body and html tag + html = html.replace(/]*?>(.*)/gim, "$1"); + html = html.replace(/<\/html>/gi, ''); + html = html.replace(/]*?>(.*)/gi, "$1"); + html = html.replace(/<\/body>/gi, ''); + + // remove style, meta and link tags + html = html.replace(/]*?>[\s\S]*?<\/style[^>]*>/gi, ''); + html = html.replace(/<(?:meta|link)[^>]*>\s*/gi, ''); + + // remove XML elements and declarations + html = html.replace(/<\\?\?xml[^>]*>/gi, ''); + + // remove w: tags with contents. + html = html.replace(/]*>[\s\S]*?<\/w:[^>]*>/gi, ''); + + // remove tags with XML namespace declarations: <\/o:p> + html = html.replace(/\s*<\/o:p>/g, ''); + html = html.replace(/[\s\S]*?<\/o:p>/g, ' '); + html = html.replace(/<\/?\w+:[^>]*>/gi, ''); + + // remove comments [SF BUG-1481861]. + html = html.replace(/<\!--[\s\S]*?-->/g, ''); + html = html.replace(/<\!\[[\s\S]*?\]>/g, ''); + + // remove mso-xxx styles. + html = html.replace(/\s*mso-[^:]+:[^;"']+;?/gi, ''); + + // remove styles. + html = html.replace(/<(\w[^>]*) style='([^\']*)'([^>]*)/gim, "<$1$3"); + html = html.replace(/<(\w[^>]*) style="([^\"]*)"([^>]*)/gim, "<$1$3"); + + // remove margin styles. + html = html.replace(/\s*margin: 0cm 0cm 0pt\s*;/gi, ''); + html = html.replace(/\s*margin: 0cm 0cm 0pt\s*"/gi, "\""); + + html = html.replace(/\s*text-indent: 0cm\s*;/gi, ''); + html = html.replace(/\s*text-indent: 0cm\s*"/gi, "\""); + + html = html.replace(/\s*text-align: [^\s;]+;?"/gi, "\""); + + html = html.replace(/\s*page-break-before: [^\s;]+;?"/gi, "\""); + + html = html.replace(/\s*font-variant: [^\s;]+;?"/gi, "\""); + + html = html.replace(/\s*tab-stops:[^;"']*;?/gi, ''); + html = html.replace(/\s*tab-stops:[^"']*/gi, ''); + + // remove font face attributes. + html = html.replace(/\s*face="[^"']*"/gi, ''); + html = html.replace(/\s*face=[^ >]*/gi, ''); + + html = html.replace(/\s*font-family:[^;"']*;?/gi, ''); + html = html.replace(/\s*font-size:[^;"']*;?/gi, ''); + + // remove class attributes + html = html.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3"); + + // remove "display:none" attributes. + html = html.replace(/<(\w+)[^>]*\sstyle="[^"']*display\s?:\s?none[\s \S]*?<\/\1>/ig, ''); + + // remove empty styles. + html = html.replace(/\s*style='\s*'/gi, ''); + html = html.replace(/\s*style="\s*"/gi, ''); + + html = html.replace(/]*>\s* \s*<\/span>/gi, ' '); + + html = html.replace(/]*><\/span>/gi, ''); + + // remove align attributes + html = html.replace(/<(\w[^>]*) align=([^ |>]*)([^>]*)/gi, "<$1$3"); + + // remove lang attributes + html = html.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3"); + + html = html.replace(/]*)>([\s\S]*?)<\/span>/gi, '$2'); + + html = html.replace(/([\s\S]*?)<\/font>/gi, '$1'); + + html = html.replace(/<(u|i|strike)> <\/\1>/gi, ' '); + + html = html.replace(/\s*<\/h\d>/gi, ''); + + // remove language attributes + html = html.replace(/<(\w[^>]*) language=([^ |>]*)([^>]*)/gi, "<$1$3"); + + // remove onmouseover and onmouseout events (from MS word comments effect) + html = html.replace(/<(\w[^>]*) onmouseover="([^\"']*)"([^>]*)/gi, "<$1$3"); + html = html.replace(/<(\w[^>]*) onmouseout="([^\"']*)"([^>]*)/gi, "<$1$3"); + + // the original tag sent from word is something like this: + html = html.replace(/]*)>/gi, ''); + + // word likes to insert extra tags, when using IE. (Weird). + html = html.replace(/<(h\d)>]*>([\s\S]*?)<\/font><\/\1>/gi, '<$1>$2<\/$1>'); + html = html.replace(/<(h\d)>([\s\S]*?)<\/em><\/\1>/gi, '<$1>$2<\/$1>'); + + // i -> em, b -> strong - doesn't match nested tags e.g some text - not possible in regexp + // @see - http://stackoverflow.com/questions/1721223/php-regexp-for-nested-div-tags etc. + html = html.replace(/]*>(.*?)<\/b[^>]*>/gi, '$1'); + html = html.replace(/]*>(.*?)<\/i[^>]*>/gi, '$1'); + + // remove "bad" tags + html = html.replace(/<\s+[^>]*>/gi, ''); + + // remove empty s (ie. no attributes, no reason for span in pasted text) + // done twice for nested spans + html = html.replace(/([\s\S]*?)<\/span>/gi, '$1'); + html = html.replace(/([\s\S]*?)<\/span>/gi, '$1'); + + // remove empty

s (see span) + html = html.replace(/
([\s\S]*?)<\/div>/gi, '$1'); + html = html.replace(/
([\s\S]*?)<\/div>/gi, '$1'); + + // remove empty tags (three times, just to be sure - for nested empty tags). + // This also removes any empty anchors + html = html.replace(/<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, ''); + html = html.replace(/<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, ''); + html = html.replace(/<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, ''); + + html = html.trim(); + + // Convert

to
+ if (!this.options.paragraphise) { + html.replace(/

/gi, '
'); + html.replace(/<\/p>/gi, ''); + } + // Check if in paragraph - this fixes FF3.6 and it's
issue + else { + var check = html.substr(0,2); + if (''; + // Replace breaks with paragraphs + html = html.replace(/\n/g, "<\/p>

"); + html = html.replace(/]*>/gi, '<\/p>

'); + } + } + + // Make it valid xhtml + html = html.replace(/
/gi, '
'); + + // remove
's that end a paragraph here. + html = html.replace(/]*><\/p>/gim, '

'); + + // remove empty paragraphs - with just a   (or whitespace) in (and tags again for good measure) + html = html.replace(/

 <\/p>/gi,''); + html = html.replace(/

\s<\/p>/gi, ''); + html = html.replace(/<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, ''); + + html = html.trim(); + } + + return html; } }); -})(); \ No newline at end of file +}()); \ No newline at end of file