summaryrefslogtreecommitdiff
path: root/addons/web_editor/static/src/js
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2016-02-24 13:13:12 +0100
committerqsm-odoo <qsm@odoo.com>2016-02-24 13:47:36 +0100
commit6610d05549e347fbb548e606fa66cfb113df9e67 (patch)
treefc750ca544b5caa135791c0eaeb10dfee17eefa3 /addons/web_editor/static/src/js
parent58c5ff1d4f64f16d43106e6b00f0b94fe63506c2 (diff)
[REF] web_editor,website,mass_mailing: JS/XML update
* Adapt DOM selectors * Refactore dialog XMLs to have odoo styling * New editor options (background-position, ...) * Various improvements
Diffstat (limited to 'addons/web_editor/static/src/js')
-rw-r--r--addons/web_editor/static/src/js/backend.js22
-rw-r--r--addons/web_editor/static/src/js/base.js10
-rw-r--r--addons/web_editor/static/src/js/editor.js13
-rw-r--r--addons/web_editor/static/src/js/inline.js6
-rw-r--r--addons/web_editor/static/src/js/rte.js6
-rw-r--r--addons/web_editor/static/src/js/rte.summernote.js114
-rw-r--r--addons/web_editor/static/src/js/snippets.animation.js4
-rw-r--r--addons/web_editor/static/src/js/snippets.editor.js195
-rw-r--r--addons/web_editor/static/src/js/snippets.options.js1387
-rw-r--r--addons/web_editor/static/src/js/summernote.js6
-rw-r--r--addons/web_editor/static/src/js/translator.js4
-rw-r--r--addons/web_editor/static/src/js/widgets.js38
12 files changed, 889 insertions, 916 deletions
diff --git a/addons/web_editor/static/src/js/backend.js b/addons/web_editor/static/src/js/backend.js
index 72bf61cbb7f..08712a05d0e 100644
--- a/addons/web_editor/static/src/js/backend.js
+++ b/addons/web_editor/static/src/js/backend.js
@@ -51,7 +51,7 @@ var FieldTextHtmlSimple = widget.extend({
}
return config;
},
- start: function() {
+ start: function () {
var def = this._super.apply(this, arguments);
this.$translate.remove();
this.$translate = $();
@@ -59,7 +59,7 @@ var FieldTextHtmlSimple = widget.extend({
this.$content.trigger('mouseup');
return def;
},
- initialize_content: function() {
+ initialize_content: function () {
var self = this;
this.$textarea = this.$("textarea").val(this.get('value') || "<p><br/></p>");
this.$content = $();
@@ -118,20 +118,20 @@ var FieldTextHtmlSimple = widget.extend({
return value;
},
focus: function() {
- if (this.get("effective_readonly")) {
+ if (!(!this.get("effective_readonly") && this.$textarea)) {
return false;
}
// on IE an error may occur when creating range on not displayed element
try {
- return this.$content.focusInEnd();
+ return this.$textarea.focusInEnd();
} catch (e) {
- return this.$content.focus();
+ return this.$textarea.focus();
}
},
resize: function() {
this.$('iframe').css('height', '0px').css('height', Math.max(30, Math.min(this.$content[0] ? this.$content[0].scrollHeight : 0, 500)) + 'px');
},
- render_value: function() {
+ render_value: function () {
var value = this.get('value');
this.$textarea.val(value || '');
this.$content.html(this.text_to_html(value));
@@ -148,10 +148,10 @@ var FieldTextHtmlSimple = widget.extend({
this.$('.note-toolbar').find('button[data-event="undo"]').attr('disabled', false);
}
},
- is_false: function() {
+ is_false: function () {
return !this.get('value') || this.get('value') === "<p><br/></p>" || !this.get('value').match(/\S/);
},
- before_save: function() {
+ before_save: function () {
if (this.options['style-inline']) {
transcoder.class_to_style(this.$content);
transcoder.font_to_img(this.$content);
@@ -268,7 +268,7 @@ var FieldTextHtml = widget.extend({
return src;
},
- initialize_content: function() {
+ initialize_content: function () {
this.$el.closest('.modal-body').css('max-height', 'none');
this.$iframe = this.$el.find('iframe');
this.document = null;
@@ -334,7 +334,7 @@ var FieldTextHtml = widget.extend({
self.initialize_content();
});
},
- render_value: function() {
+ render_value: function () {
if (this.lang !== this.view.dataset.context.lang || this.$iframe.attr('src').match(/[?&]edit_translations=1/)) {
return;
}
@@ -354,7 +354,7 @@ var FieldTextHtml = widget.extend({
}
}
},
- is_false: function() {
+ is_false: function () {
return this.get('value') === false || !this.$content.html() || !this.$content.html().match(/\S/);
},
before_save: function () {
diff --git a/addons/web_editor/static/src/js/base.js b/addons/web_editor/static/src/js/base.js
index 4d8d128f60c..f65ecaa7c02 100644
--- a/addons/web_editor/static/src/js/base.js
+++ b/addons/web_editor/static/src/js/base.js
@@ -30,7 +30,7 @@ data.dom_ready = dom_ready;
// todo: remove and load a bundle of translated templates
var all_ready;
-data.ready = function() {
+data.ready = function () {
if (!all_ready) {
all_ready = $.when(dom_ready, ajax.loadXML()).then(translations);
} else if(all_ready.state() === "resolved") { // can add async template
@@ -40,9 +40,9 @@ data.ready = function() {
};
function translations() {
- function translate_node(node){
+ function translate_node(node) {
if(node.nodeType === 3) { // TEXT_NODE
- if(node.nodeValue.match(/\S/)){
+ if(node.nodeValue.match(/\S/)) {
var space = node.nodeValue.match(/^([\s]*)([\s\S]*?)([\s]*)$/);
node.nodeValue = space[1] + $.trim(_t(space[2])) + space[3];
}
@@ -55,11 +55,11 @@ function translations() {
'mods': ['web_editor'],
'lang': data.get_context().lang
})
- .then(function(trans) {
+ .then(function (trans) {
_t.database.set_bundle(trans);
}).then(function () {
var keys = _.keys(qweb.templates);
- for (var i = 0; i < keys.length; i++){
+ for (var i = 0; i < keys.length; i++) {
translate_node(qweb.templates[keys[i]]);
}
}).promise();
diff --git a/addons/web_editor/static/src/js/editor.js b/addons/web_editor/static/src/js/editor.js
index 88d86bc825b..9e842bed4bc 100644
--- a/addons/web_editor/static/src/js/editor.js
+++ b/addons/web_editor/static/src/js/editor.js
@@ -63,9 +63,9 @@ editor.Class = Widget.extend({
template: 'web_editor.editorbar',
events: {
'click button[data-action=save]': 'save',
- 'click a[data-action=cancel]': 'cancel',
+ 'click button[data-action=cancel]': 'cancel',
},
- init: function(parent) {
+ init: function (parent) {
var self = this;
var res = this._super.apply(this, arguments);
this.parent = parent;
@@ -75,7 +75,7 @@ editor.Class = Widget.extend({
});
return res;
},
- start: function() {
+ start: function () {
var self = this;
$('.dropdown-toggle').dropdown();
@@ -86,14 +86,13 @@ editor.Class = Widget.extend({
this.rte.start();
var flag = false;
- window.onbeforeunload = function(event) {
+ window.onbeforeunload = function (event) {
if (rte.history.getEditableHasUndo().length && !flag) {
flag = true;
setTimeout(function () {flag=false;},0);
return _t('This document is not saved!');
}
};
- this.$('button[data-action="save"]').prop('disabled', true);
return this._super();
},
display_placeholder: function () {
@@ -119,9 +118,7 @@ editor.Class = Widget.extend({
}
});
},
- rte_changed: function () {
- this.$('button[data-action=save]').prop('disabled', !rte.history.getEditableHasUndo().length);
- },
+ rte_changed: function () {},
save: function () {
return this.rte.save().then(function () {
editor.reload();
diff --git a/addons/web_editor/static/src/js/inline.js b/addons/web_editor/static/src/js/inline.js
index 2b6ee1c6595..8f63d603b20 100644
--- a/addons/web_editor/static/src/js/inline.js
+++ b/addons/web_editor/static/src/js/inline.js
@@ -57,10 +57,10 @@ snippet_editor.Class.include({
transcoder.class_to_style($editable);
// fix outlook image rendering bug
- _.each(['width', 'height'], function(attribute) {
- $editable.find('img[style*="width"], img[style*="height"]').attr(attribute, function(){
+ _.each(['width', 'height'], function (attribute) {
+ $editable.find('img[style*="width"], img[style*="height"]').attr(attribute, function () {
return $(this)[attribute]();
- }).css(attribute, function(){
+ }).css(attribute, function () {
return $(this).get(0).style[attribute] || 'auto';
});
});
diff --git a/addons/web_editor/static/src/js/rte.js b/addons/web_editor/static/src/js/rte.js
index becaf978d17..bbd5e6616aa 100644
--- a/addons/web_editor/static/src/js/rte.js
+++ b/addons/web_editor/static/src/js/rte.js
@@ -203,7 +203,7 @@ var history = new History();
// add focusIn to jQuery to allow to move caret into a div of a contentEditable area
$.extend($.expr[':'],{
- o_editable: function(node,i,m){
+ o_editable: function (node,i,m) {
while (node) {
if (node.className) {
if (node.className.indexOf('o_not_editable')!==-1 ) {
@@ -423,11 +423,11 @@ var RTE = Widget.extend({
/**
* Get HTML cloned element with text nodes escaped for XML storage
*/
- getEscapedElement: function($el) {
+ getEscapedElement: function ($el) {
var escaped_el = $el.clone();
var to_escape = escaped_el.find('*').addBack();
to_escape = to_escape.not(to_escape.filter('object,iframe,script,style,[data-oe-model][data-oe-model!="ir.ui.view"]').find('*').addBack());
- to_escape.contents().each(function(){
+ to_escape.contents().each(function () {
if(this.nodeType == 3) {
this.nodeValue = $('<div />').text(this.nodeValue).html();
}
diff --git a/addons/web_editor/static/src/js/rte.summernote.js b/addons/web_editor/static/src/js/rte.summernote.js
index 28e1a32a55e..31ee5db72fe 100644
--- a/addons/web_editor/static/src/js/rte.summernote.js
+++ b/addons/web_editor/static/src/js/rte.summernote.js
@@ -44,27 +44,68 @@ renderer.createPalette = function ($container, options) {
return;
}
- var $color = $container.find('.note-color');
- var html = $(QWeb.render('web_editor.colorpicker'));
- var theme = html.find('.theme')
+ var $clpicker = $(QWeb.render('web_editor.colorpicker'));
- $color.find('.palette_theme').prepend(html.find('.theme'));
- $color.find('.palette_ui').prepend(html.find('.ui'));
- $color.find('.palette_grayscale').prepend(html.find('.grayscale'));
+ $container.find('.colorpicker').each(function (i, picker) {
+ var $picker = $(picker);
- var $bg = $color.find('.background_toggle .dropdown-menu button');
- var $fore = $color.find('.foreground_toggle .dropdown-menu button');
+ var $sections = $clpicker.find('.o_colorpicker_section').clone(true);
+
+ var $toggles = $picker.find('.o_colorpicker_section_menu');
+ var $tabs = $picker.find('.o_colorpicker_section_tabs');
+ var $defaultToggle = $toggles.find('li');
+ var $defaultTab = $tabs.find('.tab-pane');
+
+ var newDefaultID = _.uniqueId();
+ $defaultToggle.children('a').attr('href', $defaultToggle.children('a').attr('href') + newDefaultID);
+ $defaultTab.attr('id', $defaultTab.attr('id') + newDefaultID);
+
+ if ($sections.length) {
+ $sections.each(function () {
+ var $section = $(this);
+ var id = 'o_palette_' + $section.data('name') + _.uniqueId();
+
+ var $li = $('<li/>')
+ .append($('<a/>', {href: '#' + id})
+ .append($('<i/>', {'class': $section.data('iconClass') || '', html: $section.data('iconContent') || ''})));
+ $defaultToggle.before($li);
+
+ $defaultTab.before($section.addClass('tab-pane').attr('id', id));
+ });
+ } else {
+ var id = 'o_palette_other' + _.uniqueId();
+
+ var $li = $('<li/>')
+ .append($('<a/>', {href: '#' + id, 'aria-controls': id})
+ .append($('<i/>', {'class': 'fa fa-magic'})));
+ $toggles.prepend($li);
+
+ $tabs.prepend($('<div/>', {'class': 'tab-pane', id: id}).append($clpicker.clone(true)));
+ }
+
+ $toggles.find('li:first-child').addClass('active');
+ $tabs.find('div:first-child').addClass('active');
+
+ $toggles.on('click mouseover', '> li > a', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ $(this).tab('show');
+ });
+ });
+
+ var $bg = $container.find('.o_background_toggle .dropdown-menu button');
+ var $fore = $container.find('.o_foreground_toggle .dropdown-menu button');
$bg.each(function () {
- $(this).attr('data-event', 'backColor').attr('data-value',
- $(this).attr($(this).attr('class') == 'note-color-btn' ?'title':'class')
- );
+ var $el = $(this);
+ var className = $el.hasClass('note-color-btn')? $el.attr('title') : ('bg-' + $el.data('color'));
+ $el.attr('data-event', 'backColor').attr('data-value', className).addClass(className);
});
$fore.each(function () {
- $(this).attr('data-event', 'foreColor').attr('data-value',
- $(this).attr($(this).attr('class') == 'note-color-btn' ?'title':'class').replace(/bg-/, 'text-')
- );
- });
+ var $el = $(this);
+ var className = $el.hasClass('note-color-btn')? $el.attr('title') : ('text-' + $el.data('color'));
+ $el.attr('data-event', 'foreColor').attr('data-value', className).addClass(className);
+ });
};
var fn_tplPopovers = renderer.tplPopovers;
@@ -92,7 +133,7 @@ renderer.tplPopovers = function (lang, options) {
var $alt = $('<div class="btn-group"/>');
$alt.prependTo($imagePopover.find('.popover-content'));
- $alt.append('<button class="btn btn-default btn-sm btn-small" data-event="alt"><strong>Alt: </strong><span class="o_image_alt"></span></button>');
+ $alt.append('<button class="btn btn-default btn-sm btn-small" data-event="alt"><strong>' + _t('Description') + ': </strong><span class="o_image_alt"/></button>');
// padding button
var $padding = $('<div class="btn-group"/>');
@@ -209,24 +250,7 @@ eventHandler.modules.popover.button.update = function ($container, oStyle) {
fn_boutton_update.call(this, $container, oStyle);
- $container.find('.note-color').removeClass("hidden")
-
- // ACTIVATE TABS
- $container.find('[data-tab-target]').each(function(){
- var $el = $(this);
- var target = $el.data('tab-target');
- var $parent = $el.parent().closest('.tabs_container');
- var $parentLi = $el.parent().closest('li');
-
- $parentLi.on('click', function(){return false});
-
- $el.on('click', function(){
- $parent.find('.tab, .tabs_toggles li').removeClass('on');
- $parent.find(target).add($parentLi).addClass('on')
- return false;
- })
- })
-
+ $container.find('.note-color').removeClass("hidden");
if (oStyle.image) {
$container.find('[data-event]').parent().removeClass("active");
@@ -728,17 +752,33 @@ eventHandler.attach = function (oLayoutInfo, options) {
$(document).on('mousedown', summernote_mousedown);
$(document).on('mouseup', summernote_mouseup);
oLayoutInfo.editor().off('click').on('click', function (e) {e.preventDefault();}); // if the content editable is a link
- oLayoutInfo.editor().on('dblclick', 'img, .media_iframe_video, span.fa, i.fa, span.fa, a.o_image', function (event) {
+ var imageSelector = 'img, .media_iframe_video, span.fa, i.fa, span.fa, a.o_image';
+ var show_tooltip = true;
+ oLayoutInfo.editor().on('dblclick', imageSelector, function (event) {
+ show_tooltip = false;
if (!$(event.target).closest(".note-toolbar").length) { // prevent icon edition of top bar for default summernote
new widgets.MediaDialog(oLayoutInfo.editor(), event.target).appendTo(document.body);
}
});
+ oLayoutInfo.editor().on('click', imageSelector, function (event) {
+ if (!$(event.target).closest(".note-toolbar").length) { // prevent icon edition of top bar for default summernote
+ setTimeout(function () {
+ if (show_tooltip) {
+ $(event.target).tooltip({title: _t('Double-click to edit'), trigger: 'manuel', container: 'body'}).tooltip('show');
+ setTimeout(function () {
+ $(event.target).tooltip('destroy');
+ }, 800);
+ }
+ }, 400);
+ show_tooltip = true;
+ }
+ });
if(oLayoutInfo.editor().is('[data-oe-model][data-oe-type="image"]')) {
oLayoutInfo.editor().on('click', 'img', function (event) {
$(event.target).trigger("dblclick");
});
}
- oLayoutInfo.editable().on('mousedown', function(e) {
+ oLayoutInfo.editable().on('mousedown', function (e) {
if(dom.isImg(e.target)) {
range.createFromNode(e.target).select();
}
@@ -898,7 +938,7 @@ $.summernote.lang.odoo = {
recent: _t('Recent Color'),
more: _t('More Color'),
background: _t('Background Color'),
- foreground: _t('Foreground Color'),
+ foreground: _t('Font Color'),
transparent: _t('Transparent'),
setTransparent: _t('Set transparent'),
reset: _t('Reset'),
diff --git a/addons/web_editor/static/src/js/snippets.animation.js b/addons/web_editor/static/src/js/snippets.animation.js
index bb67d026e3c..f396bafcc30 100644
--- a/addons/web_editor/static/src/js/snippets.animation.js
+++ b/addons/web_editor/static/src/js/snippets.animation.js
@@ -43,7 +43,7 @@ var start = function (editable_mode, $target) {
else continue;
}
- $(selector).each(function() {
+ $(selector).each(function () {
var $snipped_id = $(this);
if ( !$snipped_id.parents("#oe_snippets").length &&
!$snipped_id.parent("body").length &&
@@ -58,7 +58,7 @@ var start = function (editable_mode, $target) {
};
var stop = function () {
- $(ready).each(function() {
+ $(ready).each(function () {
var $snipped_id = $(this);
if ($snipped_id.data("snippet-view")) {
$snipped_id.data("snippet-view").stop();
diff --git a/addons/web_editor/static/src/js/snippets.editor.js b/addons/web_editor/static/src/js/snippets.editor.js
index 93e09c4e7f0..ef033dc07f3 100644
--- a/addons/web_editor/static/src/js/snippets.editor.js
+++ b/addons/web_editor/static/src/js/snippets.editor.js
@@ -18,7 +18,7 @@ var dummy = editor.dummy;
ajax.loadXML('/web_editor/static/src/xml/snippets.xml', qweb);
editor.Class.include({
- init: function() {
+ init: function () {
var self = this;
var res = this._super.apply(this, arguments);
var $editable = this.rte.editable();
@@ -46,10 +46,10 @@ editor.Class.include({
/* ----- SNIPPET SELECTOR ---- */
$.extend($.expr[':'],{
- hasData: function(node,i,m){
+ hasData: function (node,i,m) {
return !!_.toArray(node.dataset).length;
},
- data: function(node,i,m){
+ data: function (node,i,m) {
return $(node).data(m[3]);
}
});
@@ -75,28 +75,23 @@ $.fn.extend({
/* ----- BuildingBlock (managment of drag&drop and focus/blur snippets) ---- */
var BuildingBlock = Widget.extend({
- template: 'web_editor.snippets',
+ id: "oe_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' class='o_css_editor'></div>").appendTo('body');
+ if(!$('#oe_manipulators').length) {
+ $("<div/>", {id: "oe_manipulators", 'class': "o_css_editor"}).appendTo('body');
}
this.$active_snipped_id = false;
this.snippets = [];
data.instance = this;
},
- start: function() {
+ 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);
@@ -130,8 +125,7 @@ var BuildingBlock = Widget.extend({
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();
+ self.$('.scroll:first > ul li:eq('+(event.keyCode-49)+') a').trigger("click");
event.preventDefault();
}
});
@@ -188,22 +182,19 @@ var BuildingBlock = Widget.extend({
var self = this;
var url = this._get_snippet_url();
if (!url || !url.length) {
- this.$snippet.detach();
+ this.$el.detach();
return;
}
- this.$el.find("#o_left_bar").addClass("hidden");
return ajax.jsonRpc(url, 'call', {}).then(function (html) {
self.compute_snippet_templates(html);
self.trigger("snippets:ready");
}, function () {
- self.$snippet.hide();
console.warn('Snippets template not found:', url);
});
},
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");
@@ -309,16 +300,14 @@ var BuildingBlock = Widget.extend({
// hide scroll if no snippets defined
if (!number) {
- this.$snippet.detach();
- } else {
- this.$el.find("#o_left_bar").removeClass("hidden");
+ this.$el.detach();
}
$("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() {
+ .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) {
@@ -328,7 +317,6 @@ var BuildingBlock = Widget.extend({
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 () {
@@ -339,14 +327,13 @@ var BuildingBlock = Widget.extend({
}
}
});
- // end
$html.find('.o_not_editable').attr("contentEditable", false);
- $left_bar.html($html);
+ this.$el.html($html);
// animate for list of snippet blocks
- $left_bar.on('click', '.scroll-link', function (event) {
+ this.$el.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);
@@ -367,55 +354,33 @@ var BuildingBlock = Widget.extend({
}
$(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", "100%");
- } 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;
+ 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
+ width: $target.outerWidth(),
+ left: pos.left,
+ top: pos.top - mt,
});
- $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});
+ $el.find('.oe_handles').css({
+ height: $target.outerHeight(true),
+ });
+
+ $el.toggleClass('o_top_cover', pos.top <= (this.$('#o_scroll').position().top + 15));
},
show_blocks: function () {
var self = this;
var cache = {};
- this.$snippet.find(".o_panel").each(function () {
+ this.$(".o_panel").each(function () {
var catcheck = false;
var $category = $(this);
$category.find(".oe_snippet_body").each(function () {
@@ -450,15 +415,6 @@ var BuildingBlock = Widget.extend({
$('#oe_snippets .scroll a[data-toggle="tab"][href="#' + $category.attr("id") + '"]').toggle(catcheck);
});
},
- show: function () {
- var self = this;
- 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;
@@ -541,7 +497,7 @@ var BuildingBlock = Widget.extend({
this.cover_target($snippet.data('overlay'), $snippet);
this.snippet_focus($snippet);
}
- this.$snippet.trigger('snippet-activated', $snippet);
+ this.$el.trigger('snippet-activated', $snippet);
if ($snippet) {
$snippet.trigger('snippet-activated', $snippet);
}
@@ -554,7 +510,7 @@ var BuildingBlock = Widget.extend({
},
// activate drag and drop for the snippets in the snippet toolbar
- make_snippet_draggable: function($snippets){
+ make_snippet_draggable: function ($snippets) {
var self = this;
var $tumb = $snippets.find(".oe_snippet_thumbnail_img:first");
var left = $tumb.outerWidth()/2;
@@ -572,8 +528,7 @@ var BuildingBlock = Widget.extend({
'left': left,
'top': top
},
- start: function(){
- self.hide();
+ start: function () {
dropped = false;
// snippet_selectors => to get drop-near, drop-in
$snippet = $(this);
@@ -602,23 +557,25 @@ var BuildingBlock = Widget.extend({
return;
}
+ self.make_active(false);
self.activate_insertion_zones($selector_siblings, $selector_children);
$('.oe_drop_zone').droppable({
- over: function(){
+ over: function () {
dropped = true;
- $(this).first().after($toInsert);
+ $(this).first().after($toInsert).addClass('hidden');
},
- out: function(){
+ out: function () {
var prev = $toInsert.prev();
- if(this === prev[0]){
+ if(this === prev[0]) {
dropped = false;
$toInsert.detach();
+ $(this).removeClass('hidden');
}
- }
+ },
});
},
- stop: function(ev, ui){
+ stop: function (ev, ui) {
$toInsert.removeClass('oe_snippet_body');
if (! dropped && self.$editable.find('.oe_drop_zone') && ui.position.top > 3) {
@@ -658,7 +615,7 @@ var BuildingBlock = Widget.extend({
$target = $toInsert;
setTimeout(function () {
- self.$snippet.trigger('snippet-dropped', $target);
+ self.$el.trigger('snippet-dropped', $target);
animation.start(true, $target);
@@ -693,8 +650,8 @@ var BuildingBlock = Widget.extend({
},
// return the original snippet in the editor bar from a snippet id (string)
- get_snippet_from_id: function(id){
- return $('.oe_snippet').filter(function(){
+ get_snippet_from_id: function (id) {
+ return $('.oe_snippet').filter(function () {
return $(this).data('option') === id;
}).first();
},
@@ -704,12 +661,12 @@ var BuildingBlock = Widget.extend({
// 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){
+ activate_insertion_zones: function ($selector_siblings, $selector_children) {
var self = this;
- var zone_template = $("<div class='oe_drop_zone oe_insert'></div>");
+ var zone_template = $("<div class='oe_drop_zone oe_insert'/>");
if ($selector_children) {
- $selector_children.each(function (){
+ $selector_children.each(function () {
var $zone = $(this);
var css = window.getComputedStyle(this);
var float = css.float || css.cssFloat;
@@ -719,7 +676,7 @@ var BuildingBlock = Widget.extend({
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({
+ $drop.addClass("oe_vertical").css({
'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
'float': 'none',
'display': 'inline-block'
@@ -734,7 +691,7 @@ var BuildingBlock = Widget.extend({
var node = $drop[0].nextSibling;
var test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR"));
if (test) {
- $drop.addClass("oe_vertical oe_vertical_text").css({
+ $drop.addClass("oe_vertical").css({
'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
'float': 'none',
'display': 'inline-block'
@@ -752,20 +709,20 @@ var BuildingBlock = Widget.extend({
}
if ($selector_siblings) {
- $selector_siblings.filter(':not(.oe_drop_zone):not(.oe_drop_clone)').each(function (){
+ $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){
+ 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){
+ 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));
@@ -785,7 +742,7 @@ var BuildingBlock = Widget.extend({
// 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 (){
+ $zones.each(function () {
var zone = $(this);
var prev = zone.prev();
var next = zone.next();
@@ -799,12 +756,12 @@ var BuildingBlock = Widget.extend({
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') ){
+ && (float_next === 'left' || float_next === 'right') ) {
zone.remove();
}else if( !( disp_prev === null
|| disp_next === null
|| disp_prev === 'block'
- || disp_next === 'block' )){
+ || disp_next === 'block' )) {
zone.remove();
}
});
@@ -812,21 +769,21 @@ var BuildingBlock = Widget.extend({
// 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){
+ activate_overlay_zones: function ($targets) {
var self = this;
- function is_visible($el){
+ 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)); });
+ $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)); });
+ $targets = $targets.filter(function () {
+ var parents = $(this).parents().filter(function () { return !is_visible($(this)); });
return parents.length === 0;
});
@@ -839,7 +796,7 @@ var BuildingBlock = Widget.extend({
if (document.body && document.body.addEventListener) {
$zone.on("click mousedown mousedown", function passThrough(event) {
event.preventDefault();
- $target.each(function() {
+ $target.each(function () {
// check if clicked point (taken from event) is inside element
event.srcElement = this;
$(this).trigger(event.type);
@@ -849,8 +806,8 @@ var BuildingBlock = Widget.extend({
}
$zone.appendTo('#oe_manipulators');
- $zone.data('target',$target);
- $target.data('overlay',$zone);
+ $zone.data('target', $target);
+ $target.data('overlay', $zone);
var timer;
$target.closest('.o_editable').on("content_changed", function (event) {
@@ -890,7 +847,7 @@ var Editor = Class.extend({
},
// activate drag and drop for the snippets in the snippet toolbar
- _drag_and_drop: function(){
+ _drag_and_drop: function () {
var self = this;
this.dropped = false;
this.$overlay.draggable({
@@ -902,7 +859,7 @@ var Editor = Class.extend({
left: 18,
top: 14
},
- helper: function() {
+ 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});
@@ -913,25 +870,24 @@ var Editor = Class.extend({
stop: _.bind(self._drag_and_drop_stop, self)
});
},
- _drag_and_drop_after_insert_dropzone: function (){},
- _drag_and_drop_active_drop_zone: function ($zones){
+ _drag_and_drop_after_insert_dropzone: function () {},
+ _drag_and_drop_active_drop_zone: function ($zones) {
var self = this;
$zones.droppable({
- over: function(){
+ over: function () {
$(".oe_drop_zone.hide").removeClass("hide");
$(this).addClass("hide").first().after(self.$target);
self.dropped = true;
},
- out: function(){
+ out: function () {
$(this).removeClass("hide");
self.$target.detach();
self.dropped = false;
},
});
},
- _drag_and_drop_start: function (){
+ _drag_and_drop_start: function () {
var self = this;
- self.buildingBlock.hide();
self.buildingBlock.editor_busy = true;
self.size = {
width: self.$target.width(),
@@ -952,6 +908,7 @@ var Editor = Class.extend({
else $selector_children = $selector_children.add(self.selector_children[i].all());
}
+ self.buildingBlock.make_active(false);
self.buildingBlock.activate_insertion_zones($selector_siblings, $selector_children);
$("body").addClass('move-important');
@@ -959,7 +916,7 @@ var Editor = Class.extend({
self._drag_and_drop_after_insert_dropzone();
self._drag_and_drop_active_drop_zone($('.oe_drop_zone'));
},
- _drag_and_drop_stop: function (){
+ _drag_and_drop_stop: function () {
var self = this;
var $dropzone = this.$target.prev();
var prev = $dropzone.length && $dropzone[0].previousSibling;
@@ -984,7 +941,7 @@ var Editor = Class.extend({
$parent.prepend(this.$target);
}
- for (var i in this.styles){
+ for (var i in this.styles) {
this.styles[i].on_move();
}
}
@@ -992,9 +949,9 @@ var Editor = Class.extend({
self.buildingBlock.editor_busy = false;
self.get_parent_block();
- setTimeout(function () {
+ _.defer(function () {
self.buildingBlock.cover_target(self.$target.data('overlay'), self.$target);
- },0);
+ });
},
load_style_options: function () {
@@ -1071,7 +1028,7 @@ var Editor = Class.extend({
this.$target.after($clone);
this.buildingBlock.call_for_all_snippets($clone, function (editor, $snippet) {
- for (var i in editor.styles){
+ for (var i in editor.styles) {
editor.styles[i].on_clone($snippet);
}
});
@@ -1086,7 +1043,7 @@ var Editor = Class.extend({
var index = _.indexOf(this.buildingBlock.snippets, this.$target.get(0));
this.buildingBlock.call_for_all_snippets(this.$target, function (editor, $snippet) {
- for (var i in editor.styles){
+ for (var i in editor.styles) {
editor.styles[i].on_remove();
}
});
@@ -1120,7 +1077,7 @@ var Editor = Class.extend({
* (after the insertion of this.$body, if this.$body exists)
*/
drop_and_build_snippet: function () {
- for (var i in this.styles){
+ for (var i in this.styles) {
this.styles[i].drop_and_build_snippet();
}
},
@@ -1130,7 +1087,7 @@ var Editor = Class.extend({
*/
on_focus : function () {
this.$overlay.addClass('oe_active');
- for (var i in this.styles){
+ for (var i in this.styles) {
this.styles[i].on_focus();
}
},
@@ -1139,7 +1096,7 @@ var Editor = Class.extend({
* 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){
+ for (var i in this.styles) {
this.styles[i].on_blur();
}
this.$overlay.removeClass('oe_active');
diff --git a/addons/web_editor/static/src/js/snippets.options.js b/addons/web_editor/static/src/js/snippets.options.js
index cbf8fea5c4e..811d0e9c175 100644
--- a/addons/web_editor/static/src/js/snippets.options.js
+++ b/addons/web_editor/static/src/js/snippets.options.js
@@ -1,766 +1,747 @@
odoo.define('web_editor.snippets.options', function (require) {
-'use strict';
-
-var Class = require('web.Class');
-var ajax = require('web.ajax');
-var core = require('web.core');
-var base = require('web_editor.base');
-var editor = require('web_editor.editor');
-var widget = require('web_editor.widget');
-var animation = require('web_editor.snippets.animation');
-
-var qweb = core.qweb;
-
-/* ----- Editor option (object link the the xml with data-js) ---- */
-
-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 = this.buildingBlock.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') {
+ 'use strict';
+
+ var Class = require('web.Class');
+ var ajax = require('web.ajax');
+ var core = require('web.core');
+ var Dialog = require('web.Dialog');
+ var base = require('web_editor.base');
+ var editor = require('web_editor.editor');
+ var widget = require('web_editor.widget');
+ var animation = require('web_editor.snippets.animation');
+
+ var qweb = core.qweb;
+ var _t = core._t;
+
+ /* ----- Editor option (object link the the xml with data-js) ---- */
+
+ var SnippetOption = Class.extend({
+ // initialisation (don't overwrite)
+ init: function (BuildingBlock, editor, $target, option_id) {
+ this.buildingBlock = BuildingBlock;
+ this.editor = editor;
+ this.$target = $target;
+ var option = this.buildingBlock.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.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 ($clone) {
- },
-
- 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);
+ 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 ($clone) {
+ },
+
+ 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 ($li.is('[data-'+method+']') || $li.closest('[data-'+method+']').size()) {
- delete self.reset_methods[k];
+ if (method) {
+ self[method]("reset", null);
}
}
- 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,
+ $methods = [],
+ el = $li[0];
+
+ if ($li.data('only') && type !== $li.data('only')) {
+ return;
}
- }
- 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,
- $methods = [],
- el = $li[0];
-
- if ($li.data('only') && type !== $li.data('only')) {
- return;
- }
- if (type==="click") {
- this.reset();
- this.buildingBlock.parent.rte.historyRecordUndo(this.$target);
- }
+ 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;
+ 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;
}
- return false;
- }
- function method(el) {
- var data = {};
- for (var k in el.dataset) {
- if (filter (k)) {
- data[k] = el.dataset[k];
+ function method(el) {
+ var data = {};
+ for (var k in el.dataset) {
+ if (filter (k)) {
+ data[k] = el.dataset[k];
+ }
}
+ return data;
}
- return data;
- }
- while (el && this.$el.is(el) || _.some(this.$el.map(function () {return $.contains(this, el);}).get()) ) {
- if (hasData(el)) {
- $methods.push(el);
+ 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;
}
- el = el.parentNode;
- }
- $methods.reverse();
+ $methods.reverse();
- _.each($methods, function (el) {
- var $el = $(el);
- var methods = method(el);
+ _.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);
+ 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+"'");
}
- 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, $li) {
- var $lis = this.$el.find('[data-toggle_class]').add(this.$el).filter('[data-toggle_class]');
+ // default method for snippet
+ toggle_class: function (type, value, $li) {
+ 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)'));
+ 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);
+ this.$target.removeClass(classes);
+ this.$target.addClass(active_classes);
- if (type !== 'reset') {
- this.$target.toggleClass(value);
+ if (type !== 'reset') {
+ this.$target.toggleClass(value);
+ }
+ },
+ select_class: function (type, value, $li) {
+ 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: editor.dummy
+ });
+ var registry = {};
+
+ /* ----- default options ---- */
+
+ // to remove after 9.0 (keep for compatibility without update with -u)
+ registry.media = SnippetOption.extend({
+ start: function () {
+ var self =this;
+ this._super();
+ animation.start(true, this.$target);
+ this.$target.closest(".o_editable").on("content_changed", function () {
+ if (!self.$target.parent().length) {
+ self.$target.remove();
+ self.$overlay.remove();
+ }
+ });
+ },
+ edition: function (type, value) {
+ if(type !== "click") return;
+ var self = this;
+ var _editor = new widget.MediaDialog(this.$target.closest('.o_editable'), this.$target[0]);
+ _editor.appendTo(document.body);
+ _editor.on('saved', this, function (item, old) {
+ 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);
+ }
+ $(item).trigger("content_changed");
+ });
+ },
+ 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);
+ }
}
- },
- select_class: function (type, value, $li) {
- var $lis = this.$el.find('[data-select_class]').add(this.$el).filter('[data-select_class]');
+ });
+
+ registry.colorpicker = SnippetOption.extend({
+ start: function () {
+ var self = this;
+ var res = this._super();
+
+ if (!this.$el.find('.colorpicker').length) {
+ var $pt = $(qweb.render('web_editor.snippet.option.colorpicker'));
+ var $clpicker = $(qweb.render('web_editor.colorpicker'));
+
+ var $toggles = $pt.find('.o_colorpicker_section_menu');
+ var $tabs = $pt.find('.o_colorpicker_section_tabs');
+
+ var $sections = $clpicker.find('.o_colorpicker_section');
+ if ($sections.length) {
+ $sections.each(function () {
+ var $section = $(this);
+ var id = 'o_palette_' + $section.data('name') + _.uniqueId();
+
+ var $li = $('<li/>')
+ .append($('<a/>', {href: '#' + id})
+ .append($('<i/>', {'class': $section.data('iconClass') || '', html: $section.data('iconContent') || ''})));
+ $toggles.append($li);
+
+ $tabs.append($section.addClass('tab-pane').attr('id', id));
+ });
+ $toggles.find('li').first().addClass('active');
+ $tabs.find('div').first().addClass('active');
+
+ $toggles.on('click mouseover', '> li > a', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ $(this).tab('show');
+ });
+ } else {
+ $toggles.parent().empty().append($clpicker);
+ }
- var classes = $lis.map(function () {return $(this).data('select_class');}).get();
+ this.$el.find('li').append($pt);
+ }
+ if (this.$el.data('area')) {
+ this.$target = this.$target.find(this.$el.data('area'));
+ this.$el.removeData('area').removeAttr('area');
+ }
- 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);
- },
+ var classes = [];
+ this.$el.find(".colorpicker button").map(function () {
+ var $color = $(this);
+ var className = 'bg-' + $color.data('color');
- clean_for_save: editor.dummy
-});
+ $color.addClass(className);
-/* ----- default options ---- */
-
-// to remove after 9.0 (keep for compatibility without update with -u)
-var media = Option.extend({
- start: function () {
- var self =this;
- this._super();
- animation.start(true, this.$target);
- this.$target.closest(".o_editable").on("content_changed", function () {
- if (!self.$target.parent().length) {
- self.$target.remove();
- self.$overlay.remove();
- }
- });
- },
- edition: function (type, value) {
- if(type !== "click") return;
- var self = this;
- var _editor = new widget.MediaDialog(this.$target.closest('.o_editable'), this.$target[0]);
- _editor.appendTo(document.body);
- _editor.on('saved', this, function (item, old) {
- 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);
- }
- $(item).trigger("content_changed");
- });
- },
- 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);
- }
- }
-});
+ if (self.$target.hasClass(className)) {
+ self.color = className;
+ $color.addClass("selected");
+ }
+ classes.push(className);
+ });
+ this.classes = classes.join(" ");
+
+ this.bind_events();
+ return res;
+ },
+ bind_events: function () {
+ var self = this;
+ var $colors = this.$el.find(".colorpicker button");
+ $colors
+ .mouseenter(function () {
+ self.$target.removeClass(self.classes).addClass('bg-' + $(this).data("color"));
+ })
+ .mouseleave(function () {
+ self.$target.removeClass(self.classes)
+ .addClass('bg-' + $colors.filter(".selected").data("color"));
+ })
+ .click(function () {
+ $colors.removeClass("selected");
+ $(this).addClass("selected");
+ self.$target.closest(".o_editable").trigger("content_changed");
+ });
-var colorpicker = Option.extend({
- start: function () {
- var self = this;
- var res = this._super();
-
- var paletteTemplate = '<div class="colorpicker">'+
- '<div class="note-palette-title">Background Color</div>' +
- '<div class="btn-group palette-reset">' +
- '<div class="note-color-reset" data-event="foreColor"' +
- ' data-value="inherit" title="None"><i class="material-icons">&#xE23B;</i> '+
- '</div>' +
- '</div>' +
-
- '<div class="tabs_container">' +
- '<ul class="tabs_toggles">'+
- '<li class="on"><a href="#" data-tab-target=".palette_theme"><i class="material-icons">&#xE3B7;</i></a></li>' +
- '<li><a href="#" data-tab-target=".palette_grayscale"><i class="material-icons">&#xE3E9;</i></a></li>' +
- '<li><a href="#" data-tab-target=".palette_ui"><i class="material-icons">&#xE41D;</i></a></li>' +
- '<li><a href="#" data-tab-target=".palette_spectrum"><i class="material-icons">&#xE3B8;</i></a></li>' +
- '</ul>' +
- '<div class="tabs">' +
- '<div class="tab palette_theme on"/>'+
- '<div class="tab palette_grayscale"/>'+
- '<div class="tab palette_ui"/>'+
- '<div class="tab palette_spectrum">'+
- '<div class="note-color-palette"></div>' +
- '</div>' +
- '</div>' +
- '</div>' +
-
- '</div></div>';
- var $pt = $(paletteTemplate);
-
- if (!this.$el.find('.colorpicker').length) {
- var $clpicker = $(qweb.render('web_editor.colorpicker'))
- var pTheme = $clpicker.find('.theme')
- var pGray = $clpicker.find('.grayscale')
- var pUi = $clpicker.find('.ui')
- $pt.find('.palette_theme').append(pTheme).end()
- .find('.palette_grayscale').append(pGray).end()
- .find('.palette_ui').append(pUi)
- this.$el.find('li').append($pt);
-
- // ACTIVATE TABS
- this.$el.find('[data-tab-target]').each(function(){
- var $el = $(this);
- var target = $el.data('tab-target');
- var $parent = $el.parent().closest('.tabs_container');
- var $parentLi = $el.parent().closest('li');
-
- $parentLi.on('click', function(){return false});
-
- $el.on('click', function(){
- $parent.find('.tab, .tabs_toggles li').removeClass('on');
- $parent.find(target).add($parentLi).addClass('on')
- return false;
- })
- })
- }
- if (this.$el.data('area')) {
- this.$target = this.$target.find(this.$el.data('area'));
- this.$el.removeData('area').removeAttr('area');
+ this.$el.find('.note-color-reset').on('click', function () {
+ self.$target.removeClass(self.classes);
+ });
}
-
- 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");
+ });
+
+ registry.background = SnippetOption.extend({
+ start: function ($change_target) {
+ this.$target = $change_target || this.$target;
+ this._super();
+ 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);
}
- classes.push(color);
- });
- this.classes = classes.join(" ");
-
- this.bind_events();
- return res;
- },
- bind_events: function () {
- var self = this;
- var $td = this.$el.find(".tab");
- 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($colors.filter(".selected").attr("class"));
- })
- .click(function () {
- $colors.removeClass("selected");
- $(this).addClass("selected");
- self.$target.closest(".o_editable").trigger("content_changed");
+ },
+ background: function (type, value, $li) {
+ if (value && value.length) {
+ this.$target.attr("style", 'background-image: url(' + value + '); ' + (this.$target.attr("style") || '').replace(/background-image:[^;]+/, '') );
+ this.$target.addClass("oe_img_bg");
+ } else {
+ this.$target.css("background-image", "");
+ this.$target.removeClass("oe_img_bg oe_custom_bg");
+ }
+ },
+ select_class : function (type, value, $li) {
+ this.background(type, '', $li);
+ this._super(type, value, $li);
+ },
+ 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.$target);
+
+ var _editor = new widget.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.$target.addClass('oe_custom_bg');
+ self.$target.trigger("snippet-option-change", [self]);
+ self.set_active();
});
- }
-});
+ _editor.on('cancel', self, function () {
+ $image.remove();
+ });
+ },
+ set_active: function () {
+ var self = this;
+ 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);
+ }
-var background_position = Option.extend({
- start: function(){
- var self = this;
- var $btn = self.$overlay.find('.oe_options');
- $btn.on('show.bs.dropdown', function(){
- if (self.$target.css('background-image') == 'none'){
- $btn.find('.background_position_li').addClass('hidden')
+ 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 {
- $btn.find('.background_position_li').removeClass('hidden')
+ this.$el.find('li[data-background=""]:not([data-choose_image])').removeClass("active");
}
- })
- },
- background_position: function(type, value, $li){
- if (type != 'click') return;
- var self = this;
- var $modal = $(qweb.render('web_editor.dialog.background_position'));
- $modal.modal()
- $modal.on('hidden.bs.modal', function(){
- setTimeout(function(){
- $modal.remove()
- },2000)
- })
- self.editing(self, $modal)
- },
- editing: function(self, $modal){
- // Init main collapse
- $modal.find(".panel-collapse.collapse").collapse({
- toggle: false,
- parent: $('#bg_image_opt_accordition')
- })
-
- // Fetch data form $target
- if(self.$target.hasClass('o_bg_img_contain')){
- $modal.find("#bg_size").val('o_bg_img_contain').end()
- .find("#radio2").prop('checked', true).end()
- .find("#collapse_contain").collapse('show');
-
- } else if (self.$target.hasClass('o_bg_img_cover')){
- $modal.find("#bg_size").val('o_bg_img_cover').end()
- .find("#radio1").prop('checked', true).end()
- .find("#collapse_cover").collapse('show');
- } else if (self.$target.hasClass('o_bg_img_custom')){
- $modal.find("#bg_size").val('o_bg_img_custom').end()
- .find("#radio3").prop('checked', true).end()
- .find("#collapse_custom").collapse('show');
- }
- if(self.$target.hasClass("o_bg_img_repeat")){
- $modal.find("#contain_repeat").prop('checked', true);
- $modal.find("#custom_repeat").val('o_bg_img_repeat')
- } else if (self.$target.hasClass("o_bg_img_no_repeat")){
- $modal.find("#custom_repeat").val('o_bg_img_no_repeat')
- } else if (self.$target.hasClass("o_bg_img_repeat_x")){
- $modal.find("#custom_repeat").val('o_bg_img_repeat_x')
- } else if (self.$target.hasClass("o_bg_img_repeat_y")){
- $modal.find("#custom_repeat").val('o_bg_img_repeat_y')
}
+ });
+
+ registry.background_position = SnippetOption.extend({
+ start: function () {
+ var self = this;
+ var $btn = this.$overlay.find('.oe_options');
+ $btn.on('show.bs.dropdown', function () {
+ if (self.$target.css('background-image') === 'none') {
+ $btn.find('.background_position_li').addClass('hidden');
+ } else {
+ $btn.find('.background_position_li').removeClass('hidden');
+ }
+ });
+ },
+ background_position: function (type, value, $li) {
+ if (type != 'click') { return; }
+ var self = this;
+
+ this.previous_state = [this.$target.attr('class'), this.$target.css('background-size'), this.$target.css('background-position')];
+
+ this.bg_pos = self.$target.css('background-position').split(' ');
+ this.bg_siz = self.$target.css('background-size').split(' ');
+
+ this.modal = new Dialog(null, {
+ title: _t("Background Image Options"),
+ $content: $(qweb.render('web_editor.dialog.background_position')),
+ buttons: [
+ {text: _t("Ok"), classes: "btn-primary", close: true, click: _.bind(this.save, this)},
+ {text: _t("Discard"), close: true, click: _.bind(this.discard, this)},
+ ],
+ }).open();
+
+ this.modal.opened().then(function () {
+ // Fetch data form $target
+ var value = ((self.$target.hasClass('o_bg_img_opt_contain'))? 'contain' : ((self.$target.hasClass('o_bg_img_opt_custom'))? 'custom' : 'cover'));
+ self.modal.$("> label > input[value=" + value + "]").prop('checked', true);
+
+ if(self.$target.hasClass("o_bg_img_opt_repeat")) {
+ self.modal.$("#o_bg_img_opt_contain_repeat").prop('checked', true);
+ self.modal.$("#o_bg_img_opt_custom_repeat").val('o_bg_img_opt_repeat');
+ } else if (self.$target.hasClass("o_bg_img_opt_repeat_x")) {
+ self.modal.$("#o_bg_img_opt_custom_repeat").val('o_bg_img_opt_repeat_x');
+ } else if (self.$target.hasClass("o_bg_img_opt_repeat_y")) {
+ self.modal.$("#o_bg_img_opt_custom_repeat").val('o_bg_img_opt_repeat_y');
+ }
- var bg_pos = self.$target.css('background-position').split(' '),
- bg_siz = self.$target.css('background-size').split(' ');
+ if(self.bg_pos.length > 1) {
+ self.bg_pos = {
+ x: self.bg_pos[0],
+ y: self.bg_pos[1],
+ };
+ self.modal.$("#o_bg_img_opt_custom_pos_x").val(self.bg_pos.x.replace('%', ''));
+ self.modal.$("#o_bg_img_opt_custom_pos_y").val(self.bg_pos.y.replace('%', ''));
+ }
+ if(self.bg_siz.length > 1) {
+ self.modal.$("#o_bg_img_opt_custom_size_x").val(self.bg_siz[0].replace('%', ''));
+ self.modal.$("#o_bg_img_opt_custom_size_y").val(self.bg_siz[1].replace('%', ''));
+ }
- if( bg_pos.length > 1 ) {
- $modal.find("#custom_pos_x").val(bg_pos[0].replace('%',''))
- $modal.find("#custom_pos_y").val(bg_pos[1].replace('%',''))
- }
- if( bg_siz.length > 1 ) {
- $modal.find("#custom_size_x").val(bg_siz[0].replace('%',''))
- $modal.find("#custom_size_y").val(bg_siz[1].replace('%',''))
- }
+ // Focus Point
+ self.$focus = self.modal.$(".o_focus_point");
+ self.update_pos_information();
- // Collapse events
- $('#collapse_cover').on('show.bs.collapse', function(){
- $('#radio1').prop('checked', true);
- $modal.find("#bg_size").val('o_bg_img_cover');
- });
-
- $('#collapse_contain').on('show.bs.collapse', function(){
- $('#radio2').prop('checked', true);
- $modal.find("#bg_size").val('o_bg_img_contain');
- });
-
- $('#collapse_custom').on('show.bs.collapse', function(){
- $('#radio3').prop('checked', true);
- $modal.find("#bg_size").val('o_bg_img_custom');
- });
-
- // Focus Point
- var img_url = self.$target.css('background-image').replace(/url\(['"]*|['"]*\)|^none$/g, "");
-
- var $object = $modal.find(".object"),
- $focus = $modal.find(".focus_point");
-
- $modal.find("#pos_x").val(bg_pos[0]).end()
- .find("#pos_y").val(bg_pos[1]).end()
- .find(".ui_info .x").text(bg_pos[0]).end()
- .find(".ui_info .y").text(bg_pos[1])
- $focus.css({
- left: bg_pos[0],
- top: bg_pos[1]
- })
- setTimeout(function(){$focus.addClass("ready") },50)
-
- var $img = $('<img class="img-responsive" src="'+ img_url +'"/>')
- $img.prependTo($object)
- $img.on('load',function(){
- self.retrive_click($img, $focus, $modal, self);
- })
-
- // Save
- $modal.find('.save').on('click',function(){self.save($modal, self) })
- },
- retrive_click: function($img, $focus, $modal, self){
- // Prevent clicks on ui items
- $focus.on('click', function(){$img.mousedown(); })
- $modal.find('.ui_info').on('click', function(){$img.mousedown(); })
- $modal.find('.grid').on('click', function(){$img.mousedown(); })
-
- // Retrive click position
- $img.click(function (e) {
- var posX = e.pageX - $(this).offset().left,
- posY = e.pageY - $(this).offset().top;
- var res = {
- x: (self.range_value(posX/$img.width()*100).toFixed(2)) + '%',
- y: (self.range_value(posY/$img.height()*100).toFixed(2)) + '%'
- };
- $focus.css({top: res.y, left: res.x })
-
- $modal.find("#pos_x").val(res.x).end()
- .find("#pos_y").val(res.y).end()
- .find(".ui_info .x").text(res.x).end()
- .find(".ui_info .y").text(res.y).end()
- .find(".ui_info").hide()
-
- setTimeout(function(){$modal.find(".ui_info").show() },50)
- });
- },
- range_value: function(value){
- if (value < 0) value = 0;
- if (value > 100) value = 100;
- return (value)
- },
- save: function($modal, self){
- self.clean(self.$target);
- self.$target.addClass($modal.find("#bg_size").val());
- switch ($modal.find("#bg_size").val()) {
- case "o_bg_img_cover":
- self.$target.css('background-position', $modal.find("#pos_x").val() + ' ' +$modal.find("#pos_y").val())
- break;
- case "o_bg_img_contain":
- if ($modal.find("#contain_repeat").is(":checked")){
- self.$target.addClass('o_bg_img_repeat')
- } else {
- self.$target.addClass('o_bg_img_no_repeat')
- }
- break;
- case "o_bg_img_custom":
- self.$target.addClass($modal.find("#custom_repeat").val());
- self.$target.css('background-size', $modal.find("#custom_size_x").val() + '% ' + $modal.find("#custom_size_y").val() + '%');
- self.$target.css('background-position', $modal.find("#custom_pos_x").val() + '% ' + $modal.find("#custom_pos_y").val() + '%');
- break;
- }
- },
- clean: function($target){
- $target.removeClass('o_bg_img_cover o_bg_img_contain o_bg_img_custom o_bg_img_repeat o_bg_img_repeat_x o_bg_img_repeat_y o_bg_img_no_repeat')
- .css('background-size', '')
- .css('background-position', '');
- },
-});
+ var img_url = /\(['"]?([^'"]+)['"]?\)/g.exec(self.$target.css('background-image'));
+ img_url = (img_url && img_url[1]) || '';
+ var $img = $('<img/>', {'class': 'img img-responsive', src: img_url});
+ $img.on('load', function () {
+ self.bind_img_events($img);
+ });
+ $img.prependTo(self.modal.$(".o_bg_img_opt_object"));
-var background = Option.extend({
- start: function ($change_target) {
- this.$target = $change_target || this.$target;
- this._super();
- 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.$target.attr("style", 'background-image: url(' + value + '); ' + (this.$target.attr("style") || '').replace(/background-image:[^;]+/, '') );
- this.$target.addClass("oe_img_bg");
- } else {
- this.$target.css("background-image", "");
- this.$target.removeClass("oe_img_bg").removeClass("oe_custom_bg");
- }
- },
- select_class : function(type, value, $li) {
- this.background(type, '', $li);
- this._super(type, value, $li);
- },
- 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.$target);
-
- var _editor = new widget.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.$target.addClass('oe_custom_bg');
- self.$target.trigger("snippet-option-change", [self]);
- self.set_active();
- });
- _editor.on('cancel', self, function () {
- $image.remove();
- });
- },
- set_active: function () {
- var self = this;
- 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);
- }
+ // Bind events
+ self.modal.$el.on('change', '> label > input', function (e) {
+ self.modal.$('> .o_bg_img_opt').addClass('o_hidden')
+ .filter("[data-value=" + e.target.value + "]")
+ .removeClass('o_hidden');
+ });
+ self.modal.$el.on('change', 'input, select', function (e) {
+ self.save();
+ });
+ self.modal.$("> label > input:checked").trigger('change');
+ });
+ },
+ bind_img_events: function ($img) {
+ var self = this;
- 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");
+ var mousedown = false;
+ $img.on('mousedown', function (e) {
+ mousedown = true;
+ });
+ $img.on('mousemove', function (e) {
+ if (mousedown) {
+ _update(e);
}
});
+ $img.on('mouseup', function (e) {
+ self.$focus.addClass('o_with_transition');
+ _update(e);
+ setTimeout(function () {
+ self.$focus.removeClass('o_with_transition');
+ }, 200);
+ mousedown = false;
+ });
- 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");
- }
- }
-});
+ function _update(e) {
+ var posX = e.pageX - $(e.target).offset().left;
+ var posY = e.pageY - $(e.target).offset().top;
+ self.bg_pos = {
+ x: clip_value(posX/$img.width()*100).toFixed(2) + '%',
+ y: clip_value(posY/$img.height()*100).toFixed(2) + '%',
+ };
+ self.update_pos_information();
+ self.save();
+ }
+
+ function clip_value(value) {
+ return Math.max(0, Math.min(value, 100));
+ }
+ },
+ update_pos_information: function () {
+ this.modal.$(".o_bg_img_opt_ui_info .o_x").text(this.bg_pos.x);
+ this.modal.$(".o_bg_img_opt_ui_info .o_y").text(this.bg_pos.y);
+ this.$focus.css({
+ left: this.bg_pos.x,
+ top: this.bg_pos.y,
+ });
+ },
+ save: function () {
+ this.clean();
+
+ var bg_img_size = this.modal.$('> :not(label):not(.o_hidden)').data('value') || 'cover';
+ switch (bg_img_size) {
+ case "cover":
+ this.$target.css('background-position', this.bg_pos.x + ' ' + this.bg_pos.y);
+ break;
+ case "contain":
+ this.$target.addClass('o_bg_img_opt_contain');
+ this.$target.toggleClass('o_bg_img_opt_repeat', this.modal.$("#o_bg_img_opt_contain_repeat").prop("checked"));
+ break;
+ case "custom":
+ this.$target.addClass('o_bg_img_opt_custom');
+ var sizeX = this.modal.$("#o_bg_img_opt_custom_size_x").val();
+ var sizeY = this.modal.$("#o_bg_img_opt_custom_size_y").val();
+ var posX = this.modal.$("#o_bg_img_opt_custom_pos_x").val();
+ var posY = this.modal.$("#o_bg_img_opt_custom_pos_y").val();
+ this.$target.addClass(this.modal.$("#o_bg_img_opt_custom_repeat").val())
+ .css({
+ 'background-size': ((sizeX)? sizeX + '%' : 'auto') + " " + ((sizeY)? sizeY + '%' : 'auto'),
+ 'background-position': ((posX)? posX + '%' : 'auto') + " " + ((posY)? posY + '%' : 'auto'),
+ });
+ break;
+ }
+ },
+ discard: function () {
+ this.clean();
+ if (this.previous_state) {
+ this.$target.addClass(this.previous_state[0]).css({
+ 'background-size': this.previous_state[1],
+ 'background-position': this.previous_state[2],
+ });
+ }
+ },
+ clean: function () {
+ this.$target.removeClass('o_bg_img_opt_contain o_bg_img_opt_custom o_bg_img_opt_repeat o_bg_img_opt_repeat_x o_bg_img_opt_repeat_y')
+ .css({
+ 'background-size': '',
+ 'background-position': '',
+ });
+ },
+ });
-/* t-field options */
+ /* t-field options */
-var many2one = Option.extend({
- start: function () {
- var self = this;
+ registry.many2one = SnippetOption.extend({
+ start: function () {
+ var self = this;
- this.Model = this.$target.data('oe-many2one-model');
- this.ID = +this.$target.data('oe-many2one-id');
+ 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 = $(qweb.render("web_editor.many2one.button"))
- .insertAfter(this.$overlay.find('.oe_options'));
+ // create search button and bind search bar
+ this.$btn = $(qweb.render("web_editor.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();
+ });
- 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 (e) {
+ self.clear();
+ });
+ }
+ },0);
- // 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'
+ // bind search input
+ this.$search.find('input')
+ .focus()
+ .on('keyup', function (e) {
+ self.find_existing($(this).val());
});
+
+ // bind result
+ this.$ul.on('click', "li:not(:first) a", function (e) {
+ 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 {
- self.$btn.find('a').on('click', function (e) {
- self.clear();
- });
+ domain.push(['id', '=', name]);
}
- },0);
- // bind search input
- this.$search.find('input')
- .focus()
- .on('keyup', function(e) {
- self.find_existing($(this).val());
+ 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: base.get_context(),
+ }
+ }).then(function (result) {
+ self.$search.siblings().remove();
+ self.$search.after(qweb.render("web_editor.many2one.search",{contacts:result}));
+ });
+ },
+
+ get_contact_rendering: function (options) {
+ return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
+ model: 'ir.qweb.field.contact',
+ method: 'get_record_to_html',
+ args: [[this.ID]],
+ kwargs: {
+ options: options,
+ context: base.get_context(),
+ }
});
+ },
- // bind result
- this.$ul.on('click', "li:not(:first) a", function (e) {
- 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]);
+ select_record: function (li) {
+ var self = this;
+
+ this.ID = +$(li).data("id");
+ this.$target.attr('data-oe-many2one-id', this.ID).data('oe-many2one-id', this.ID);
+
+ this.buildingBlock.parent.rte.historyRecordUndo(this.$target);
+ this.$target.trigger('content_changed');
+
+ 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 {
- domain.push('|', ['name', 'ilike', name], ['email', 'ilike', name]);
+ self.$target.html($(li).data("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: base.get_context(),
- }
- }).then(function (result){
- self.$search.siblings().remove();
- self.$search.after(qweb.render("web_editor.many2one.search",{contacts:result}));
- });
- },
-
- get_contact_rendering: function (options) {
- return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
- model: 'ir.qweb.field.contact',
- method: 'get_record_to_html',
- args: [[this.ID]],
- kwargs: {
- options: options,
- context: base.get_context(),
- }
- });
- },
-
- select_record: function (li) {
- var self = this;
-
- this.ID = +$(li).data("id");
- this.$target.attr('data-oe-many2one-id', this.ID).data('oe-many2one-id', this.ID);
-
- this.buildingBlock.parent.rte.historyRecordUndo(this.$target);
- this.$target.trigger('content_changed');
-
- 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"));
+ setTimeout(function () {
+ self.buildingBlock.make_active(false);
+ },0);
}
+ });
- setTimeout(function () {
- self.buildingBlock.make_active(false);
- },0);
- }
-});
-
-/* end*/
-
-return {
- 'registry': {
- 'media': media,
- 'colorpicker': colorpicker,
- 'background_position': background_position,
- 'background': background,
- 'many2one': many2one,
- },
- 'Class': Option
-};
-
+ return {
+ registry: registry,
+ Class: SnippetOption,
+ };
});
diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js
index 775c4398268..5c9e86dc8df 100644
--- a/addons/web_editor/static/src/js/summernote.js
+++ b/addons/web_editor/static/src/js/summernote.js
@@ -977,7 +977,7 @@ $.summernote.pluginEvents.tab = function (event, editor, layoutInfo, outdent) {
$.summernote.pluginEvents.indent(event, editor, layoutInfo);
}
} else {
- if (!outdent){
+ if (!outdent) {
if(dom.isText(r.sc)) {
var next = r.sc.splitText(r.so);
} else {
@@ -1876,11 +1876,11 @@ eventHandler.modules.toolbar.button.updateRecentColor = function (elBtn, sEvent,
font.style.color = sValue !== 'inherit' ? sValue : "";
}
} else {
- font.className = font.className.replace(/(^|\s+)bg-\S+/, '');
if (sValue.indexOf('bg-') !== -1) {
font.className += ' ' + sValue;
font.style.backgroundColor = "";
} else {
+ font.className = font.className.replace(/(^|\s+)bg-\S+/, '');
font.style.backgroundColor = sValue !== 'inherit' ? sValue : "";
}
}
@@ -1905,7 +1905,7 @@ eventHandler.modules.editor.redo = function ($popover) {
// use image toolbar if current range is on image
var fn_editor_currentstyle = eventHandler.modules.editor.currentStyle;
-eventHandler.modules.editor.currentStyle = function(target) {
+eventHandler.modules.editor.currentStyle = function (target) {
var styleInfo = fn_editor_currentstyle.apply(this, arguments);
// with our changes for inline editor, the targeted element could be a button of the editor
if(!styleInfo.image || !dom.isEditable(styleInfo.image)) {
diff --git a/addons/web_editor/static/src/js/translator.js b/addons/web_editor/static/src/js/translator.js
index 39efbe1db2f..6932d5f9ed2 100644
--- a/addons/web_editor/static/src/js/translator.js
+++ b/addons/web_editor/static/src/js/translator.js
@@ -116,7 +116,6 @@ var Translate = Widget.extend({
},
start: function () {
this._super();
- this.$('button[data-action=save]').prop('disabled', true);
return this.edit();
},
setTarget: function ($target) {
@@ -158,7 +157,7 @@ var Translate = Widget.extend({
},
edit: function () {
var flag = false;
- window.onbeforeunload = function(event) {
+ window.onbeforeunload = function (event) {
if ($('.o_editable.o_dirty').length && !flag) {
flag = true;
setTimeout(function () {flag=false;},0);
@@ -179,7 +178,6 @@ var Translate = Widget.extend({
var $node = $(node);
var trans = this.getTranlationObject($node[0]);
$node.toggleClass('o_dirty', trans.value !== $node.html().replace(/[ \t\n\r]+/, ' '));
- this.$('button[data-action=save]').prop('disabled', !$('.o_editable.o_dirty').length);
},
getTranlationObject: function (node) {
var $node = $(node);
diff --git a/addons/web_editor/static/src/js/widgets.js b/addons/web_editor/static/src/js/widgets.js
index 165f0b0e914..8db4c66180c 100644
--- a/addons/web_editor/static/src/js/widgets.js
+++ b/addons/web_editor/static/src/js/widgets.js
@@ -39,8 +39,8 @@ var Dialog = Widget.extend({
close: function () {
this.$el.modal('hide');
},
- stop_escape: function(event) {
- if($(".modal.in").length>0 && event.which == 27){
+ stop_escape: function (event) {
+ if($(".modal.in").length>0 && event.which == 27) {
event.stopPropagation();
}
}
@@ -72,7 +72,7 @@ var alt = Dialog.extend({
},
});
-var click_event = function(el, type) {
+var click_event = function (el, type) {
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, el);
el.dispatchEvent(evt);
@@ -239,14 +239,14 @@ var ImageDialog = Widget.extend({
},
'click button.filepicker': function () {
var filepicker = this.$('input[type=file]');
- if (!_.isEmpty(filepicker)){
+ if (!_.isEmpty(filepicker)) {
filepicker[0].click();
}
},
'click .js_disable_optimization': function () {
this.$('input[name="disable_optimization"]').val('1');
var filepicker = this.$('button.filepicker');
- if (!_.isEmpty(filepicker)){
+ if (!_.isEmpty(filepicker)) {
filepicker[0].click();
}
},
@@ -256,8 +256,8 @@ var ImageDialog = Widget.extend({
'keyup input.url': "change_input",
//'change select.image-style': 'preview_image',
'click .existing-attachments [data-src]': 'select_existing',
- 'click .existing-attachment-remove': 'try_remove',
- 'keydown.dismiss.bs.modal': function(){},
+ 'click .o_existing_attachment_remove': 'try_remove',
+ 'keydown.dismiss.bs.modal': function () {},
}),
init: function (parent, media, options) {
this._super();
@@ -417,7 +417,7 @@ var ImageDialog = Widget.extend({
this.$('button.filepicker').removeClass('btn-danger btn-success');
this.$('form').submit();
},
- file_selected: function(attachment, error) {
+ file_selected: function (attachment, error) {
var $button = this.$('button.filepicker');
if (!error) {
$button.addClass('btn-success');
@@ -497,14 +497,14 @@ var ImageDialog = Widget.extend({
},
selected_existing: function () {
var self = this;
- this.$('.existing-attachment-cell.media_selected').removeClass("media_selected");
- var $select = this.$('.existing-attachment-cell [data-src]').filter(function () {
+ this.$('.o_existing_attachment_cell.o_selected').removeClass("o_selected");
+ var $select = this.$('.o_existing_attachment_cell [data-src]').filter(function () {
var $img = $(this);
return !!_.find(self.images, function (v) {
return (v.url === $img.data("src") || ($img.data("url") && v.url === $img.data("url")) || v.id === $img.data("id"));
});
});
- $select.closest('.existing-attachment-cell').addClass("media_selected");
+ $select.closest('.o_existing_attachment_cell').addClass("o_selected");
return $select;
},
try_remove: function (e) {
@@ -535,7 +535,7 @@ var ImageDialog = Widget.extend({
var cacheCssSelectors = {};
-var getCssSelectors = function(filter) {
+var getCssSelectors = function (filter) {
var css = [];
if (cacheCssSelectors[filter]) {
return cacheCssSelectors[filter];
@@ -580,7 +580,7 @@ var getCssSelectors = function(filter) {
}
return cacheCssSelectors[filter] = css;
};
-var computeFonts = _.once(function() {
+var computeFonts = _.once(function () {
_.each(fontIcons, function (data) {
data.cssData = getCssSelectors(data.parser);
data.alias = [];
@@ -628,14 +628,14 @@ var fontIconsDialog = Widget.extend({
e.stopPropagation();
this.$('#fa-icon').val(e.target.getAttribute('data-id'));
- $(".font-icons-icon").removeClass("font-icons-selected");
- $(e.target).addClass("font-icons-selected");
+ $(".font-icons-icon").removeClass("o_selected");
+ $(e.target).addClass("o_selected");
},
- 'keydown.dismiss.bs.modal': function(){},
+ 'keydown.dismiss.bs.modal': function () {},
}),
// extract list of font (like awsome) from the cheatsheet.
- renderElement: function() {
+ renderElement: function () {
this.iconsParser = fontIcons;
this.icons = _.flatten(_.map(fontIcons, function (data) {
return data.icons;
@@ -750,7 +750,7 @@ var fontIconsDialog = Widget.extend({
continue;
case '': continue;
default:
- $(".font-icons-icon").removeClass("font-icons-selected").filter("[data-alias*=',"+cls+",']").addClass("font-icons-selected");
+ $(".font-icons-icon").removeClass("o_selected").filter("[data-alias*=',"+cls+",']").addClass("o_selected");
for (var k=0; k<this.icons.length; k++) {
if (this.icons.indexOf(cls) !== -1) {
this.$('#fa-icon').val(cls);
@@ -852,7 +852,7 @@ var VideoDialog = Widget.extend({
'keyup input#urlvideo': 'change_input',
'change input#embedvideo': 'change_input',
'keyup input#embedvideo': 'change_input',
- 'keydown.dismiss.bs.modal': function(){},
+ 'keydown.dismiss.bs.modal': function () {},
}),
init: function (parent, media) {
this._super();