diff options
Diffstat (limited to 'addons/website/static/src/js/website.snippets.editor.js')
| -rw-r--r-- | addons/website/static/src/js/website.snippets.editor.js | 1667 |
1 files changed, 46 insertions, 1621 deletions
diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index 3be81da11ce..d9e41badd8e 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -1,1066 +1,19 @@ odoo.define('website.snippets.editor', function (require) { 'use strict'; -var ajax = require('web.ajax'); -var Class = require('web.Class'); -var core = require('web.core'); -var Widget = require('web.Widget'); -var editor = require('website.editor'); +var widget = require('web_editor.widget'); +var animation = require('web_editor.snippets.animation'); +var options = require('web_editor.snippets.options'); +var snippet_editor = require('web_editor.snippet.editor'); -var animation = require('website.snippets.animation'); -var website = require('website.website'); - -var dummy = function () {}; - -var options = {}; - -var templateOptions = []; -var globalSelector = { - closest: function () { return $(); }, - all: function () { return $(); }, - is: function () { return false; }, -}; -var selector = []; - -website.add_template_file('/website/static/src/xml/website.snippets.xml'); - -editor.EditorBar.include({ - start: function () { - var self = this; - $(document).on('click', '.o_editable', function (event) { - var $this = $(event.srcElement); - var tag = $this[0] && $this[0].tagName.toLowerCase(); - if (!(tag === 'a' || tag === "button") && !$this.parents("a, button").length) { - self.$('[data-action="edit"]').parent().effect('bounce', {distance: 18, times: 5}, 250); - } - }); - return this._super(); - }, - edit: function () { - var self = this; - animation.stop_animation(); - this.on('rte:ready', this, function () { - var $editable = $(".o_editable"); - window.snippets = this.snippets = new BuildingBlock(this, $editable); - this.snippets.insertAfter(this.$el); - animation.start_animation(true); - $editable.find("*").off('mousedown mouseup click'); - this.snippets.on("snippets:ready", this, function () { - self.trigger("snippets:ready"); - }); - }); - - return this._super.apply(this, arguments); - }, - save: function () { - this.snippets.clean_for_save(); - this._super(); - }, -}); - -/* ----- SNIPPET SELECTOR ---- */ - -$.extend($.expr[':'],{ - o_editable: function(node,i,m){ - while (node) { - if (node.className) { - if (node.className.indexOf('o_not_editable')!==-1 ) { - return false; - } - if (node.className.indexOf('o_editable')!==-1 ) { - return true; - } - } - node = node.parentNode; - } - return false; - }, - hasData: function(node,i,m){ - return !!_.toArray(node.dataset).length; - }, - data: function(node,i,m){ - return $(node).data(m[3]); - } -}); - - -var BuildingBlock = Widget.extend({ - template: 'website.snippets', - activeSnippets: [], - init: function (parent, $editable) { - this.parent = parent; - this.$editable = $editable; - - this._super.apply(this, arguments); - if(!$('#oe_manipulators').length){ - $("<div id='oe_manipulators'></div>").appendTo('body'); - } - this.$active_snipped_id = false; - this.snippets = []; - }, - start: function() { - var self = this; - this.$snippet = $("#oe_snippets"); - - this.$el - .on("mouseenter", function () { self.show(); }) - .on("mouseleave", function (event) { if (event.clientX>0 && event.clientY>0) self.hide(); }); - - $(window).resize(function () { - setTimeout('$(document).click()',0); - }); - - this.fetch_snippet_templates(); - this.bind_snippet_click_editor(); - - $(document).on('click', '.dropdown-submenu a[tabindex]', function (e) { - e.preventDefault(); - }); - - var _isNotBreakable = $.summernote.core.dom.isNotBreakable; - $.summernote.core.dom.isNotBreakable = function (node, sc, so, ec, eo) { - return _isNotBreakable(node, sc, so, ec, eo) || $(node).is('div') || globalSelector.is($(node)); - }; - - $(window).on('resize', function () { - if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) { - self.cover_target(self.$active_snipped_id.data("snippet-editor").$overlay, self.$active_snipped_id); - } - }); - - $(document).on('mousemove', function () { - if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) { - self.$active_snipped_id.data("snippet-editor").$overlay.removeClass('o_keypress'); - } - }); - $(document).on('keydown', function (event) { - if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) { - self.$active_snipped_id.data("snippet-editor").$overlay.addClass('o_keypress'); - } - if ((event.metaKey || (event.ctrlKey && !event.altKey)) && event.shiftKey && event.keyCode >= 48 && event.keyCode <= 57) { - self.$snippet.find('.scroll:first > ul li:eq('+(event.keyCode-49)+') a').trigger("click"); - self.show(); - event.preventDefault(); - } - }); - }, +snippet_editor.Class.include({ _get_snippet_url: function () { return '/website/snippets'; - }, - _add_check_selector : function (selector, no_check) { - var self = this; - selector = selector.split(/\s*,/).join(":not(.o_snippet_not_selectable), ") + ":not(.o_snippet_not_selectable)"; - - if (no_check) { - return { - closest: function ($from, parentNode) { - return $from.closest(selector, parentNode); - }, - all: function ($from) { - return $from ? $from.find(selector) : $(selector); - }, - is: function ($from) { - return $from.is(selector); - } - }; - } else { - selector = selector.split(/\s*,/).join(":o_editable, ") + ":o_editable"; - return { - closest: function ($from, parentNode) { - var parents = self.$editable.get(); - return $from.closest(selector, parentNode).filter(function () { - var node = this; - while (node.parentNode) { - if (parents.indexOf(node)!==-1) { - return true; - } - node = node.parentNode; - } - return false; - }); - }, - all: function ($from) { - return $from ? $from.find(selector) : self.$editable.parent().find(selector); - }, - is: function ($from) { - return $from.is(selector); - } - }; - } - }, - - fetch_snippet_templates: function () { - var self = this; - var url = this._get_snippet_url(); - if (!url || !url.length) { - this.$snippet.detach(); - return; - } - return ajax.jsonRpc(url, 'call', {}).then(function (html) { - self.compute_snippet_templates(html); - self.trigger("snippets:ready"); - }); - }, - compute_snippet_templates: function (html) { - var self = this; - var $html = $(html); - var $left_bar = this.$el.find("#o_left_bar"); - var $ul = $html.siblings("ul"); - var $scroll = $html.siblings("#o_scroll"); - - if (!$scroll.length) { - throw new Error("Wrong snippets xml definition"); - } - - // t-snippet - $html.find('[data-oe-type="snippet"][data-oe-name]').each(function () { - $('<div/>').insertAfter(this).append(this).attr('name', $(this).data('oe-name')); - }); - // end - - var selector = []; - var $styles = $html.find("[data-js], [data-selector]"); - $styles.each(function () { - var $style = $(this); - var no_check = $style.data('no-check'); - var option_id = $style.data('js'); - var option = { - 'option' : option_id, - 'base_selector': $style.data('selector'), - 'selector': self._add_check_selector($style.data('selector'), no_check), - '$el': $style, - 'drop-near': $style.data('drop-near') && self._add_check_selector($style.data('drop-near'), no_check), - 'drop-in': $style.data('drop-in') && self._add_check_selector($style.data('drop-in'), no_check), - 'data': $style.data() - }; - templateOptions.push(option); - selector.push(option.selector); - }); - $styles.addClass("hidden"); - _.extend(globalSelector, { - closest: function ($from) { - var $temp; - var $target; - var len = selector.length; - for (var i = 0; i<len; i++) { - $temp = selector[i].closest($from, $target && $target[0]); - if (!$target || $temp.length) { - $target = $temp; - } - } - return $target; - }, - all: function ($from) { - var $target; - var len = selector.length; - for (var i = 0; i<len; i++) { - if (!$target) $target = selector[i].all($from); - else $target = $target.add(selector[i].all($from)); - } - return $target; - }, - is: function ($from) { - var len = selector.length; - for (var i = 0; i<len; i++) { - if (selector[i].is($from)) { - return true; - } - } - return false; - }, - }); - - // oe_snippet_body - self.$snippets = $scroll.find(".o_panel_body").children() - .addClass("oe_snippet") - .each(function () { - if (!$('.oe_snippet_thumbnail', this).size()) { - var $div = $( - '<div class="oe_snippet_thumbnail">'+ - '<div class="oe_snippet_thumbnail_img"/>'+ - '<span class="oe_snippet_thumbnail_title"></span>'+ - '</div>'); - $div.find('span').text($(this).attr("name")); - $(this).prepend($div); - - // from t-snippet - var thumbnail = $("[data-oe-thumbnail]", this).data("oe-thumbnail"); - if (thumbnail) { - $div.find('.oe_snippet_thumbnail_img').css('background-image', 'url(' + thumbnail + ')'); - } - // end - } - if (!$(this).data("selector")) { - $("> *:not(.oe_snippet_thumbnail)", this).addClass('oe_snippet_body'); - } - }); - - // 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"); - $(document).on("mouseup", ".o_default_snippet_text", function (event) { - $(event.target).selectContent(); - }); - $(document).on("keyup", function () { - var r = $.summernote.core.range.create(); - $(r && r.sc).closest(".o_default_snippet_text").removeClass("o_default_snippet_text"); - }); - // end - - // clean t-oe - $html.find('[data-oe-model], [data-oe-type]').each(function () { - for (var k=0; k<this.attributes.length; k++) { - if (this.attributes[k].name.indexOf('data-oe-') === 0) { - $(this).removeAttr(this.attributes[k].name); - k--; - } - } - }); - // end - - $html.find('.o_not_editable').attr("contentEditable", false); - - $left_bar.append($html); - - // animate for list of snippet blocks - $left_bar.on('click', '.scroll-link', function (event) { - event.preventDefault(); - var targetOffset = $($(this).attr("href")).position().top - $ul.outerHeight() + $scroll[0].scrollTop; - $scroll.animate({'scrollTop': targetOffset}, 750); - }); - $scroll.on('scroll', function () { - var middle = $scroll.height()/4; - var $li = $ul.find("a").parent().removeClass('active'); - var last; - for (var k=0; k<$li.length; k++) { - var li = $($li[k]); - if (!li.data('target')) { - li.data('target', $($("a", li).attr("href"))); - } - if (li.data('target').position().top > middle) { - break; - } - last = $li[k]; - } - $(last).addClass("active"); - }); - // end - - // display scrollbar - $(window).on('resize', function () { - $scroll.css("overflow", ""); - var height = $left_bar.height() - $ul.outerHeight(); - $scroll.css("height", height); - var $last = $scroll.children(":visible").last().children(".o_panel_body"); - $last.css({'min-height': (height-$last.prev().outerHeight())+'px'}); - if ($scroll[0].scrollHeight + $ul[0].scrollHeight > document.body.clientHeight) { - $scroll.css("overflow", "auto").css("width", "226px"); - } else { - $scroll.css("width", ""); - } - }).trigger('resize'); - // end - - self.make_snippet_draggable(self.$snippets); - }, - - cover_target: function ($el, $target){ - if($el.data('not-cover_target')) return; - var pos = $target.offset(); - var mt = parseInt($target.css("margin-top") || 0); - var mb = parseInt($target.css("margin-bottom") || 0); - var width = $target.outerWidth(); - var bigger = pos.left+width > $("body").outerWidth()-8; - $el.css({ - 'width': width, - 'top': pos.top - mt - 5, - 'left': pos.left-1 - }); - $el.find(".oe_handle.e,.oe_handle.w").css({'height': $target.outerHeight() + mt + mb+1}); - if (bigger) { - $el.find(".oe_handle.e").css({right: 0, margin: 0}) - .find("div").css({right: 0, left: 'auto'}); - } else { - $el.find(".oe_handle.e").css({right: "", margin: ""}) - .find("div").css({right: "", left: ""}); - } - $el.find(".oe_handle.s").css({'top': $target.outerHeight() + mt + mb}); - $el.find(".oe_handle.size").css({'top': $target.outerHeight() + mt}); - $el.find(".oe_handle.s,.oe_handle.n").css({'width': width-2}); - }, - - show_blocks: function () { - var cache = {}; - this.$snippet.find(".tab-pane").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 templateOptions) { - var option = 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() : [] - }; - - if (cache[k]['drop-near'].length || cache[k]['drop-in'].length) { - catcheck = true; - check = true; - break; - } - } - } - - if (check) { - $snippet.closest(".oe_snippet").removeClass("disable"); - } else { - $snippet.closest(".oe_snippet").addClass("disable"); - } - }); - - $('#oe_snippets .scroll a[data-toggle="tab"][href="#' + $category.attr("id") + '"]').toggle(catcheck); - }); - }, - show: function () { - this.make_active(false); - this.$el.addClass("o_open"); - this.show_blocks(); - }, - hide: function () { - this.$el.removeClass("o_open"); - }, - bind_snippet_click_editor: function () { - var self = this; - var snipped_event_flag; - $(document).on('click', '*', function (event) { - var srcElement = event.srcElement || (event.originalEvent && (event.originalEvent.originalTarget || event.originalEvent.target) || event.target); - if (self.editor_busy || snipped_event_flag===srcElement || !srcElement) { - return; - } - snipped_event_flag = srcElement; - - setTimeout(function () {snipped_event_flag = false;}, 0); - var $target = $(srcElement); - - if ($target.closest(".oe_overlay, .note-popover").length) { - return; - } - - if (!globalSelector.is($target)) { - $target = globalSelector.closest($target); - } - - if (self.$active_snipped_id && self.$active_snipped_id.is($target)) { - return; - } - self.make_active($target); - }); - }, - snippet_blur: function ($snippet) { - if ($snippet) { - if ($snippet.data("snippet-editor")) { - $snippet.data("snippet-editor").on_blur(); - } - } - }, - snippet_focus: function ($snippet) { - if ($snippet) { - if ($snippet.data("snippet-editor")) { - $snippet.data("snippet-editor").on_focus(); - } - } - }, - clean_for_save: function () { - var self = this; - var template = templateOptions; - for (var k in template) { - var Option = options[template[k]['option']]; - if (Option && Option.prototype.clean_for_save !== dummy) { - template[k].selector.all().each(function () { - new Option(self, null, $(this), k).clean_for_save(); - }); - } - } - this.$editable.find("*[contentEditable], *[attributeEditable]") - .removeAttr('contentEditable') - .removeProp('contentEditable') - .removeAttr('attributeEditable') - .removeProp('attributeEditable'); - }, - make_active: function ($snippet) { - if ($snippet && this.$active_snipped_id && this.$active_snipped_id.get(0) === $snippet.get(0)) { - return; - } - if (this.$active_snipped_id) { - this.snippet_blur(this.$active_snipped_id); - this.$active_snipped_id = false; - } - if ($snippet && $snippet.length) { - if(_.indexOf(this.snippets, $snippet.get(0)) === -1) { - this.snippets.push($snippet.get(0)); - } - this.$active_snipped_id = $snippet; - this.create_overlay(this.$active_snipped_id); - this.snippet_focus($snippet); - } - this.$snippet.trigger('snippet-activated', $snippet); - if ($snippet) { - $snippet.trigger('snippet-activated', $snippet); - } - }, - create_overlay: function ($snippet) { - if (typeof $snippet.data("snippet-editor") === 'undefined') { - var $targets = this.activate_overlay_zones($snippet); - if (!$targets.length) return; - $snippet.data("snippet-editor", new SnippetEditor(this, $snippet)); - } - this.cover_target($snippet.data('overlay'), $snippet); - }, - - // activate drag and drop for the snippets in the snippet toolbar - make_snippet_draggable: function($snippets){ - var self = this; - var $tumb = $snippets.find(".oe_snippet_thumbnail_img:first"); - var left = $tumb.outerWidth()/2; - var top = $tumb.outerHeight()/2; - var $toInsert, dropped, $snippet; - - $snippets.draggable({ - greedy: true, - helper: 'clone', - zIndex: '1000', - appendTo: 'body', - cursor: "move", - handle: ".oe_snippet_thumbnail", - cursorAt: { - 'left': left, - 'top': top - }, - start: function(){ - self.hide(); - dropped = false; - // snippet_selectors => to get drop-near, drop-in - $snippet = $(this); - var $base_body = $snippet.find('.oe_snippet_body'); - var $selector_siblings = $(); - var $selector_children = $(); - var temp = templateOptions; - for (var k in temp) { - if ($base_body.is(temp[k].base_selector)) { - if (temp[k]['drop-near']) { - if (!$selector_siblings) $selector_siblings = temp[k]['drop-near'].all(); - else $selector_siblings = $selector_siblings.add(temp[k]['drop-near'].all()); - } - if (temp[k]['drop-in']) { - if (!$selector_children) $selector_children = temp[k]['drop-in'].all(); - else $selector_children = $selector_children.add(temp[k]['drop-in'].all()); - } - } - } - - $toInsert = $base_body.clone(); - - if (!$selector_siblings.length && !$selector_children.length) { - console.debug($snippet.find(".oe_snippet_thumbnail_title").text() + " have not insert action: data-drop-near or data-drop-in"); - return; - } - - self.activate_insertion_zones($selector_siblings, $selector_children); - - $('.oe_drop_zone').droppable({ - over: function(){ - dropped = true; - $(this).first().after($toInsert); - }, - out: function(){ - var prev = $toInsert.prev(); - if(this === prev[0]){ - dropped = false; - $toInsert.detach(); - } - } - }); - }, - stop: function(ev, ui){ - $toInsert.removeClass('oe_snippet_body'); - - if (! dropped && self.$editable.find('.oe_drop_zone') && ui.position.top > 3) { - var el = self.$editable.find('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first(); - if (el.length) { - el.after($toInsert); - dropped = true; - } - } - - self.$editable.find('.oe_drop_zone').droppable('destroy').remove(); - - if (dropped) { - - var prev = $toInsert.first()[0].previousSibling; - var next = $toInsert.last()[0].nextSibling; - var rte = self.parent.rte; - - if (prev) { - $toInsert.detach(); - rte.historyRecordUndo($(prev)); - $toInsert.insertAfter(prev); - } else if (next) { - $toInsert.detach(); - rte.historyRecordUndo($(next)); - $toInsert.insertBefore(next); - } else { - var $parent = $toInsert.parent(); - $toInsert.detach(); - rte.historyRecordUndo($parent); - $parent.prepend($toInsert); - } - - var $target = false; - $target = $toInsert; - - setTimeout(function () { - self.$snippet.trigger('snippet-dropped', $target); - - animation.start_animation(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 templateOptions) { - 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(); - } - }); - } - $target.closest(".o_editable").trigger("content_changed"); - // end - - self.make_active($target); - },0); - } else { - $toInsert.remove(); - } - }, - }); - }, - - // return the original snippet in the editor bar from a snippet id (string) - get_snippet_from_id: function(id){ - return $('.oe_snippet').filter(function(){ - return $(this).data('option') === id; - }).first(); - }, - - // Create element insertion drop zones. two css selectors can be provided - // selector.children -> will insert drop zones as direct child of the selected elements - // in case the selected elements have children themselves, dropzones will be interleaved - // with them. - // selector.siblings -> will insert drop zones after and before selected elements - activate_insertion_zones: function($selector_siblings, $selector_children){ - var self = this; - var zone_template = $("<div class='oe_drop_zone oe_insert'></div>"); - - if ($selector_children) { - $selector_children.each(function (){ - var $zone = $(this); - var css = window.getComputedStyle(this); - var float = css.float || css.cssFloat; - var $drop = zone_template.clone(); - - $zone.append($drop); - var node = $drop[0].previousSibling; - var test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR")); - if (test) { - $drop.addClass("oe_vertical oe_vertical_text").css({ - 'height': parseInt(window.getComputedStyle($zone[0]).lineHeight), - 'float': 'none', - 'display': 'inline-block' - }); - } else if (float === "left" || float === "right") { - $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.children().last().outerHeight()), 30)); - } - - $drop = $drop.clone(); - - $zone.prepend($drop); - node = $drop[0].nextSibling; - test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR")); - if (test) { - $drop.addClass("oe_vertical oe_vertical_text").css({ - 'height': parseInt(window.getComputedStyle($zone[0]).lineHeight), - 'float': 'none', - 'display': 'inline-block' - }); - } else if (float === "left" || float === "right") { - $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.children().first().outerHeight()), 30)); - } - if (test) { - $drop.css({'float': 'none', 'display': 'inline-block'}); - } - }); - - // add children near drop zone - $selector_siblings = $(_.uniq(($selector_siblings || $()).add($selector_children.children()).get())); - } - - if ($selector_siblings) { - $selector_siblings.filter(':not(.oe_drop_zone):not(.oe_drop_clone)').each(function (){ - var $zone = $(this); - var $drop; - var css = window.getComputedStyle(this); - var float = css.float || css.cssFloat; - - if($zone.prev('.oe_drop_zone:visible').length === 0){ - $drop = zone_template.clone(); - if (float === "left" || float === "right") { - $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.prev().outerHeight() || Infinity), 30)); - } - $zone.before($drop); - } - if($zone.next('.oe_drop_zone:visible').length === 0){ - $drop = zone_template.clone(); - if (float === "left" || float === "right") { - $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.next().outerHeight() || Infinity), 30)); - } - $zone.after($drop); - } - }); - } - - var count; - do { - count = 0; - $zones = self.$editable.find('.oe_drop_zone > .oe_drop_zone').remove(); // no recursive zones - count += $zones.length; - $zones.remove(); - } while (count > 0); - - // Cleaning consecutive zone and up zones placed between floating or inline elements. We do not like these kind of zones. - var $zones = self.$editable.find('.oe_drop_zone:not(.oe_vertical)'); - $zones.each(function (){ - var zone = $(this); - var prev = zone.prev(); - var next = zone.next(); - // remove consecutive zone - if (prev.is('.oe_drop_zone') || next.is('.oe_drop_zone')) { - zone.remove(); - return; - } - var float_prev = prev.css('float') || 'none'; - var float_next = next.css('float') || 'none'; - var disp_prev = prev.css('display') || null; - var disp_next = next.css('display') || null; - if( (float_prev === 'left' || float_prev === 'right') - && (float_next === 'left' || float_next === 'right') ){ - zone.remove(); - }else if( !( disp_prev === null - || disp_next === null - || disp_prev === 'block' - || disp_next === 'block' )){ - zone.remove(); - } - }); - }, - - // generate drop zones covering the elements selected by the selector - // we generate overlay drop zones only to get an idea of where the snippet are, the drop - activate_overlay_zones: function($targets){ - var self = this; - - function is_visible($el){ - return $el.css('display') != 'none' - && $el.css('opacity') != '0' - && $el.css('visibility') != 'hidden'; - } - - // filter out invisible elements - $targets = $targets.filter(function(){ return is_visible($(this)); }); - - // filter out elements with invisible parents - $targets = $targets.filter(function(){ - var parents = $(this).parents().filter(function(){ return !is_visible($(this)); }); - return parents.length === 0; - }); - - $targets.each(function () { - var $target = $(this); - if (!$target.data('overlay')) { - var $zone = $(core.qweb.render('website.snippet_overlay')); - - // fix for pointer-events: none with ie9 - if (document.body && document.body.addEventListener) { - $zone.on("click mousedown mousedown", function passThrough(event) { - event.preventDefault(); - $target.each(function() { - // check if clicked point (taken from event) is inside element - event.srcElement = this; - $(this).trigger(event.type); - }); - return false; - }); - } - - $zone.appendTo('#oe_manipulators'); - $zone.data('target',$target); - $target.data('overlay',$zone); - - var timer; - $target.closest('.o_editable').on("content_changed", function () { - if ($target.data('overlay') && $target.data('overlay').hasClass("oe_active")) { - clearTimeout(timer); - timer = setTimeout(function () { - self.cover_target($target.data('overlay'), $target); - },50); - } - }); - - var resize = function () { - if ($zone.parent().length) { - self.cover_target($zone, $target); - } else { - $('body').off("resize", resize); - } - }; - $('body').on("resize", resize); - } - self.cover_target($target.data('overlay'), $target); - }); - return $targets; } }); - -var Option = Class.extend({ - // initialisation (don't overwrite) - init: function (BuildingBlock, editor, $target, option_id) { - this.BuildingBlock = BuildingBlock; - this.editor = editor; - this.$target = $target; - var option = templateOptions[option_id]; - var styles = this.$target.data("snippet-option-ids") || {}; - styles[option_id] = this; - this.$target.data("snippet-option-ids", styles); - this.$overlay = this.$target.data('overlay') || $('<div>'); - this.option= option_id; - this.$el = option.$el.find(">li").clone(); - this.data = option.$el.data(); - }, - - // helper for this.$target.find - $: function (selector) { - return this.$target(selector); - }, - - _bind_li_menu: function () { - this.$el.filter("li:hasData").find('a:first') - .off('mouseenter click') - .on('mouseenter click', _.bind(this._mouse, this)); - - this.$el - .off('mouseenter click', "li:hasData a") - .on('mouseenter click', "li:hasData a", _.bind(this._mouse, this)); - - this.$el.closest("ul").add(this.$el) - .off('mouseleave') - .on('mouseleave', _.bind(this.reset, this)); - - this.$el - .off('mouseleave', "ul") - .on('mouseleave', "ul", _.bind(this.reset, this)); - - this.reset_methods = []; - }, - - /** - * this method handles mouse:over and mouse:leave on the snippet editor menu - */ - _time_mouseleave: null, - _mouse: function (event) { - var $next = $(event.currentTarget).parent(); - - // triggers preview or apply methods if a menu item has been clicked - this.select(event.type === "click" ? "click" : "over", $next); - if (event.type === 'click') { - this.set_active(); - this.$target.trigger("snippet-option-change", [this]); - } else { - this.$target.trigger("snippet-option-preview", [this]); - } - }, - /* - * select and set item active or not (add highlight item and his parents) - * called before start - */ - set_active: function () { - var classes = _.uniq((this.$target.attr("class") || '').split(/\s+/)); - this.$el.find('[data-toggle_class], [data-select_class]') - .add(this.$el) - .filter('[data-toggle_class], [data-select_class]') - .removeClass("active") - .filter('[data-toggle_class="' + classes.join('"], [data-toggle_class="') + '"] ,'+ - '[data-select_class="' + classes.join('"], [data-select_class="') + '"]') - .addClass("active"); - }, - - start: function () { - this.set_active(); - this.$target.on('snippet-option-reset', _.bind(this.set_active, this)); - this._bind_li_menu(); - }, - - on_focus : function () { - this._bind_li_menu(); - }, - - on_blur : function () { - }, - - on_clone: function () { - }, - - on_move: function () { - }, - - on_remove: function () { - }, - - drop_and_build_snippet: function () { - }, - - reset: function () { - var self = this; - var lis = self.$el.add(self.$el.find('li')).filter('.active').get(); - lis.reverse(); - _.each(lis, function (li) { - var $li = $(li); - for (var k in self.reset_methods) { - var method = self.reset_methods[k]; - if ($li.is('[data-'+method+']') || $li.closest('[data-'+method+']').size()) { - delete self.reset_methods[k]; - } - } - self.select("reset", $li); - }); - - for (var k in self.reset_methods) { - var method = self.reset_methods[k]; - if (method) { - self[method]("reset", null); - } - } - self.reset_methods = []; - self.$target.trigger("snippet-option-reset", [this]); - }, - - // call data-method args as method (data-only can be used) - select: function (type, $li) { - var self = this; - var $methods = []; - var el = $li[0]; - - if ($li.data('only') && type !== $li.data('only')) { - return; - } - - if (type==="click") { - this.reset(); - this.BuildingBlock.parent.rte.historyRecordUndo(this.$target); - } - - function filter (k) { return k !== 'oeId' && k !== 'oeModel' && k !== 'oeField' && k !== 'oeXpath' && k !== 'oeSourceId' && k !== 'only';} - function hasData(el) { - for (var k in el.dataset) { - if (filter (k)) { - return true; - } - } - return false; - } - function method(el) { - var data = {}; - for (var k in el.dataset) { - if (filter (k)) { - data[k] = el.dataset[k]; - } - } - return data; - } - - while (el && this.$el.is(el) || _.some(this.$el.map(function () {return $.contains(this, el);}).get()) ) { - if (hasData(el)) { - $methods.push(el); - } - el = el.parentNode; - } - - $methods.reverse(); - - _.each($methods, function (el) { - var $el = $(el); - var methods = method(el); - - for (var k in methods) { - if (self[k]) { - if (type !== "reset" && self.reset_methods.indexOf(k) === -1) { - self.reset_methods.push(k); - } - self[k](type, methods[k], $el); - } else { - console.error("'"+self.option+"' snippet have not method '"+k+"'"); - } - } - }); - }, - - // default method for snippet - toggle_class: function (type, value) { - var $lis = this.$el.find('[data-toggle_class]').add(this.$el).filter('[data-toggle_class]'); - - function map ($lis) { - return $lis.map(function () {return $(this).data("toggle_class");}).get().join(" "); - } - var classes = map($lis); - var active_classes = map($lis.filter('.active, :has(.active)')); - - this.$target.removeClass(classes); - this.$target.addClass(active_classes); - - if (type !== 'reset') { - this.$target.toggleClass(value); - } - }, - select_class: function (type, value) { - var $lis = this.$el.find('[data-select_class]').add(this.$el).filter('[data-select_class]'); - - var classes = $lis.map(function () {return $(this).data('select_class');}).get(); - - this.$target.removeClass(classes.join(" ")); - if(value) this.$target.addClass(value); - }, - eval: function (type, value, $li) { - var fn = new Function("node", "type", "value", "$li", value); - fn.call(this, this, type, value, $li); - }, - - clean_for_save: dummy -}); - - var preventParentEmpty = { hide_remove_button: function() { this.$overlay.find('.oe_snippet_remove, .oe_snippet_move').toggleClass("hidden", !this.$target.siblings().length); @@ -1080,119 +33,7 @@ var preventParentEmpty = { }; -options.background = Option.extend({ - start: function ($change_target) { - this.$bg = $change_target || this.$target; - this._super(); - var src = this.$bg.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, ""); - if (this.$bg.hasClass('oe_custom_bg')) { - this.$el.find('li[data-choose_image]').data("background", src).attr("data-background", src); - } - }, - background: function(type, value) { - 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"); - } else { - this.$bg.css("background-image", ""); - this.$bg.removeClass("oe_img_bg").removeClass("oe_custom_bg"); - } - }, - choose_image: function(type, value, $li) { - if(type !== "click") return; - - var self = this; - var $image = $('<img class="hidden"/>'); - $image.attr("src", value); - $image.appendTo(self.$bg); - - var _editor = new editor.MediaDialog(null, $image[0]); - _editor.appendTo(document.body); - _editor.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden'); - - _editor.on('saved', self, function () { - var value = $image.attr("src"); - $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.set_active(); - }); - _editor.on('cancel', self, function () { - $image.remove(); - }); - }, - set_active: function () { - var src = this.$bg.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, ""); - this._super(); - - this.$el.find('li[data-background]:not([data-background=""])') - .removeClass("active") - .each(function () { - var background = $(this).data("background") || $(this).attr("data-background"); - if ((src.length && background.length && src.indexOf(background) !== -1) || (!src.length && !background.length)) { - $(this).addClass("active"); - } - }); - - if (!this.$el.find('li[data-background].active').size()) { - this.$el.find('li[data-background=""]:not([data-choose_image])').addClass("active"); - } else { - this.$el.find('li[data-background=""]:not([data-choose_image])').removeClass("active"); - } - } -}); - -options.colorpicker = Option.extend({ - start: function () { - var self = this; - var res = this._super(); - - if (!this.$el.find('.colorpicker').length) { - this.$el.find('li').append( core.qweb.render('website.colorpicker') ); - } - - if (this.$el.data('area')) { - this.$target = this.$target.find(this.$el.data('area')); - this.$el.removeData('area').removeAttr('area'); - } - - var classes = []; - this.$el.find(".colorpicker button").map(function () { - var $color = $(this); - var color = $color.attr("class"); - if (self.$target.hasClass(color)) { - self.color = color; - $color.parent().addClass("selected"); - } - classes.push(color); - }); - this.classes = classes.join(" "); - - this.bind_events(); - return res; - }, - bind_events: function () { - var self = this; - var $td = this.$el.find(".colorpicker td"); - var $colors = this.$el.find(".colorpicker button"); - $colors - .mouseenter(function () { - self.$target.removeClass(self.classes).addClass($(this).attr("class")); - }) - .mouseleave(function () { - self.$target.removeClass(self.classes) - .addClass($td.filter(".selected").children().attr("class")); - }) - .click(function () { - $td.removeClass("selected"); - $(this).parent().addClass("selected"); - }); - } -}); - -options.slider = Option.extend({ +options.registry.slider = options.Class.extend({ drop_and_build_snippet: function() { this.id = "myCarousel" + new Date().getTime(); this.$target.attr("id", this.id); @@ -1201,7 +42,7 @@ options.slider = Option.extend({ this.rebind_event(); }, on_clone: function ($clone) { - this.id = "myCarousel" + new Date().getTime(); + var id = "myCarousel" + new Date().getTime(); $clone.attr("id", id); $clone.find("[data-slide]").attr("href", "#" + id); $clone.find("[data-slide-to]").attr("data-target", "#" + id); @@ -1220,6 +61,7 @@ options.slider = Option.extend({ .first().addClass("active"); }, start : function () { + var self = this; this._super(); this.$target.carousel({interval: false}); this.id = this.$target.attr("id"); @@ -1228,7 +70,7 @@ options.slider = Option.extend({ this.$target.carousel('pause'); this.rebind_event(); }, - add_slide: function (type) { + add_slide: function (type, value) { if(type !== "click") return; var self = this; @@ -1239,7 +81,7 @@ options.slider = Option.extend({ this.$indicators.append('<li data-target="#' + this.id + '" data-slide-to="' + cycle + '"></li>'); // clone the best candidate from template to use new features - var $snippets = this.BuildingBlock.$snippets.find('.oe_snippet_body.carousel'); + var $snippets = this.buildingBlock.$snippets.find('.oe_snippet_body.carousel'); var point = 0; var selection; var className = _.compact(this.$target.attr("class").split(" ")); @@ -1260,13 +102,14 @@ options.slider = Option.extend({ },0); return $clone; }, - remove_slide: function (type) { + remove_slide: function (type, value) { if(type !== "click") return; if (this.remove_process) { return; } var self = this; + var new_index = 0; var cycle = this.$inner.find('.item').length - 1; var index = this.$inner.find('.item.active').index(); @@ -1299,7 +142,7 @@ options.slider = Option.extend({ }, }); -options.carousel = options.slider.extend({ +options.registry.carousel = options.registry.slider.extend({ getSize: function () { this.grid = this._super(); this.grid.size = 8; @@ -1317,6 +160,11 @@ options.carousel = options.slider.extend({ var self = this; this._super(); + // set background and prepare to clean for save + var add_class = function (c){ + if (c) self._class = (self._class || "").replace(new RegExp("[ ]+" + c.replace(" ", "|[ ]+")), '') + ' ' + c; + return self._class || ""; + }; this.$target.on('slid.bs.carousel', function () { if(self.editor && self.editor.styles.background) { self.editor.styles.background.$bg = self.$target.find(".item.active"); @@ -1356,7 +204,7 @@ options.carousel = options.slider.extend({ }, }); -options.marginAndResize = Option.extend({ +options.registry.marginAndResize = options.Class.extend({ start: function () { var self = this; this._super(); @@ -1419,7 +267,7 @@ options.marginAndResize = Option.extend({ var regClass = new RegExp("\\s*" + resize[0][begin].replace(/[-]*[0-9]+/, '[-]*[0-9]+'), 'g'); } - self.BuildingBlock.editor_busy = true; + self.buildingBlock.editor_busy = true; var cursor = $handle.css("cursor")+'-important'; var $body = $(document.body); @@ -1434,7 +282,7 @@ options.marginAndResize = Option.extend({ 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); + self.buildingBlock.cover_target(self.$overlay, self.$target); return; } var dd = event['page'+XY] - xy + resize[1][begin]; @@ -1457,7 +305,7 @@ options.marginAndResize = Option.extend({ if (change) { self.on_resize(compass, beginClass, current); - self.BuildingBlock.cover_target(self.$overlay, self.$target); + self.buildingBlock.cover_target(self.$overlay, self.$target); } }; @@ -1466,19 +314,19 @@ options.marginAndResize = Option.extend({ $body.unbind('mouseup', body_mouseup); $body.removeClass(cursor); setTimeout(function () { - self.BuildingBlock.editor_busy = false; + self.buildingBlock.editor_busy = false; + self.$target.closest(".o_editable").trigger("content_changed"); },0); self.$target.removeClass("resize_editor_busy"); - self.$target.closest(".o_editable").trigger("content_changed"); }; $body.mousemove(body_mousemove); $body.mouseup(body_mouseup); }); - this.$overlay.find(".oe_handle.size .auto_size").on('click', function (){ + this.$overlay.find(".oe_handle.size .auto_size").on('click', function (event){ self.$target.css("height", ""); self.$target.css("overflow", ""); - self.BuildingBlock.cover_target(self.$overlay, self.$target); - self.$target.closest(".o_editable").trigger("content_changed"); + self.buildingBlock.cover_target(self.$overlay, self.$target); + self.$target.closest(".o_editable").trigger("content_changed"); return false; }); }, @@ -1518,7 +366,7 @@ options.marginAndResize = Option.extend({ 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' @@ -1530,7 +378,7 @@ options.marginAndResize = Option.extend({ } }); -options["margin-y"] = options.marginAndResize.extend({ +options.registry["margin-y"] = options.registry.marginAndResize.extend({ getSize: function () { this.grid = this._super(); var grid = [0,4,8,16,32,48,64,92,128]; @@ -1545,7 +393,7 @@ options["margin-y"] = options.marginAndResize.extend({ }, }); -options["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend({ +options.registry["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend({ getSize: function () { this.grid = this._super(); var width = this.$target.parents(".row:first").first().outerWidth(); @@ -1553,7 +401,7 @@ options["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend( var grid = [1,2,3,4,5,6,7,8,9,10,11,12]; this.grid.e = [_.map(grid, function (v) {return 'col-md-'+v;}), _.map(grid, function (v) {return width/12*v;})]; - grid = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11]; + var grid = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11]; this.grid.w = [_.map(grid, function (v) {return 'col-md-offset-'+v;}), _.map(grid, function (v) {return width/12*v;}), 12]; return this.grid; @@ -1616,7 +464,7 @@ options["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend( }, }); -options.resize = options.marginAndResize.extend({ +options.registry.resize = options.registry.marginAndResize.extend({ getSize: function () { this.grid = this._super(); this.grid.size = 8; @@ -1624,7 +472,7 @@ options.resize = options.marginAndResize.extend({ }, }); -options.parallax = Option.extend({ +options.registry.parallax = options.Class.extend({ getSize: function () { this.grid = this._super(); this.grid.size = 8; @@ -1654,6 +502,7 @@ options.parallax = Option.extend({ this.$target.data("snippet-view").set_values(); }, set_active: function () { + var value = this.$target.attr('data-scroll-background-ratio') || 0; this.$el.find('[data-scroll]').removeClass("active") .filter('[data-scroll="' + (this.$target.attr('data-scroll-background-ratio') || 0) + '"]').addClass("active"); }, @@ -1665,7 +514,7 @@ options.parallax = Option.extend({ } }); -options.transform = Option.extend({ +options.registry.transform = options.Class.extend({ start: function () { var self = this; this._super(); @@ -1703,12 +552,12 @@ options.transform = Option.extend({ } }); }, - style: function (type) { + style: function (type, value) { if (type !== 'click') return; var settings = this.$target.data("transfo").settings; this.$target.transfo({ 'hide': (settings.hide = !settings.hide) }); }, - clear_style: function (type) { + clear_style: function (type, value) { if (type !== 'click') return; this.$target.removeClass("fa-spin").attr("style", ""); this.resetTransfo(); @@ -1775,42 +624,16 @@ options.transform = Option.extend({ } }); -options.media = Option.extend({ +options.registry.ul = options.Class.extend({ start: function () { - this._super(); - animation.start_animation(true, this.$target); - }, - edition: function (type) { - if(type !== "click") return; var self = this; - var dialog = new editor.MediaDialog(this.$target.closest('.o_editable'), this.$target[0]); - dialog.appendTo(document.body); - dialog.on('saved', this, function (item) { - self.editor.on_blur(); - self.BuildingBlock.make_active(false); - if (self.$target.parent().data("oe-field") !== "image") { - setTimeout(function () { - self.BuildingBlock.make_active($(item)); - },0); - } - }); - }, - on_focus : function () { - var self = this; - var $parent = this.$target.parent(); - - if ($parent.data("oe-field") === "image" && $parent.hasClass('o_editable')) { - this.$overlay.addClass("hidden"); - self.edition('click', null); - self.BuildingBlock.make_active(false); - } - } -}); - -options.ul = Option.extend({ - start: function () { this._super(); this.$target.data("snippet-view", new animation.registry.ul(this.$target, true)); + this.$target.on('mouseup', '.o_ul_toggle_self, .o_ul_toggle_next', function () { + setTimeout(function () { + self.buildingBlock.cover_target(self.$overlay, self.$target); + },0); + }); }, reset_ul: function () { this.$target.find('.o_ul_toggle_self, .o_ul_toggle_next').remove(); @@ -1851,12 +674,12 @@ options.ul = Option.extend({ }); -options.collapse = Option.extend(preventParentEmpty).extend({ +options.registry.collapse = Option.extend(preventParentEmpty).extend({ start: function () { var self = this; this._super(); this.$target.on('shown.bs.collapse hidden.bs.collapse', '[role="tabpanel"]', function () { - self.BuildingBlock.cover_target(self.$overlay, self.$target); + self.buildingBlock.cover_target(self.$overlay, self.$target); }); }, create_ids: function ($target) { @@ -1911,403 +734,5 @@ options.collapse = Option.extend(preventParentEmpty).extend({ }); -var SnippetEditor = Class.extend({ - init: function (BuildingBlock, dom) { - this.BuildingBlock = BuildingBlock; - this.$target = $(dom); - this.$overlay = this.$target.data('overlay'); - this.load_style_options(); - this.get_parent_block(); - this.start(); - }, - - // activate drag and drop for the snippets in the snippet toolbar - _drag_and_drop: function(){ - var self = this; - this.dropped = false; - this.$overlay.draggable({ - greedy: true, - appendTo: 'body', - cursor: "move", - handle: ".oe_snippet_move", - cursorAt: { - left: 18, - top: 14 - }, - helper: function() { - var $clone = $(this).clone().css({width: "24px", height: "24px", border: 0}); - $clone.find(".oe_overlay_options >:not(:contains(.oe_snippet_move)), .oe_handle").remove(); - $clone.find(":not(.glyphicon)").css({position: 'absolute', top: 0, left: 0}); - $clone.appendTo("body").removeClass("hidden"); - return $clone; - }, - start: _.bind(self._drag_and_drop_start, self), - stop: _.bind(self._drag_and_drop_stop, self) - }); - }, - _drag_and_drop_after_insert_dropzone: function (){}, - _drag_and_drop_active_drop_zone: function ($zones){ - var self = this; - $zones.droppable({ - over: function(){ - $(".oe_drop_zone.hide").removeClass("hide"); - $(this).addClass("hide").first().after(self.$target); - self.dropped = true; - }, - out: function(){ - $(this).removeClass("hide"); - self.$target.detach(); - self.dropped = false; - }, - }); - }, - _drag_and_drop_start: function (){ - var self = this; - self.BuildingBlock.hide(); - self.BuildingBlock.editor_busy = true; - self.size = { - width: self.$target.width(), - height: self.$target.height() - }; - self.$target.after("<div class='oe_drop_clone' style='display: none;'/>"); - self.$target.detach(); - self.$overlay.addClass("hidden"); - - var $selector_siblings; - for (var i=0; i<self.selector_siblings.length; i++) { - if (!$selector_siblings) $selector_siblings = self.selector_siblings[i].all(); - else $selector_siblings = $selector_siblings.add(self.selector_siblings[i].all()); - } - var $selector_children; - for (i=0; i<self.selector_children.length; i++) { - if (!$selector_children) $selector_children = self.selector_children[i].all(); - else $selector_children = $selector_children.add(self.selector_children[i].all()); - } - - self.BuildingBlock.activate_insertion_zones($selector_siblings, $selector_children); - - $("body").addClass('move-important'); - - self._drag_and_drop_after_insert_dropzone(); - self._drag_and_drop_active_drop_zone($('.oe_drop_zone')); - }, - _drag_and_drop_stop: function (){ - var self = this; - var $dropzone = this.$target.prev(); - var prev = $dropzone.length && $dropzone[0].previousSibling; - var next = this.$target.last()[0].nextSibling; - var $parent = this.$target.parent(); - - $(".oe_drop_clone").after(this.$target); - - this.$overlay.removeClass("hidden"); - $("body").removeClass('move-important'); - $('.oe_drop_zone').droppable('destroy').remove(); - $(".oe_drop_clone, .oe_drop_to_remove").remove(); - - if (this.dropped) { - this.BuildingBlock.parent.rte.historyRecordUndo(this.$target); - - if (prev) { - this.$target.insertAfter(prev); - } else if (next) { - this.$target.insertBefore(next); - } else { - $parent.prepend(this.$target); - } - - for (var i in this.styles){ - this.styles[i].on_move(); - } - } - - self.BuildingBlock.editor_busy = false; - - self.get_parent_block(); - setTimeout(function () {self.BuildingBlock.create_overlay(self.$target);},0); - }, - - load_style_options: function () { - var self = this; - var $styles = this.$overlay.find('.oe_options'); - var $ul = $styles.find('ul:first'); - this.styles = {}; - this.selector_siblings = []; - this.selector_children = []; - _.each(templateOptions, function (val, option_id) { - if (!val.selector.is(self.$target)) { - return; - } - if (val['drop-near']) self.selector_siblings.push(val['drop-near']); - if (val['drop-in']) self.selector_children.push(val['drop-in']); - - var option = val.option; - var Editor = options[option] || Option; - var editor = self.styles[option] = new Editor(self.BuildingBlock, self, self.$target, option_id); - $ul.append(editor.$el.addClass("snippet-option-" + option)); - editor.start(); - }); - - if (!this.selector_siblings.length && !this.selector_children.length) { - this.$overlay.find(".oe_snippet_move, .oe_snippet_clone, .oe_snippet_remove").addClass('hidden'); - } - - if ($ul.find("li").length) { - $styles.removeClass("hidden"); - } - this.$overlay.find('[data-toggle="dropdown"]').dropdown(); - }, - - get_parent_block: function () { - var self = this; - var $button = this.$overlay.find('.oe_snippet_parent'); - var $parent = globalSelector.closest(this.$target.parent()); - if ($parent.length) { - $button.removeClass("hidden"); - $button.off("click").on('click', function (event) { - event.preventDefault(); - setTimeout(function () { - self.BuildingBlock.make_active($parent); - }, 0); - }); - } else { - $button.addClass("hidden"); - } - }, - - /* - * start - * This method is called after init and _readXMLData - */ - start: function () { - if (!this.$target.parent().is(':o_editable')) { - this.$overlay.find('.oe_snippet_move, .oe_snippet_clone, .oe_snippet_remove').remove(); - } else { - this.$overlay.on('click', '.oe_snippet_clone', _.bind(this.on_clone, this)); - this.$overlay.on('click', '.oe_snippet_remove', _.bind(this.on_remove, this)); - this._drag_and_drop(); - } - }, - - on_clone: function (event) { - event.preventDefault(); - 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); - return false; - }, - - on_remove: function (event) { - event.preventDefault(); - this.on_blur(); - - 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(); - } - delete this.BuildingBlock.snippets[index]; - - // remove node and his empty - var node = this.$target.parent()[0]; - - this.$target.remove(); - this.$overlay.remove(); - - if (node && node.firstChild) { - $.summernote.core.dom.removeSpace(node, node.firstChild, 0, node.lastChild, 1); - if (!node.firstChild.tagName && node.firstChild.textContent === " ") { - node.firstChild.parentNode.removeChild(node.firstChild); - } - } - - // clean editor if they are image or table in deleted content - $(".note-control-selection").hide(); - $('.o_table_handler').remove(); - - return false; - }, - - /* - * drop_and_build_snippet - * This method is called just after that a thumbnail is drag and dropped into a drop zone - * (after the insertion of this.$body, if this.$body exists) - */ - drop_and_build_snippet: function () { - for (var i in this.styles){ - this.styles[i].drop_and_build_snippet(); - } - }, - - /* on_focus - * This method is called when the user click inside the snippet in the dom - */ - on_focus : function () { - this.$overlay.addClass('oe_active'); - for (var i in this.styles){ - this.styles[i].on_focus(); - } - }, - - /* on_focus - * This method is called when the user click outside the snippet in the dom, after a focus - */ - on_blur : function () { - for (var i in this.styles){ - this.styles[i].on_blur(); - } - this.$overlay.removeClass('oe_active'); - }, -}); - -/* t-field options */ - -options.many2one = Option.extend({ - start: function () { - var self = this; - - this.Model = this.$target.data('oe-many2one-model'); - this.ID = +this.$target.data('oe-many2one-id'); - - // create search button and bind search bar - this.$btn = $(core.qweb.render("website.many2one.button")) - .insertAfter(this.$overlay.find('.oe_options')); - - this.$ul = this.$btn.find("ul"); - this.$search = this.$ul.find('li:first'); - this.$search.find('input').on('mousedown click mouseup keyup keydown', function (e) { - e.stopPropagation(); - }); - - // move menu item - setTimeout(function () { - if (self.$overlay.find('.oe_options').hasClass('hidden')) { - self.$btn.css('height', '0').find('> a').addClass('hidden'); - self.$ul.show().css({ - 'top': '-24px', 'margin': '0', 'padding': '2px 0', 'position': 'relative' - }); - } else { - self.$btn.find('a').on('click', function () { - self.clear(); - }); - } - },0); - - // bind search input - this.$search.find('input') - .focus() - .on('keyup', function() { - self.find_existing($(this).val()); - }); - - // bind result - this.$ul.on('click', "li:not(:first) a", function () { - self.select_record(this); - }); - }, - - on_focus: function () { - this.$target.attr('contentEditable', 'false'); - this.clear(); - this._super(); - }, - clear: function () { - var self = this; - this.$search.siblings().remove(); - self.$search.find('input').val(""); - setTimeout(function () { - self.$search.find('input').focus(); - },0); - }, - - find_existing: function (name) { - var self = this; - var domain = []; - if (!name || !name.length) { - self.$search.siblings().remove(); - return; - } - if (isNaN(+name)) { - if (this.Model === "res.partner") { - domain.push(['name', 'ilike', name]); - } else { - domain.push('|', ['name', 'ilike', name], ['email', 'ilike', name]); - } - } else { - domain.push(['id', '=', name]); - } - - ajax.jsonRpc('/web/dataset/call_kw', 'call', { - model: this.Model, - method: 'search_read', - args: [domain, this.Model === "res.partner" ? ['name', 'display_name', 'city', 'country_id'] : ['name', 'display_name']], - kwargs: { - order: 'name DESC', - limit: 5, - context: website.get_context(), - } - }).then(function (result){ - self.$search.siblings().remove(); - self.$search.after(core.qweb.render("website.many2one.search",{contacts:result})); - }); - }, - - get_contact_rendering: function (options) { - return ajax.jsonRpc('/web/dataset/call_kw', 'call', { - model: 'website.qweb.field.contact', - method: 'get_record_to_html', - args: [[this.ID]], - kwargs: { - options: options, - context: website.get_context(), - } - }); - }, - - select_record: function (li) { - var self = this; - - this.BuildingBlock.parent.rte.historyRecordUndo(this.$target); - - self.ID = +$(li).data("id"); - self.$target.attr('data-oe-many2one-id', self.ID).data('oe-many2one-id', self.ID); - - if (self.$target.data('oe-type') === "contact") { - $('[data-oe-contact-options]') - .filter('[data-oe-model="'+self.$target.data('oe-model')+'"]') - .filter('[data-oe-id="'+self.$target.data('oe-id')+'"]') - .filter('[data-oe-field="'+self.$target.data('oe-field')+'"]') - .filter('[data-oe-contact-options!="'+self.$target.data('oe-contact-options')+'"]') - .add(self.$target) - .attr('data-oe-many2one-id', self.ID).data('oe-many2one-id', self.ID) - .each(function () { - var $node = $(this); - self.get_contact_rendering($node.data('oe-contact-options')) - .then(function (html){ - $node.html(html); - }); - }); - } else { - self.$target.html($(li).data("name")); - } - - self.clear(); - } -}); - -return { - BuildingBlock: BuildingBlock, - options: options, - Option: Option, - globalSelector: globalSelector, -}; - -}); +});
\ No newline at end of file |
