diff options
| author | Christophe Matthieu <chm@odoo.com> | 2015-10-15 16:36:49 +0200 |
|---|---|---|
| committer | Christophe Matthieu <chm@odoo.com> | 2015-10-26 11:43:36 +0100 |
| commit | a291adb31422cd4514ff0185a885c2f82cdd9e4b (patch) | |
| tree | 9627125168db6808085c2fd475dcb1b72f3b2c67 /addons/web_editor/static/src | |
| parent | d7b5eeabeb7ce0a4b0ceba783756e69b3e64d6c4 (diff) | |
[FIX] web_editor: copy-paste content keep architecture
The paste don't keep the architecture, usability team want to past the architecture but remove extra style and wrong node like span.
Diffstat (limited to 'addons/web_editor/static/src')
| -rw-r--r-- | addons/web_editor/static/src/js/summernote.js | 166 |
1 files changed, 81 insertions, 85 deletions
diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js index 354deb19902..8b30ca74011 100644 --- a/addons/web_editor/static/src/js/summernote.js +++ b/addons/web_editor/static/src/js/summernote.js @@ -134,7 +134,7 @@ dom.hasProgrammaticStyle = function (node) { }; dom.mergeFilter = function (prev, cur, parent) { // merge text nodes - if (prev && (dom.isText(prev) || (dom.pasteTextApply.indexOf(prev.tagName) !== -1 && prev !== cur.parentNode)) && dom.isText(cur)) { + if (prev && (dom.isText(prev) || ("H1 H2 H3 H4 H5 H6 LI P".indexOf(prev.tagName) !== -1 && prev !== cur.parentNode)) && dom.isText(cur)) { return true; } if (prev && prev.tagName === "P" && dom.isText(cur)) { @@ -444,75 +444,6 @@ dom.removeSpace = function (node, begin, so, end, eo) { dom.node = function (node) { return node.tagName ? node : node.parentNode; }; -dom.pasteTextApply = "h1 h2 h3 h4 h5 h6 li p".split(" "); -dom.pasteTextClose = "h1 h2 h3 h4 h5 h6 p b bold i u code sup strong small li pre".split(" "); -dom.pasteText = function (textNode, offset, text, isOnlyText) { - // clean the node - var node = dom.node(textNode); - var data = dom.merge(node.parentNode, textNode, offset, textNode, offset, null, true); - data = dom.removeSpace(node.parentNode, data.sc, data.so, data.ec, data.eo); - // Break the text node up - if (data.sc.tagName) { - if (node === data.sc.parentNode) { - data.sc = node.insertBefore(document.createTextNode(" "), data.sc); - } else if (node.firstChild && !dom.isBR(dom.firstChild(node))) { - data.sc = node.insertBefore(document.createTextNode(" "), dom.firstChild(node)); - } else if (dom.isBR(node)) { - data.sc = node.parentNode.insertBefore(document.createTextNode(" "), node); - } else { - data.sc = node.appendChild(document.createTextNode(" ")); - } - data.so = 0; - } - var first = data.sc; - var try_to_clean = [first, first.splitText(data.so)]; - - isOnlyText = isOnlyText || !text.match('\n'); - - var sc, so, ec, eo; - - if (!isOnlyText) { - var paste_after = dom.isBR(node) ? node.parentElement : node; - - // tag to close and open - var tag = paste_after.tagName.toLowerCase(); - if(dom.pasteTextApply.indexOf(tag) === -1) { - text = text.split('\n').join("<br/>"); - paste_after = data.sc; - } else { - text = "<"+tag+">"+text.split('\n').join("</"+tag+"><"+tag+">")+"</"+tag+">"; - try_to_clean.push(paste_after); - } - - var nodes = _.toArray($('<div/>').html(text).prop('childNodes')); - sc = nodes[0]; - so = 0; - ec = dom.lastChild(nodes[nodes.length - 1]); - eo = dom.nodeLength(ec); - - // split parent node and insert text - if(!dom.isText(paste_after) && dom.pasteTextClose.indexOf(tag) !== -1) { - try_to_clean.push(dom.splitTree(paste_after, {node: first, offset: data.so})); - $(paste_after).after( nodes ); - } else { - $(paste_after).after( nodes ); - } - } else { - sc = ec = first; - so = dom.nodeLength(first); - eo = so + text.length; - first.appendData( text ); - } - - // move caret - range.create(sc, so, ec, eo).clean().select(); - - _(try_to_clean).each(function(node){ - _(dom.listDescendant(node).reverse().concat(node)).each(function(subnode){ - if(dom.isEmpty(subnode) || (dom.isText(subnode) && !dom.isVisibleText(subnode))) $(subnode).remove(); - }); - }); -}; dom.removeBetween = function (sc, so, ec, eo, towrite) { if (ec.tagName) { if (ec.childNodes[eo]) { @@ -2301,6 +2232,7 @@ eventHandler.modules.popover.update = function ($popover, oStyle, isAirMode) { ////////////////////////////////////////////////////////////////////////////////////////////////////////// function summernote_paste (event) { + // keep norma feature if copy a picture var clipboardData = event.originalEvent.clipboardData; if (clipboardData.items) { @@ -2311,36 +2243,100 @@ function summernote_paste (event) { } } - var $editable = $(event.currentTarget); - $editable = $editable.is('[contenteditable]') ? $editable : $editable.find('[contenteditable]'); - $editable.data('NoteHistory').recordUndo($editable); + if (["INPUT", "TEXTAREA"].indexOf(event.target.tagName) !== -1) { + return; + } - if (["INPUT", "TEXTAREA"].indexOf(event.target.tagName) === -1) { - var r = range.create(); - if (!r.isCollapsed()) { - r = r.deleteContents(); - r.select(); - } + $(event.target).trigger('content_changed'); - var text = $('<div />').text(clipboardData.getData("text/plain").toString()).html(); - dom.pasteText(r.sc, r.so, text); - event.preventDefault(); - return false; + var r = range.create(); + if (!r.isCollapsed()) { + r = r.deleteContents(); + r.select(); } + + var html = clipboardData.getData("text/html"); + var $node = $('<div/>').html(html); + + /* + remove undesirable tag + filter classes and style attributes + remove undesirable attributes + */ + $node.find('meta, script, style').remove(); + $node.find('*').each(function() { + var $node = $(this); + + if ($(this).attr('style')) { + var style = _.filter($(this).attr('style').split(/\s*;\s*/), function (style) { + return /width|height|color|background-color|font-weight|text-align|font-style|text-decoration/i.test(style) && $node.css(style.split(':')[0]) !== $('body').css(style.split(':')[0]); + }).join(';'); + if (style.length) { + $node.attr('style', style); + } else { + $node.removeAttr('style'); + } + } + + if ($(this).attr('class')) { + var classes = _.filter($(this).attr('class').split(/\s+/), function (style) { + return /(^|\s)(fa|pull|text|bg)(\s|-|$)/.test(style); + }).join(' '); + if (classes.length) { + $node.attr('class', classes); + } else { + $node.removeAttr('class'); + } + } + }).removeAttr('title', 'alt', 'id', 'contenteditable'); + + /* + remove unless span + */ + $node.find('span:not([class]):not([style])').each(function () { + $(this).replaceWith($(this).contents()); + }); + + /* + reset architecture HTML node and add <p> tag + */ + var $arch = $('<div><p/></div>'); + var $last = $arch.find('p'); + $node.contents().each(function () { + if (dom.isBR(this)) { + $(this).remove(); + $last = $('<p/>'); + $arch.append($last); + } else if (/h[0-9]+|li|table|p/i.test(this.tagName)) { + $last = $('<p/>'); + $arch.append(this).append($last); + } else { + $last.append(this); + } + }); + $last.filter(':empty').remove(); + + /* + insert content + */ + window.document.execCommand('insertHTML', false, $arch.html()); + + event.preventDefault(); + return false; } var fn_attach = eventHandler.attach; eventHandler.attach = function (oLayoutInfo, options) { var $editable = oLayoutInfo.editor().hasClass('note-editable') ? oLayoutInfo.editor() : oLayoutInfo.editor().find('.note-editable'); fn_attach.call(this, oLayoutInfo, options); - oLayoutInfo.editor().on("paste", summernote_paste); + $(document).off("paste", summernote_paste).on("paste",'[contenteditable]', summernote_paste); $editable.on("scroll", summernote_table_scroll); }; var fn_detach = eventHandler.detach; eventHandler.detach = function (oLayoutInfo, options) { var $editable = oLayoutInfo.editor().hasClass('note-editable') ? oLayoutInfo.editor() : oLayoutInfo.editor().find('.note-editable'); fn_detach.call(this, oLayoutInfo, options); - oLayoutInfo.editor().off("paste", summernote_paste); + $(document).off("paste", summernote_paste); $editable.off("scroll", summernote_table_scroll); $('.o_table_handler').remove(); }; |
