diff options
| author | Christophe Simonis <chs@odoo.com> | 2015-08-24 18:19:19 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2015-08-24 18:19:19 +0200 |
| commit | 88c0ce0692ccf3b1302e15c4ebe34dbf2040be40 (patch) | |
| tree | 5bb1749f69f96df22a92a747052dc2965e83430e /addons/web_editor/static/src/js | |
| parent | 878c3c9291ad69b530d24227cb25b38dbf10229b (diff) | |
| parent | e16d495d8965522d90ddf5d5da234b1650a695f9 (diff) | |
[MERGE] forward port of branch saas-6 up to e16d495
Diffstat (limited to 'addons/web_editor/static/src/js')
| -rw-r--r-- | addons/web_editor/static/src/js/editor.js | 2 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/snippets.editor.js | 85 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/snippets.options.js | 26 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/summernote.js | 29 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/widgets.js | 18 |
5 files changed, 97 insertions, 63 deletions
diff --git a/addons/web_editor/static/src/js/editor.js b/addons/web_editor/static/src/js/editor.js index f9255716697..4480101bf6a 100644 --- a/addons/web_editor/static/src/js/editor.js +++ b/addons/web_editor/static/src/js/editor.js @@ -144,6 +144,8 @@ editor.Class = Widget.extend({ d.resolve(); }).on('hidden.bs.modal', function () { d.reject(); + }).on('keydown.dismiss.bs.modal', function (event) { + event.stopImmediatePropagation(); }); d.always(function () { $dialog.remove(); diff --git a/addons/web_editor/static/src/js/snippets.editor.js b/addons/web_editor/static/src/js/snippets.editor.js index cc380833074..3de9b71d5f8 100644 --- a/addons/web_editor/static/src/js/snippets.editor.js +++ b/addons/web_editor/static/src/js/snippets.editor.js @@ -531,7 +531,8 @@ var BuildingBlock = Widget.extend({ this.snippets.push($snippet.get(0)); } this.$active_snipped_id = $snippet; - this.create_overlay(this.$active_snipped_id); + this.create_snippet_editor(this.$active_snipped_id); + this.cover_target($snippet.data('overlay'), $snippet); this.snippet_focus($snippet); } this.$snippet.trigger('snippet-activated', $snippet); @@ -539,13 +540,11 @@ var BuildingBlock = Widget.extend({ $snippet.trigger('snippet-activated', $snippet); } }, - create_overlay: function ($snippet) { + create_snippet_editor: function ($snippet) { if (typeof $snippet.data("snippet-editor") === 'undefined') { - var $targets = this.activate_overlay_zones($snippet); - if (!$targets.length) return; + if (!this.activate_overlay_zones($snippet).length) return; $snippet.data("snippet-editor", new Editor(this, $snippet)); } - this.cover_target($snippet.data('overlay'), $snippet); }, // activate drag and drop for the snippets in the snippet toolbar @@ -657,22 +656,12 @@ var BuildingBlock = Widget.extend({ animation.start(true, $target); - // drop_and_build_snippet - self.create_overlay($target); - if ($target.data("snippet-editor")) { - $target.data("snippet-editor").drop_and_build_snippet(); - } - for (var k in self.templateOptions) { - self.templateOptions[k].selector.all($target).each(function () { - var $snippet = $(this); - self.create_overlay($snippet); - if ($snippet.data("snippet-editor")) { - $snippet.data("snippet-editor").drop_and_build_snippet(); - } - }); - } + self.call_for_all_snippets($target, function (editor, $snippet) { + editor.drop_and_build_snippet(); + }); + self.create_snippet_editor($target); + self.cover_target($target.data('overlay'), $target); $target.closest(".o_editable").trigger("content_changed"); - // end self.make_active($target); },0); @@ -683,6 +672,20 @@ var BuildingBlock = Widget.extend({ }); }, + // call a method on a snippet and all his children + call_for_all_snippets: function ($snippet, callback) { + var self = this; + $snippet.add(globalSelector.all($snippet)).each(function () { + var $snippet = $(this); + setTimeout(function () { + self.create_snippet_editor($snippet); + if ($snippet.data("snippet-editor")) { + callback.call(self, $snippet.data("snippet-editor"), $snippet); + } + }); + }); + }, + // return the original snippet in the editor bar from a snippet id (string) get_snippet_from_id: function(id){ return $('.oe_snippet').filter(function(){ @@ -845,14 +848,12 @@ var BuildingBlock = Widget.extend({ var timer; $target.closest('.o_editable').on("content_changed", function (event) { - if ($target.data('overlay') && $target.data('overlay').hasClass("oe_active")) { - clearTimeout(timer); - timer = setTimeout(function () { - if ($target.data('overlay')) { - self.cover_target($target.data('overlay'), $target); - } - },50); - } + clearTimeout(timer); + timer = setTimeout(function () { + if ($target.data('overlay') && $target.data('overlay').hasClass("oe_active")) { + self.cover_target($target.data('overlay'), $target); + } + },50); }); var resize = function () { @@ -985,7 +986,9 @@ var Editor = Class.extend({ self.buildingBlock.editor_busy = false; self.get_parent_block(); - setTimeout(function () {self.buildingBlock.create_overlay(self.$target);},0); + setTimeout(function () { + self.BuildingBlock.cover_target(self.$target.data('overlay'), self.$target); + },0); }, load_style_options: function () { @@ -1022,7 +1025,10 @@ var Editor = Class.extend({ get_parent_block: function () { var self = this; var $button = this.$overlay.find('.oe_snippet_parent'); - var $parent = globalSelector.closest(this.$target.parent()); + var $parent = this.$target.parents().filter(function () { return $(this).data("snippet-editor"); }); + if (!$parent.length) { + $parent = globalSelector.closest(this.$target.parent()); + } if ($parent.length) { $button.removeClass("hidden"); $button.off("click").on('click', function (event) { @@ -1056,12 +1062,13 @@ var Editor = Class.extend({ var $clone = this.$target.clone(false); this.buildingBlock.parent.rte.historyRecordUndo(this.$target); - + this.$target.after($clone); - for (var i in this.styles){ - this.styles[i].on_clone($clone); - } - this.buildingBlock.create_overlay(this.$target); + this.BuildingBlock.call_for_all_snippets($clone, function (editor, $snippet) { + for (var i in editor.styles){ + editor.styles[i].on_clone($snippet); + } + }); return false; }, @@ -1072,9 +1079,11 @@ var Editor = Class.extend({ this.buildingBlock.parent.rte.historyRecordUndo(this.$target); var index = _.indexOf(this.buildingBlock.snippets, this.$target.get(0)); - for (var i in this.styles){ - this.styles[i].on_remove(); - } + this.BuildingBlock.call_for_all_snippets(this.$target, function (editor, $snippet) { + for (var i in editor.styles){ + editor.styles[i].on_remove(); + } + }); delete this.buildingBlock.snippets[index]; var $editable = this.$target.closest(".o_editable"); diff --git a/addons/web_editor/static/src/js/snippets.options.js b/addons/web_editor/static/src/js/snippets.options.js index 4dce2e358ed..df4ec303894 100644 --- a/addons/web_editor/static/src/js/snippets.options.js +++ b/addons/web_editor/static/src/js/snippets.options.js @@ -319,20 +319,20 @@ var colorpicker = Option.extend({ var background = Option.extend({ start: function ($change_target) { - this.$bg = $change_target || this.$target; + this.$target = $change_target || this.$target; this._super(); - var src = this.$bg.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, ""); - if (this.$bg.hasClass('oe_custom_bg')) { + var src = this.$target.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, ""); + if (this.$target.hasClass('oe_custom_bg')) { this.$el.find('li[data-choose_image]').data("background", src).attr("data-background", src); } }, background: function(type, value, $li) { if (value && value.length) { - this.$bg.attr("style", 'background-image: url(' + value + '); ' + (this.$bg.attr("style") || '').replace(/background-image:[^;]+/, '') ); - this.$bg.addClass("oe_img_bg"); + this.$target.attr("style", 'background-image: url(' + value + '); ' + (this.$target.attr("style") || '').replace(/background-image:[^;]+/, '') ); + this.$target.addClass("oe_img_bg"); } else { - this.$bg.css("background-image", ""); - this.$bg.removeClass("oe_img_bg").removeClass("oe_custom_bg"); + this.$target.css("background-image", ""); + this.$target.removeClass("oe_img_bg").removeClass("oe_custom_bg"); } }, select_class : function(type, value, $li) { @@ -345,7 +345,7 @@ var background = Option.extend({ var self = this; var $image = $('<img class="hidden"/>'); $image.attr("src", value); - $image.appendTo(self.$bg); + $image.appendTo(self.$target); var _editor = new widget.MediaDialog(null, $image[0]); _editor.appendTo(document.body); @@ -356,8 +356,8 @@ var background = Option.extend({ $image.remove(); self.$el.find('li[data-choose_image]').data("background", value).attr("data-background", value); self.background(type, value,$li); - self.$bg.addClass('oe_custom_bg'); - self.$bg.trigger("snippet-option-change", [self]); + self.$target.addClass('oe_custom_bg'); + self.$target.trigger("snippet-option-change", [self]); self.set_active(); }); _editor.on('cancel', self, function () { @@ -366,9 +366,13 @@ var background = Option.extend({ }, set_active: function () { var self = this; - var src = this.$bg.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, ""); + var src = this.$target.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, ""); this._super(); + if (this.$target.hasClass('oe_custom_bg')) { + this.$el.find('li[data-choose_image]').data("background", src).attr("data-background", src); + } + this.$el.find('li[data-background]:not([data-background=""])') .removeClass("active") .each(function () { diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js index 46b21aeec88..235bd6c3500 100644 --- a/addons/web_editor/static/src/js/summernote.js +++ b/addons/web_editor/static/src/js/summernote.js @@ -26,7 +26,7 @@ dom.hasContentAfter = function (node) { var next; while (node.nextSibling) { next = node.nextSibling; - if (next.tagName || next.textContent.match(/\S|\u00A0/) || dom.isBR(next)) return next; + if (next.tagName || dom.isVisibleText(next) || dom.isBR(next)) return next; node = next; } }; @@ -34,7 +34,7 @@ dom.hasContentBefore = function (node) { var prev; while (node.previousSibling) { prev = node.previousSibling; - if (prev.tagName || prev.textContent.match(/\S|\u00A0/) || dom.isBR(prev)) return prev; + if (prev.tagName || dom.isVisibleText(prev) || dom.isBR(prev)) return prev; node = prev; } }; @@ -138,7 +138,7 @@ dom.mergeFilter = function (prev, cur, parent) { if (prev && prev.tagName === "P" && dom.isText(cur)) { return true; } - if (prev && dom.isText(cur) && !cur.textContent.match(/\S|\u00A0/) && (dom.isText(prev) || prev.textContent.match(/\S|\u00A0/))) { + if (prev && dom.isText(cur) && !dom.isVisibleText(cur) && (dom.isText(prev) || dom.isVisibleText(prev))) { return true; } if (prev && !dom.isBR(prev) && dom.isEqual(prev, cur) && @@ -382,7 +382,7 @@ dom.removeSpace = function (node, begin, so, end, eo) { if (cur === end) add = false; // remove begin empty text node - if (node.childNodes.length > 1 && dom.isText(cur) && !cur.textContent.match(/\S|\u00A0/)) { + if (node.childNodes.length > 1 && dom.isText(cur) && !dom.isVisibleText(cur)) { removed = true; if (cur === begin) { so = 0; @@ -579,7 +579,7 @@ dom.removeBetween = function (sc, so, ec, eo, towrite) { } eo = so; - if(!dom.isBR(sc) && !sc.textContent.match(/\S|\u00A0/) && !dom.isText(dom.hasContentBefore(sc)) && !dom.isText(dom.hasContentAfter(sc))) { + if(!dom.isBR(sc) && !dom.isVisibleText(sc) && !dom.isText(dom.hasContentBefore(sc)) && !dom.isText(dom.hasContentAfter(sc))) { ancestor = dom.node(sc); var text = document.createTextNode('\u00A0'); $(sc).before(text); @@ -699,6 +699,9 @@ dom.isContentEditable = function (node) { return $(node).closest('[contenteditable]').is('[contenteditable="true"]'); }; +dom.isPre = function (node) { + return node.tagName === "PRE"; +}; dom.isFont = function (node) { var nodeName = node && node.nodeName.toUpperCase(); return node && (nodeName === "FONT" || @@ -1025,6 +1028,8 @@ $.summernote.pluginEvents.enter = function (event, editor, layoutInfo) { } var node = dom.node(r.sc); + var exist = r.sc.childNodes[r.so] || r.sc; + exist = dom.isVisibleText(exist) || dom.isBR(exist) ? exist : dom.hasContentAfter(exist) || (dom.hasContentBefore(exist) || exist); var last = node; while (node && dom.isSplitable(node) && !dom.isList(node)) { last = node; @@ -1042,7 +1047,7 @@ $.summernote.pluginEvents.enter = function (event, editor, layoutInfo) { } while (node && dom.isBR(node)); // create an other br because the user can't see the new line with only br in a block - if (!node) { + if (!node && (!br.nextElementSibling || !dom.isBR(br.nextElementSibling))) { $(br).before($("<br/>")[0]); } node = br.nextSibling || br; @@ -1051,7 +1056,11 @@ $.summernote.pluginEvents.enter = function (event, editor, layoutInfo) { node = br; } else if (!r.so && r.isOnList() && !r.sc.textContent.length && !dom.ancestor(r.sc, dom.isLi).nextElementSibling) { // double enter on the end of a list = new line out of the list - node = $('<p></p>').append(br).insertAfter(dom.ancestor(r.sc, dom.isList))[0]; + $('<p></p>').append(br).insertAfter(dom.ancestor(r.sc, dom.isList)); + node = br; + } else if (dom.isBR(exist) && $(r.sc).closest('blockquote, pre').length && !dom.hasContentAfter($(exist.parentNode).closest('blockquote *, pre *').length ? exist.parentNode : exist)) { + // double enter on the end of a blockquote & pre = new line out of the list + $('<p></p>').append(br).insertAfter($(r.sc).closest('blockquote, pre')); node = br; } else if (last === r.sc) { if (dom.isBR(last)) { @@ -1071,7 +1080,7 @@ $.summernote.pluginEvents.enter = function (event, editor, layoutInfo) { $(cur).html(br); } } - if (!node.textContent.match(/\S|\u00A0/)) { + if (!dom.isVisibleText(node)) { node = dom.firstChild(node); $(dom.node( dom.isBR(node) ? node.parentNode : node )).html(br); node = br; @@ -1105,7 +1114,7 @@ $.summernote.pluginEvents.visible = function (event, editor, layoutInfo) { while (node.parentNode) { if (dom.isForbiddenNode(node)) { var text = node.previousSibling; - if (text && dom.isText(text) && text.textContent.match(/\S|\u00A0/)) { + if (text && dom.isText(text) && dom.isVisibleText(text)) { range.create(text, text.textContent.length, text, text.textContent.length).select(); } else { text = node.parentNode.insertBefore(document.createTextNode( "." ), node); @@ -1715,7 +1724,7 @@ $.summernote.pluginEvents.formatBlock = function (event, editor, layoutInfo, sTa // fix by odoo because if you select a style in a li with no p tag all the ul is wrapped by the style tag var nodes = dom.listBetween(r.sc, r.ec); for (var i=0; i<nodes.length; i++) { - if (dom.isBR(nodes[i]) || (dom.isText(nodes[i]) && nodes[i].textContent.match(/\S|\u00A0/)) || dom.isB(nodes[i]) || dom.isU(nodes[i]) || dom.isS(nodes[i]) || dom.isI(nodes[i]) || dom.isFont(nodes[i])) { + if (dom.isBR(nodes[i]) || (dom.isText(nodes[i]) && dom.isVisibleText(nodes[i])) || dom.isB(nodes[i]) || dom.isU(nodes[i]) || dom.isS(nodes[i]) || dom.isI(nodes[i]) || dom.isFont(nodes[i])) { var ancestor = dom.ancestor(nodes[i], isFormatNode); if (!ancestor) { dom.wrap(nodes[i], sTagName); diff --git a/addons/web_editor/static/src/js/widgets.js b/addons/web_editor/static/src/js/widgets.js index acd8c859535..5e852a1c5ef 100644 --- a/addons/web_editor/static/src/js/widgets.js +++ b/addons/web_editor/static/src/js/widgets.js @@ -16,6 +16,7 @@ var dom = $.summernote.core.dom; var Dialog = Widget.extend({ events: { 'hidden.bs.modal': 'destroy', + 'keydown.dismiss.bs.modal': 'stop_escape', 'click button.save': 'save', 'click button[data-dismiss="modal"]': 'cancel', }, @@ -38,6 +39,11 @@ var Dialog = Widget.extend({ close: function () { this.$el.modal('hide'); }, + stop_escape: function(event) { + if($(".modal.in").length>0 && event.which == 27){ + event.stopPropagation(); + } + } }); /** @@ -251,6 +257,7 @@ var ImageDialog = Widget.extend({ //'change select.image-style': 'preview_image', 'click .existing-attachments [data-src]': 'select_existing', 'click .existing-attachment-remove': 'try_remove', + 'keydown.dismiss.bs.modal': function(){}, }), init: function (parent, media, options) { this._super(); @@ -339,7 +346,7 @@ var ImageDialog = Widget.extend({ return this.media; }, clear: function () { - this.media.className = this.media.className.replace(/(^|\s)(img(\s|$)|img-[^\s]*)/g, ' '); + this.media.className = this.media.className.replace(/(^|\s+)(img(\s|$)|img-(?!circle|rounded|thumbnail)[^\s]*)/g, ' '); }, cancel: function () { this.trigger('cancel'); @@ -609,6 +616,7 @@ var fontIconsDialog = Widget.extend({ $(".font-icons-icon").removeClass("font-icons-selected"); $(event.target).addClass("font-icons-selected"); }, + 'keydown.dismiss.bs.modal': function(){}, }), // extract list of font (like awsome) from the cheatsheet. @@ -662,12 +670,14 @@ var fontIconsDialog = Widget.extend({ var icons = this.icons; var style = this.media.attributes.style ? this.media.attributes.style.value : ''; var classes = (this.media.className||"").split(/\s+/); + var custom_classes = /^fa(-[1-5]x|spin|rotate-(9|18|27)0|flip-(horizont|vertic)al|fw|border)?$/; var non_fa_classes = _.reject(classes, function (cls) { - return self.getFont(cls); + return self.getFont(cls) || custom_classes.test(cls); }); var final_classes = non_fa_classes.concat(this.get_fa_classes()); if (this.media.tagName !== "SPAN") { var media = document.createElement('span'); + $(media).data($(this.media).data()); $(this.media).replaceWith(media); this.media = media; style = style.replace(/\s*width:[^;]+/, ''); @@ -828,7 +838,8 @@ var VideoDialog = Widget.extend({ 'change input#urlvideo': 'change_input', 'keyup input#urlvideo': 'change_input', 'change input#embedvideo': 'change_input', - 'keyup input#embedvideo': 'change_input' + 'keyup input#embedvideo': 'change_input', + 'keydown.dismiss.bs.modal': function(){}, }), init: function (parent, media) { this._super(); @@ -842,7 +853,6 @@ var VideoDialog = Widget.extend({ if ($media.hasClass("media_iframe_video")) { var src = $media.data('src'); this.$("input#urlvideo").val(src); - this.$("#autoplay").attr("checked", src.indexOf('autoplay=1') != -1); this.get_video(); } else { this.add_class = "pull-left"; |
