summaryrefslogtreecommitdiff
path: root/addons/web_editor/static/src/js/summernote.js
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2015-08-28 15:07:16 +0200
committerChristophe Simonis <chs@odoo.com>2015-08-28 15:07:16 +0200
commitedeceba7df84a1782c125641ea39df31c93715b4 (patch)
tree21a123009ad9f0d3833c5b1bd5d96ef36f568470 /addons/web_editor/static/src/js/summernote.js
parent31518bc09b1ae2be37c3555799e2c122f0a4dbcd (diff)
parent7a768a495168e9b74c7f6b768aa9a975601501be (diff)
[MERGE] forward port of branch saas-6 up to 7a768a4
Due to `sale` rewrite (94716a3f14d929574c46ef165e4364d12a5903ed), the commit 503820acb6d82a85c0c49ac26f7e7f8cd73851dd has been partially ignored (in sale.order.line) and will be rewritten later using new-api.
Diffstat (limited to 'addons/web_editor/static/src/js/summernote.js')
-rw-r--r--addons/web_editor/static/src/js/summernote.js129
1 files changed, 92 insertions, 37 deletions
diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js
index 235bd6c3500..96462501825 100644
--- a/addons/web_editor/static/src/js/summernote.js
+++ b/addons/web_editor/static/src/js/summernote.js
@@ -24,6 +24,7 @@ var options = $.summernote.options;
dom.hasContentAfter = function (node) {
var next;
+ if(dom.isEditable(node)) return;
while (node.nextSibling) {
next = node.nextSibling;
if (next.tagName || dom.isVisibleText(next) || dom.isBR(next)) return next;
@@ -32,6 +33,7 @@ dom.hasContentAfter = function (node) {
};
dom.hasContentBefore = function (node) {
var prev;
+ if(dom.isEditable(node)) return;
while (node.previousSibling) {
prev = node.previousSibling;
if (prev.tagName || dom.isVisibleText(prev) || dom.isBR(prev)) return prev;
@@ -40,12 +42,12 @@ dom.hasContentBefore = function (node) {
};
dom.ancestorHaveNextSibling = function (node, pred) {
pred = pred || dom.hasContentAfter;
- while (!node.nextSibling || !pred(node)) { node = node.parentNode; }
+ while (!dom.isEditable(node) && (!node.nextSibling || !pred(node))) { node = node.parentNode; }
return node;
};
dom.ancestorHavePreviousSibling = function (node, pred) {
pred = pred || dom.hasContentBefore;
- while (!node.previousSibling || !pred(node)) { node = node.parentNode; }
+ while (!dom.isEditable(node) && (!node.previousSibling || !pred(node))) { node = node.parentNode; }
return node;
};
dom.nextElementSibling = function (node) {
@@ -369,6 +371,7 @@ dom.removeSpace = function (node, begin, so, end, eo) {
(function __remove_space (node) {
if (!node) return;
+ var t_begin, t_end;
for (var k=0; k<node.childNodes.length; k++) {
var cur = node.childNodes[k];
@@ -385,14 +388,20 @@ dom.removeSpace = function (node, begin, so, end, eo) {
if (node.childNodes.length > 1 && dom.isText(cur) && !dom.isVisibleText(cur)) {
removed = true;
if (cur === begin) {
- so = 0;
- begin = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(cur)));
+ t_begin = dom.hasContentBefore(dom.ancestorHavePreviousSibling(cur));
+ if(t_begin) {
+ so = 0;
+ begin = dom.lastChild(t_begin);
+ }
}
if (cur === end) {
- eo = 1;
- end = dom.firstChild(dom.hasContentAfter(dom.ancestorHaveNextSibling(cur)));
- if (dom.isText(end)) {
- eo = end.textContent.length;
+ t_end = dom.hasContentAfter(dom.ancestorHaveNextSibling(cur));
+ if(t_end) {
+ eo = 1;
+ end = dom.firstChild(t_end);
+ if (dom.isText(end)) {
+ eo = end.textContent.length;
+ }
}
}
cur.parentNode.removeChild(cur);
@@ -429,7 +438,7 @@ dom.removeSpace = function (node, begin, so, end, eo) {
sc: begin,
ec: end,
so: !dom.isBR(begin) && so > 0 ? so : 0,
- eo: eo
+ eo: dom.isBR(end) ? 0 : eo
};
};
dom.node = function (node) {
@@ -448,47 +457,61 @@ dom.pasteText = function (textNode, offset, text, isOnlyText) {
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;
}
- data.sc.splitText(data.so);
var first = data.sc;
- var last = data.sc.nextSibling;
+ 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 = node.tagName.toLowerCase();
+ 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 $text = $(text);
+ 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.pasteTextClose.indexOf(tag) !== -1) {
- var $next = $(node).clone().empty();
- $next.append( last );
- $(node).after( $next );
- $(node).after( $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 {
- $(data.sc).after( $text );
+ $(paste_after).after( nodes );
}
} else {
+ sc = ec = first;
+ so = dom.nodeLength(first);
+ eo = so + text.length;
first.appendData( text );
}
- // clean the dom content
- data = dom.merge(node.parentNode.parentNode, last, 0, last, 0, null, true);
- data = dom.removeSpace(node.parentNode.parentNode, data.sc, data.so, data.ec, data.eo);
-
// move caret
- range.create(data.sc, data.so, data.ec, data.eo).select();
+ 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) {
@@ -508,7 +531,7 @@ dom.removeBetween = function (sc, so, ec, eo, towrite) {
}
}
if (!eo && sc !== ec) {
- ec = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(ec)));
+ ec = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(ec)) || ec);
eo = ec.textContent.length;
}
@@ -555,8 +578,13 @@ dom.removeBetween = function (sc, so, ec, eo, towrite) {
}
}
- sc = before ? dom.lastChild(before) : dom.firstChild(after);
- so = sc.textContent.length;
+ if (dom.listAncestor(after).length <= dom.listAncestor(before).length) {
+ sc = dom.lastChild(before || ancestor);
+ so = dom.nodeLength(sc);
+ } else {
+ sc = dom.firstChild(after);
+ so = 0;
+ }
if (before) {
var text = sc.textContent.replace(/[ \t\n\r]+$/, '\u00A0');
@@ -565,7 +593,7 @@ dom.removeBetween = function (sc, so, ec, eo, towrite) {
}
if (towrite && !node.firstChild && node.parentNode && !dom.isNotBreakable(node)) {
var br = $("<br/>")[0];
- node.appendChild(br);
+ node.appendChild(sc);
sc = br;
so = 0;
}
@@ -829,13 +857,13 @@ range.WrappedRange.prototype.reRange = function (keep_end, isNotBreakable) {
if ($.contains(start, end)) {
if (keep_end) {
- sc = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(end)));
+ sc = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(end)) || sc);
so = sc.textContent.length;
} else if (!eo) {
- ec = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(end)));
+ ec = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(end)) || ec);
eo = ec.textContent.length;
} else {
- ec = dom.firstChild(dom.hasContentAfter(dom.ancestorHaveNextSibling(end)));
+ ec = dom.firstChild(dom.hasContentAfter(dom.ancestorHaveNextSibling(end)) || ec);
eo = 0;
}
} else {
@@ -864,6 +892,7 @@ range.WrappedRange.prototype.deleteContents = function (towrite) {
};
range.WrappedRange.prototype.clean = function (mergeFilter, all) {
var node = dom.node(this.sc === this.ec ? this.sc : this.commonAncestor());
+ node = node || $(this.sc).closest('[contenteditable]')[0];
if (node.childNodes.length <=1) {
return this;
}
@@ -941,7 +970,7 @@ $.summernote.pluginEvents.tab = function (event, editor, layoutInfo, outdent) {
var r = range.create();
var outdent = outdent || false;
- if (r.isCollapsed()) {
+ if (r && r.isCollapsed()) {
if (r.isOnCell() && r.isOnCellFirst()) {
var td = dom.ancestor(r.sc, dom.isCell);
if (!outdent && !dom.nextElementSibling(td) && !dom.nextElementSibling(td.parentNode)) {
@@ -1104,7 +1133,9 @@ $.summernote.pluginEvents.visible = function (event, editor, layoutInfo) {
$editable.data('NoteHistory').recordUndo($editable, "visible");
var r = range.create();
- if (r && !r.isCollapsed()) {
+ if (!r) return;
+
+ if (!r.isCollapsed()) {
r = r.deleteContents(true);
r.select();
}
@@ -1208,7 +1239,7 @@ $.summernote.pluginEvents.delete = function (event, editor, layoutInfo) {
}
while (dom.isImg(node)) {
parent = node.parentNode;
- index = dom.makeOffsetPath(parent, node)[0];
+ index = dom.position(node);
if (index>0) {
var next = node.previousSibling;
range.create(next,next.textContent.length).select();
@@ -1289,6 +1320,7 @@ $.summernote.pluginEvents.backspace = function (event, editor, layoutInfo) {
$editable.data('NoteHistory').recordUndo($editable, "backspace");
var r = range.create();
+ if (!r) return;
if (!r.isContentEditable()) {
event.preventDefault();
return false;
@@ -1313,10 +1345,15 @@ $.summernote.pluginEvents.backspace = function (event, editor, layoutInfo) {
var node = dom.node(target);
var data = dom.merge(node, target, offset, target, offset, null, true);
data = dom.removeSpace(node.parentNode, data.sc, data.so, data.ec, data.eo);
- r = range.create(data.sc, data.so);
+ r = dom.isVoid(data.sc) ? range.createFromNode(data.sc) : range.create(data.sc, data.so);
r.select();
target = r.sc;
offset = r.so;
+ if (target.tagName && target.childNodes[offset]) {
+ target = target.childNodes[offset];
+ offset = 0;
+ node = dom.node(target);
+ }
while (node.parentNode && !dom.hasContentAfter(node) && !dom.hasContentBefore(node) && !dom.isImg(node)) {node = node.parentNode;}
@@ -1779,6 +1816,22 @@ eventHandler.toolbar.button.updateRecentColor = function (elBtn, sEvent, sValue)
return false;
};
+$(document).on('click keyup', function () {
+ var $popover = $((range.create()||{}).sc).closest('[contenteditable]');
+ var popover_history = ($popover.data()||{}).NoteHistory;
+ if(!popover_history || popover_history == history) return;
+ var editor = $popover.parent('.note-editor');
+ $('button[data-event="undo"]', editor).attr('disabled', !popover_history.hasUndo());
+ $('button[data-event="redo"]', editor).attr('disabled', !popover_history.hasRedo());
+});
+
+eventHandler.editor.undo = function ($popover) {
+ if(!$popover.attr('disabled')) $popover.data('NoteHistory').undo();
+};
+eventHandler.editor.redo = function ($popover) {
+ if(!$popover.attr('disabled')) $popover.data('NoteHistory').redo();
+};
+
options.fontSizes = [_t('Default'), 8, 9, 10, 11, 12, 14, 18, 24, 36, 48, 62];
$.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color, bgcolor, size) {
var rng = range.create();
@@ -2183,9 +2236,11 @@ function summernote_paste (event) {
if (!r.isCollapsed()) {
r = r.deleteContents();
r.select();
+ event.preventDefault();
+ return false;
}
- var text = clipboardData.getData("text/plain").replace(/</g, "&lt;");
+ var text = $('<div />').text(clipboardData.getData("text/plain").toString()).html();
dom.pasteText(r.sc, r.so, text);
event.preventDefault();
return false;