diff options
| author | Christophe Simonis <chs@odoo.com> | 2016-09-22 15:27:35 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2016-09-22 15:27:35 +0200 |
| commit | f308b09a9ab3f3bf452fdd1ac6c2c86812732110 (patch) | |
| tree | 9506e8e830ce1e6737c1f7c87b451f60bbb2cbff /addons/web_editor/static | |
| parent | 30260bbb0ee683c67cf8ddd0358f40fbd2f5dd0f (diff) | |
| parent | 856476d4418390ca89ef161e31faf61248eeaa1d (diff) | |
[MERGE] forward port branch saas-13 up to 856476d
Diffstat (limited to 'addons/web_editor/static')
| -rw-r--r-- | addons/web_editor/static/lib/summernote/src/js/module/Editor.js | 4 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/rte.js | 2 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/snippets.editor.js | 75 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/snippets.options.js | 225 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/transcoder.js | 6 | ||||
| -rw-r--r-- | addons/web_editor/static/src/js/widgets.js | 35 | ||||
| -rw-r--r-- | addons/web_editor/static/src/less/web_editor.ui.less | 13 | ||||
| -rw-r--r-- | addons/web_editor/static/src/xml/editor.xml | 2 | ||||
| -rw-r--r-- | addons/web_editor/static/src/xml/snippets.xml | 2 |
9 files changed, 291 insertions, 73 deletions
diff --git a/addons/web_editor/static/lib/summernote/src/js/module/Editor.js b/addons/web_editor/static/lib/summernote/src/js/module/Editor.js index a30ee9c18c8..b7ba30bfcd1 100644 --- a/addons/web_editor/static/lib/summernote/src/js/module/Editor.js +++ b/addons/web_editor/static/lib/summernote/src/js/module/Editor.js @@ -616,7 +616,6 @@ define([ var linkUrl = linkInfo.url; var linkText = linkInfo.text; var isNewWindow = linkInfo.isNewWindow; - var className = linkInfo.className || null; // ODOO: addition var rng = linkInfo.range || this.createRange($editable); var isTextChanged = rng.toString() !== linkText; @@ -647,7 +646,8 @@ define([ $.each(anchors, function (idx, anchor) { $(anchor).attr('href', linkUrl); - $(anchor).attr('class', className); // ODOO: addition + $(anchor).attr('class', linkInfo.className || null); // ODOO: addition + $(anchor).css(linkInfo.style || {}); // ODOO: addition if (isNewWindow) { $(anchor).attr('target', '_blank'); } else { diff --git a/addons/web_editor/static/src/js/rte.js b/addons/web_editor/static/src/js/rte.js index 1ed12eb4a73..b0366583aea 100644 --- a/addons/web_editor/static/src/js/rte.js +++ b/addons/web_editor/static/src/js/rte.js @@ -509,7 +509,7 @@ var RTE = Widget.extend({ */ $target.attr('contenteditable', true); _.defer(function () { - $editable.attr('contenteditable', false); + $editable.not($target).attr('contenteditable', false); $target.focus(); }); diff --git a/addons/web_editor/static/src/js/snippets.editor.js b/addons/web_editor/static/src/js/snippets.editor.js index d603210b576..dcfabb6feb4 100644 --- a/addons/web_editor/static/src/js/snippets.editor.js +++ b/addons/web_editor/static/src/js/snippets.editor.js @@ -258,11 +258,7 @@ data.Class = Widget.extend({ $("body").toggleClass("editor_has_snippets", !!number); // select all default text to edit (if snippet default text) - self.$snippets.find('.oe_snippet_body, .oe_snippet_body *') - .contents() - .filter(function () { - return this.nodeType === 3 && this.textContent.match(/\S/); - }).parent().addClass("o_default_snippet_text"); + this.add_default_snippet_text_classes(); $(document).on("click", ".o_default_snippet_text", function (event) { $(event.target).selectContent(); }); @@ -287,6 +283,9 @@ data.Class = Widget.extend({ self.make_snippet_draggable(self.$snippets); this.associate_snippet_names(this.$snippets); + + this.show_blocks(); + this.$el.on("snippet-dropped snippet-removed", this.show_blocks.bind(this)); }, associate_snippet_names: function ($snippets) { @@ -301,6 +300,18 @@ data.Class = Widget.extend({ }); }, + add_default_snippet_text_classes: function ($in) { + if ($in === undefined) { + $in = this.$snippets.find(".oe_snippet_body"); + } + + $in.find("*").addBack() + .contents() + .filter(function () { + return this.nodeType === 3 && this.textContent.match(/\S/); + }).parent().addClass("o_default_snippet_text"); + }, + cover_target: function ($el, $target) { if ($el.data('not-cover_target')) { return; @@ -322,39 +333,22 @@ data.Class = Widget.extend({ show_blocks: function () { var self = this; var cache = {}; - this.$(".o_panel").each(function () { - var catcheck = false; - var $category = $(this); - $category.find(".oe_snippet_body").each(function () { - var $snippet = $(this); - - var check = false; - - for (var k in self.templateOptions) { - var option = self.templateOptions[k]; - if ($snippet.is(option.base_selector)) { - - cache[k] = cache[k] || { - 'drop-near': option['drop-near'] ? option['drop-near'].all() : [], - 'drop-in': option['drop-in'] ? option['drop-in'].all() : [] - }; + this.$snippets.each(function () { + var $snippet = $(this); + var $snippet_body = $snippet.find(".oe_snippet_body"); - if (cache[k]['drop-near'].length || cache[k]['drop-in'].length) { - catcheck = true; - check = true; - break; - } - } - } + var check = false; + _.each(self.templateOptions, function (option, k) { + if (check || !$snippet_body.is(option.base_selector)) return; - if (check) { - $snippet.closest(".oe_snippet").removeClass("disable"); - } else { - $snippet.closest(".oe_snippet").addClass("disable"); - } + cache[k] = cache[k] || { + 'drop-near': option['drop-near'] ? option['drop-near'].all().length : 0, + 'drop-in': option['drop-in'] ? option['drop-in'].all().length : 0 + }; + check = (cache[k]['drop-near'] || cache[k]['drop-in']); }); - $('#oe_snippets .scroll a[data-toggle="tab"][href="#' + $category.attr("id") + '"]').toggle(catcheck); + $snippet.toggleClass("disable", !check); }); }, bind_snippet_click_editor: function () { @@ -900,7 +894,6 @@ data.Editor = Class.extend({ this.$overlay.removeClass("hidden"); $("body").removeClass('move-important'); $clone.remove(); - $(".oe_drop_to_remove").remove(); if (this.dropped) { this.buildingBlock.getParent().rte.historyRecordUndo(this.$target); @@ -1008,10 +1001,12 @@ data.Editor = Class.extend({ }, on_remove: function (event) { - event.preventDefault(); - this.on_blur(); + if (event !== undefined) { + event.preventDefault(); + this.buildingBlock.getParent().rte.historyRecordUndo(this.$target); + } - this.buildingBlock.getParent().rte.historyRecordUndo(this.$target); + this.on_blur(); var index = _.indexOf(this.buildingBlock.snippets, this.$target.get(0)); this.buildingBlock.call_for_all_snippets(this.$target, function (editor, $snippet) { @@ -1044,7 +1039,7 @@ data.Editor = Class.extend({ } if ($parent.children().length === 0 && $parent.text().trim() === "") { _.defer(function () { - $parent.data("snippet-editor").on_remove(event); + $parent.data("snippet-editor").on_remove(); }); } } @@ -1053,6 +1048,8 @@ data.Editor = Class.extend({ $(".note-control-selection").hide(); $('.o_table_handler').remove(); + this.buildingBlock.$el.trigger("snippet-removed"); + return false; }, diff --git a/addons/web_editor/static/src/js/snippets.options.js b/addons/web_editor/static/src/js/snippets.options.js index b4b96beabca..6d4800cd0db 100644 --- a/addons/web_editor/static/src/js/snippets.options.js +++ b/addons/web_editor/static/src/js/snippets.options.js @@ -214,6 +214,231 @@ odoo.define('web_editor.snippets.options', function (require) { /* ----- default options ---- */ + registry.marginAndResize = SnippetOption.extend({ + preventChildPropagation: true, + + start: function () { + var self = this; + this._super(); + + var resize_values = this.getSize(); + if (resize_values.n) this.$overlay.find(".oe_handle.n").removeClass("readonly"); + if (resize_values.s) this.$overlay.find(".oe_handle.s").removeClass("readonly"); + if (resize_values.e) this.$overlay.find(".oe_handle.e").removeClass("readonly"); + if (resize_values.w) this.$overlay.find(".oe_handle.w").removeClass("readonly"); + if (resize_values.size) this.$overlay.find(".oe_handle.size").removeClass("readonly"); + + var $auto_size = this.$overlay.find(".oe_handle.size .auto_size"); + var $fixed_size = this.$overlay.find(".oe_handle.size .size"); + + var auto_sized = isNaN(parseInt(self.$target.prop("style").height)); + $fixed_size.toggleClass("active", !auto_sized); + $auto_size.toggleClass("active", auto_sized); + + $fixed_size.add(this.$overlay.find(".oe_handle:not(.size)")).on('mousedown', function (event) { + event.preventDefault(); + + var $handle = $(this); + + var resize_values = self.getSize(); + var compass = false; + var XY = false; + if ($handle.hasClass('n')) { + compass = 'n'; + XY = 'Y'; + } + else if ($handle.hasClass('s')) { + compass = 's'; + XY = 'Y'; + } + else if ($handle.hasClass('e')) { + compass = 'e'; + XY = 'X'; + } + else if ($handle.hasClass('w')) { + compass = 'w'; + XY = 'X'; + } + else if ($handle.hasClass('size')) { + compass = 'size'; + XY = 'Y'; + } + + var resize = resize_values[compass]; + if (!resize) return; + + + if (compass === 'size') { + var offset = self.$target.offset().top; + if (self.$target.css("background").match(/rgba\(0, 0, 0, 0\)/)) { + self.$target.addClass("resize_editor_busy"); + } + } else { + var xy = event['page'+XY]; + var current = resize[2] || 0; + var margin_dir = {s:'bottom', n: 'top', w: 'left', e: 'right'}[compass]; + var real_margin = parseInt(self.$target.css('margin-'+margin_dir)); + _.each(resize[0], function (val, key) { + if (self.$target.hasClass(val)) { + current = key; + } else if (resize[1][key] === real_margin) { + current = key; + } + }); + var begin = current; + var beginClass = self.$target.attr("class"); + var regClass = new RegExp("\\s*" + resize[0][begin].replace(/[-]*[0-9]+/, '[-]*[0-9]+'), 'g'); + } + + self.buildingBlock.editor_busy = true; + + var cursor = $handle.css("cursor")+'-important'; + var $body = $(document.body); + $body.addClass(cursor); + + var body_mousemove = function (event) { + event.preventDefault(); + if (compass === 'size') { + var dy = event.pageY-offset; + dy = dy - dy%resize; + if (dy <= 0) dy = resize; + self.$target.css("height", dy+"px"); + self.$target.css("overflow", "hidden"); + self.on_resize(compass, null, dy); + self.buildingBlock.cover_target(self.$overlay, self.$target); + return; + } + var dd = event['page'+XY] - xy + resize[1][begin]; + var next = current+1 === resize[1].length ? current : (current+1); + var prev = current ? (current-1) : 0; + + var change = false; + if (dd > (2*resize[1][next] + resize[1][current])/3) { + self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, '')); + self.$target.addClass(resize[0][next]); + current = next; + change = true; + } + if (prev !== current && dd < (2*resize[1][prev] + resize[1][current])/3) { + self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, '')); + self.$target.addClass(resize[0][prev]); + current = prev; + change = true; + } + + if (change) { + self.on_resize(compass, beginClass, current); + self.buildingBlock.cover_target(self.$overlay, self.$target); + } + }; + + var body_mouseup = function () { + $body.unbind('mousemove', body_mousemove); + $body.unbind('mouseup', body_mouseup); + $body.removeClass(cursor); + setTimeout(function () { + self.buildingBlock.editor_busy = false; + if (begin !== current) { + self.buildingBlock.getParent().rte.historyRecordUndo(self.$target, 'resize_' + XY); + } + },0); + self.$target.removeClass("resize_editor_busy"); + + if (compass === "size") { + $fixed_size.addClass("active"); + $auto_size.removeClass("active"); + } + }; + $body.mousemove(body_mousemove); + $body.mouseup(body_mouseup); + }); + $auto_size.on('click', function () { + self.$target.css("height", ""); + self.$target.css("overflow", ""); + self.buildingBlock.getParent().rte.historyRecordUndo(self.$target, 'resize_Y'); + self.buildingBlock.cover_target(self.$overlay, self.$target); + + $fixed_size.removeClass("active"); + $auto_size.addClass("active"); + + return false; + }); + }, + getSize: function () { + this.grid = {}; + return this.grid; + }, + + on_focus : function () { + this._super(); + this.change_cursor(); + }, + + change_cursor : function () { + var _class = this.$target.attr("class") || ""; + + var col = _class.match(/col-md-([0-9-]+)/i); + col = col ? +col[1] : 0; + + var offset = _class.match(/col-md-offset-([0-9-]+)/i); + offset = offset ? +offset[1] : 0; + + var overlay_class = this.$overlay.attr("class").replace(/(^|\s+)block-[^\s]*/gi, ''); + if (col+offset >= 12) overlay_class+= " block-e-right"; + if (col === 1) overlay_class+= " block-w-right block-e-left"; + if (offset === 0) overlay_class+= " block-w-left"; + + var mb = _class.match(/mb([0-9-]+)/i); + mb = mb ? +mb[1] : parseInt(this.$target.css('margin-bottom')); + if (mb >= 128) overlay_class+= " block-s-bottom"; + else if (!mb) overlay_class+= " block-s-top"; + + var mt = _class.match(/mt([0-9-]+)/i); + mt = mt ? +mt[1] : parseInt(this.$target.css('margin-top')); + if (mt >= 128) overlay_class+= " block-n-top"; + else if (!mt) overlay_class+= " block-n-bottom"; + + this.$overlay.attr("class", overlay_class); + }, + + /* on_resize + * called when the box is resizing and the class change, before the cover_target + * @compass: resize direction : 'n', 's', 'e', 'w' + * @beginClass: attributes class at the begin + * @current: curent increment in this.grid + */ + on_resize: function () { + this.change_cursor(); + } + }); + + registry["margin-y"] = registry.marginAndResize.extend({ + preventChildPropagation: true, + + getSize: function () { + this.grid = this._super(); + var grid = [0,4,8,16,32,48,64,92,128]; + this.grid = { + // list of class (Array), grid (Array), default value (INT) + n: [_.map(grid, function (v) {return 'mt'+v;}), grid], + s: [_.map(grid, function (v) {return 'mb'+v;}), grid], + // INT if the user can resize the snippet (resizing per INT px) + size: null + }; + return this.grid; + }, + }); + + registry.resize = registry.marginAndResize.extend({ + preventChildPropagation: true, + + getSize: function () { + this.grid = this._super(); + this.grid.size = 8; + return this.grid; + }, + }); + /** * The colorpicker option is designed to change the background color class of a snippet. This class change the * default background color and text color of the snippet content. diff --git a/addons/web_editor/static/src/js/transcoder.js b/addons/web_editor/static/src/js/transcoder.js index fbdc4b34b87..ddd8ce73533 100644 --- a/addons/web_editor/static/src/js/transcoder.js +++ b/addons/web_editor/static/src/js/transcoder.js @@ -3,12 +3,8 @@ odoo.define('web_editor.transcoder', function (require) { var widget = require('web_editor.widget'); -var cache = {}; var rulesCache = []; var getMatchedCSSRules = function (a) { - if(cache[a.tagName + "." +a.className]) { - return cache[a.tagName + "." +a.className]; - } if (!rulesCache.length) { var sheets = document.styleSheets; for(var i = sheets.length-1; i >= 0 ; i--) { @@ -117,7 +113,7 @@ var getMatchedCSSRules = function (a) { delete style['padding-left']; } - return a.className ? cache[a.tagName + "." +a.className] = style : style; + return style; }; // convert font awsome into image diff --git a/addons/web_editor/static/src/js/widgets.js b/addons/web_editor/static/src/js/widgets.js index a34571a3f54..00a693d40f2 100644 --- a/addons/web_editor/static/src/js/widgets.js +++ b/addons/web_editor/static/src/js/widgets.js @@ -200,21 +200,14 @@ var MediaDialog = Dialog.extend({ $(document.body).trigger("media-saved", [media, self.old_media]); self.trigger("saved", [media, self.old_media]); - setTimeout(function () { - if (!media.parentNode) { - return; - } + + // Update editor bar after image edition (in case the image change to icon or other) + _.defer(function () { + if (!media.parentNode) return; range.createFromNode(media).select(); click_event(media, "mousedown"); - if (!this.only_images) { - setTimeout(function () { - if($(media).parent().data("oe-field") !== "image") { - click_event(media, "click"); - } - click_event(media, "mouseup"); - },0); - } - },0); + click_event(media, "mouseup"); + }); this._super.apply(this, arguments); }, @@ -774,7 +767,9 @@ var fontIconsDialog = Widget.extend({ }); -function createVideoNode(url) { +function createVideoNode(url, options) { + options = options || {}; + // video url patterns(youtube, instagram, vimeo, dailymotion, youku) var ytRegExp = /^(?:(?:https?:)?\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/; var ytMatch = url.match(ytRegExp); @@ -844,6 +839,10 @@ function createVideoNode(url) { }); } + if (options.autoplay) { + $video.attr("src", $video.attr("src") + "?autoplay=1"); + } + $video.attr('frameborder', 0); return $video; @@ -858,6 +857,7 @@ var VideoDialog = Widget.extend({ events : _.extend({}, Dialog.prototype.events, { 'click input#urlvideo ~ button': 'get_video', 'click input#embedvideo ~ button': 'get_embed_video', + 'change input#autoplay': 'get_video', 'change input#urlvideo': 'change_input', 'keyup input#urlvideo': 'change_input', 'change input#embedvideo': 'change_input', @@ -876,6 +876,7 @@ var VideoDialog = Widget.extend({ if ($media.hasClass("media_iframe_video")) { var src = $media.data('src'); this.$("input#urlvideo").val(src); + this.$("input#autoplay").prop("checked", (src || "").indexOf("autoplay") >= 0); this.get_video(); } return this._super.apply(this, arguments); @@ -900,7 +901,7 @@ var VideoDialog = Widget.extend({ }, get_video: function (event) { if (event) event.preventDefault(); - var $video = createVideoNode(this.$("input#urlvideo").val()); + var $video = createVideoNode(this.$("input#urlvideo").val(), {autoplay: this.$("input#autoplay").is(":checked")}); this.$iframe.replaceWith($video); this.$iframe = $video; return false; @@ -1091,7 +1092,9 @@ var LinkDialog = Dialog.extend({ self.data.isNewWindow = new_window; self.data.text = label; self.data.className = classes.replace(/\s+/gi, ' ').replace(/^\s+|\s+$/gi, ''); - + if (classes.replace(/(^|[ ])(btn-default|btn-success|btn-primary|btn-info|btn-warning|btn-danger)([ ]|$)/gi, ' ')) { + self.data.style = {'background-color': '', 'color': ''}; + } self.trigger("save", self.data); }).then(_super); }, diff --git a/addons/web_editor/static/src/less/web_editor.ui.less b/addons/web_editor/static/src/less/web_editor.ui.less index 81910fc0b1e..00b6414bd16 100644 --- a/addons/web_editor/static/src/less/web_editor.ui.less +++ b/addons/web_editor/static/src/less/web_editor.ui.less @@ -1069,23 +1069,20 @@ body.editor_enable { #web_editor_inside_iframe { background-color: @odoo-brand-secondary; - &.editor_enable #wrapwrap { + #wrapwrap { height: 100%; + > main { height: 100%; + #editable_area { position: relative; - overflow: hidden; - min-height: 100%; - margin: 0 auto; - + width: 100%; + height: 100%; background-color: white; } } } - .note-color-palette .colorpicker { - display: none; - } } // Mixins for buttons with alpha bg-color diff --git a/addons/web_editor/static/src/xml/editor.xml b/addons/web_editor/static/src/xml/editor.xml index 138c84da6f0..27213d7fdd8 100644 --- a/addons/web_editor/static/src/xml/editor.xml +++ b/addons/web_editor/static/src/xml/editor.xml @@ -210,7 +210,7 @@ </div> <div class="text-center mt32"> <div class="checkbox"> - <label> + <label title="The feature might not be supported for every video type"> <input id="autoplay" type="checkbox"/>Autoplay</label> </div> </div> diff --git a/addons/web_editor/static/src/xml/snippets.xml b/addons/web_editor/static/src/xml/snippets.xml index 2b9aaf15b32..d9e8c83a495 100644 --- a/addons/web_editor/static/src/xml/snippets.xml +++ b/addons/web_editor/static/src/xml/snippets.xml @@ -60,7 +60,7 @@ <!-- t-field options --> <t t-name="web_editor.many2one.button"> - <div class="dropdown"> + <div class="btn-group"> <a href="#" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" title="Search Contact"><i class="fa fa-search"></i></a> <ul class="dropdown-menu contact_menu" role="menu"> <li><a><input href="#" type="email" placeholder="Search"/></a></li> |
