diff --git a/addons/web_editor/static/src/js/rte.js b/addons/web_editor/static/src/js/rte.js index e177846c0fd..9ce1e5fb255 100644 --- a/addons/web_editor/static/src/js/rte.js +++ b/addons/web_editor/static/src/js/rte.js @@ -271,10 +271,11 @@ var RTE = Widget.extend({ * @param {DOM} target where the dom is changed is editable zone */ historyRecordUndo: function ($target, event, internal_history) { + $target = $($target); var rng = range.create(); var $editable = $(rng && rng.sc).closest(".o_editable"); if (!rng || !$editable.length) { - $editable = $($target).closest(".o_editable"); + $editable = $target.closest(".o_editable"); rng = range.create($target.closest("*")[0],0); } else { rng = $editable.data('range') || rng; diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js index e439f52824a..35e49346ee0 100644 --- a/addons/web_editor/static/src/js/summernote.js +++ b/addons/web_editor/static/src/js/summernote.js @@ -886,37 +886,67 @@ range.WrappedRange.prototype.reRange = function (keep_end, isNotBreakable) { return new range.WrappedRange(sc, so, ec, eo); }; -// isOnImg: judge whether range is an image node or not +/** + * Returns the image the range is in or matches (if any, false otherwise). + * + * @todo this implementation may not cover all corner cases but should do the + * trick for all reproductible ones + * @returns {DOMElement|boolean} + */ range.WrappedRange.prototype.isOnImg = function () { + // If not a selection but a cursor position, just check if a point's + // ancestor is an image or not + if (this.sc === this.ec && this.so === this.eo) { + return dom.ancestor(this.sc, dom.isImg); + } + + var startPoint = {node: this.sc, offset: this.so}; + var endPoint = {node: this.ec, offset: this.eo}; + var nb = 0; var image; - var startPoint = {node: this.sc.childNodes.length && this.sc.childNodes[this.so] || this.sc}; - startPoint.offset = startPoint.node === this.sc ? this.so : 0; - var endPoint = {node: this.ec.childNodes.length && this.ec.childNodes[this.eo] || this.ec}; - endPoint.offset = endPoint.node === this.ec ? this.eo : 0; - - if (dom.isImg(startPoint.node)) { - nb ++; - image = startPoint.node; - } + var textNode; dom.walkPoint(startPoint, endPoint, function (point) { - if (!dom.isText(endPoint.node) && point.node === endPoint.node && point.offset === endPoint.offset) { + // If the element has children (not a text node and not empty node), + // the element cannot be considered as selected (these children will + // be processed to determine that) + if (dom.hasChildren(point.node)) { return; } - var node = point.node.childNodes.length && point.node.childNodes[point.offset] || point.node; - var offset = node === point.node ? point.offset : 0; - var isImg = dom.ancestor(node, dom.isImg); - if (!isImg && ((!dom.isBR(node) && !dom.isText(node)) || (offset && node.textContent.length !== offset && node.textContent.match(/\S|\u00A0/)))) { + + // Check if an ancestor of the current point is an image + var pointImg = dom.ancestor(point.node, dom.isImg); + var isText = dom.isText(point.node); + + // Check if a visible element is selected, i.e. + // - If an ancestor of the current is an image we did not see yet + // - If the point is not in a br or a text (so a node with no children) + // - If the point is in a non empty text node we already saw + if (pointImg ? + (image !== pointImg) : + ((!dom.isBR(point.node) && !isText) || (textNode === point.node && point.node.textContent.match(/\S|\u00A0/)))) { nb++; } - if (isImg && image !== isImg) { - image = isImg; - nb ++; + + // If an ancestor of the current point is an image, then save it as the + // image we are looking for + if (pointImg) { + image = pointImg; + } + // If the current point is a text node save it as the last text node + // seen (if we see it again, this might mean it is selected) + if (isText) { + textNode = point.node; } }); + return nb === 1 && image; }; range.WrappedRange.prototype.deleteContents = function (towrite) { + if (this.sc === this.ec && this.so === this.eo) { + return this; + } + var prevBP = dom.removeBetween(this.sc, this.so, this.ec, this.eo, towrite); $(dom.node(prevBP.sc)).trigger("click"); // trigger click to disable and reanable editor and image handler diff --git a/doc/cla/corporate/bas-solutions.md b/doc/cla/corporate/bas-solutions.md deleted file mode 100644 index f0d49c7facf..00000000000 --- a/doc/cla/corporate/bas-solutions.md +++ /dev/null @@ -1,16 +0,0 @@ -Netherlands, 8-2-2015 - -BAS Solutions agrees to the terms of the Odoo Corporate Contributor License -Agreement v1.0. - -I declare that I am authorized and able to make this agreement and sign this -declaration. - -Signed, - -Erwin van der Ploeg erwin@bas-solutions.nl https://github.com/erwin-bas-solutions - -List of contributors: - -Erwin van der Ploeg erwin@bas-solutions.nl https://github.com/erwin-bas-solutions -Ruchir Shukla ruchir@bas-solutions.nl https://github.com/ruchir-bas-solutions \ No newline at end of file diff --git a/doc/cla/corporate/odooexperts.md b/doc/cla/corporate/odooexperts.md new file mode 100644 index 00000000000..3a73e799b87 --- /dev/null +++ b/doc/cla/corporate/odooexperts.md @@ -0,0 +1,16 @@ +Netherlands, 18-1-2018 + +Odoo Experts agrees to the terms of the Odoo Corporate Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Erwin van der Ploeg erwin@bas-solutions.nl https://github.com/erwin-bas-solutions + +List of contributors: + +Erwin van der Ploeg erwin@odooexperts.nl https://github.com/ploegvde +Yenthe Van Ginneken yenthe@odooexperts.nl https://github.com/Yenthe666