summaryrefslogtreecommitdiff
path: root/addons/web_editor/static/src/js/snippets.editor.js
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2016-05-18 18:02:51 +0200
committerqsm-odoo <qsm@odoo.com>2016-07-04 17:23:59 +0200
commit62fb1bb92493b00bd45ed3f4eced5ca8b23f81d6 (patch)
tree911fcb10158fa89ddd75ff2aac195f79236f3e59 /addons/web_editor/static/src/js/snippets.editor.js
parentc1ab17337bdc816222be372aff314fcf5de8ba92 (diff)
[REF] web_editor: code refactoring and simplification
* Remove dead code + optimization * Use Dialog API from web module * Reorganize files * Correct buggy $() function for snippet option class * Add comments * Fix the snippet parent navigation : If a page contained a three level snippet structure (i.e A contains B contains C), when editing the following bug occured : If B or C was selected first, parenting buttons were correctly set. But if selecting A then C, clicking on the parent lead to going back on A instead of going on B. * Fix snippet thumbnail layout * Better isolate ui css from themes * MediaDialog image list : prevent displaying empty attachments * ...
Diffstat (limited to 'addons/web_editor/static/src/js/snippets.editor.js')
-rw-r--r--addons/web_editor/static/src/js/snippets.editor.js274
1 files changed, 131 insertions, 143 deletions
diff --git a/addons/web_editor/static/src/js/snippets.editor.js b/addons/web_editor/static/src/js/snippets.editor.js
index ca8819bff50..1bfab9d3dc2 100644
--- a/addons/web_editor/static/src/js/snippets.editor.js
+++ b/addons/web_editor/static/src/js/snippets.editor.js
@@ -5,80 +5,42 @@ var Class = require('web.Class');
var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
-var base = require('web_editor.base');
var editor = require('web_editor.editor');
var animation = require('web_editor.snippets.animation');
var options = require('web_editor.snippets.options');
var qweb = core.qweb;
-var dummy = editor.dummy;
-
-/* ----- SNIPPET SELECTOR ---- */
ajax.loadXML('/web_editor/static/src/xml/snippets.xml', qweb);
-editor.Class.include({
- init: function () {
- var self = this;
- var res = this._super.apply(this, arguments);
- var $editable = this.rte.editable();
- this.buildingBlock = new BuildingBlock(this, $editable);
- this.buildingBlock.on("snippets:ready", this, function () {
- self.trigger("snippets:ready");
- });
- return res;
- },
- start: function () {
- var self = this;
- animation.stop();
- this.buildingBlock.insertAfter(this.$el);
- animation.start(true);
-
- this.rte.editable().find("*").off('mousedown mouseup click');
- return this._super();
- },
- save: function () {
- this.buildingBlock.clean_for_save();
- return this._super.apply(this, arguments);
- },
-});
+var data = {};
/* ----- SNIPPET SELECTOR ---- */
-$.extend($.expr[':'],{
- hasData: function (node,i,m) {
+$.extend($.expr[':'], {
+ hasData: function (node) {
return !!_.toArray(node.dataset).length;
},
- data: function (node,i,m) {
+ data: function (node, i, m) {
return $(node).data(m[3]);
}
});
-var globalSelector = {
+data.globalSelector = {
closest: function () { return $(); },
all: function () { return $(); },
is: function () { return false; },
};
-/* ----- Jquery activate block ---- */
-
-$.fn.extend({
- activateBlock: function () {
- var target = globalSelector.closest($(this))[0] || (dom.isBR(this) ? this.parentNode : dom.node(this));
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, target);
- target.dispatchEvent(evt);
- return this;
- }
-});
-
-/* ----- BuildingBlock (managment of drag&drop and focus/blur snippets) ---- */
-
-var BuildingBlock = Widget.extend({
+/**
+ * Snippet editor main class.
+ * Management of drag&drop and focus/blur of snippets.
+ * Previously named "BuildingBlock".
+ */
+data.Class = Widget.extend({
id: "oe_snippets",
activeSnippets: [],
init: function (parent, $editable) {
- this.parent = parent;
this.$editable = $editable;
this._super.apply(this, arguments);
@@ -87,14 +49,14 @@ var BuildingBlock = Widget.extend({
}
this.$active_snipped_id = false;
this.snippets = [];
-
+
data.instance = this;
},
start: function () {
var self = this;
$(window).resize(function () {
- setTimeout('$(document).click()',0);
+ _.defer(function () { $(document).click(); });
});
this.fetch_snippet_templates();
@@ -106,7 +68,7 @@ var BuildingBlock = Widget.extend({
var _isNotBreakable = $.summernote.core.dom.isNotBreakable;
$.summernote.core.dom.isNotBreakable = function (node) {
- return _isNotBreakable(node) || $(node).is('div') || globalSelector.is($(node));
+ return _isNotBreakable(node) || $(node).is('div') || data.globalSelector.is($(node));
};
$(window).on('resize', function () {
@@ -136,7 +98,7 @@ var BuildingBlock = Widget.extend({
},
_add_check_selector : function (selector, no_check, is_children) {
var self = this;
- var selector = selector.split(/\s*,/).join(":not(.o_snippet_not_selectable), ") + ":not(.o_snippet_not_selectable)";
+ selector = selector.split(/\s*,/).join(":not(.o_snippet_not_selectable), ") + ":not(.o_snippet_not_selectable)";
if (no_check) {
return {
@@ -151,7 +113,7 @@ var BuildingBlock = Widget.extend({
}
};
} else {
- var selector = selector.split(/\s*,/).join(":o_editable, ") + ":o_editable";
+ selector = selector.split(/\s*,/).join(":o_editable, ") + ":o_editable";
return {
closest: function ($from, parentNode) {
var parents = self.$editable.get();
@@ -203,14 +165,14 @@ var BuildingBlock = Widget.extend({
}
$ul.children().tooltip({
- delay: { "show": 500, "hide": 100 },
- container: 'body',
- title: function () {
- return (navigator.appVersion.indexOf('Mac') > -1 ? 'CMD' : 'CTRL')+'+SHIFT+'+($(this).index()+1);
- },
- trigger: 'hover',
- placement: 'top'
- }).on('click', function () {$(this).tooltip('hide');});
+ delay: { "show": 500, "hide": 100 },
+ container: 'body',
+ title: function () {
+ return (navigator.appVersion.indexOf('Mac') > -1 ? 'CMD' : 'CTRL')+'+SHIFT+'+($(this).index()+1);
+ },
+ trigger: 'hover',
+ placement: 'top'
+ }).on('click', function () {$(this).tooltip('hide');});
// t-snippet
$html.find('[data-oe-type="snippet"]').each(function () {
@@ -239,35 +201,35 @@ var BuildingBlock = Widget.extend({
});
$styles.addClass("hidden");
- 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;
- }
+ data.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;
+ }
+ return $target;
};
- globalSelector.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;
+ data.globalSelector.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;
};
- globalSelector.is = function ($from) {
- var len = selector.length;
- for (var i = 0; i<len; i++) {
- if (selector[i].is($from)) {
- return true;
- }
+ data.globalSelector.is = function ($from) {
+ var len = selector.length;
+ for (var i = 0; i<len; i++) {
+ if (selector[i].is($from)) {
+ return true;
}
- return false;
+ }
+ return false;
};
var number = 0;
@@ -364,7 +326,6 @@ var BuildingBlock = Widget.extend({
}
var pos = $target.offset();
var mt = parseInt($target.css("margin-top") || 0);
- var mb = parseInt($target.css("margin-bottom") || 0);
$el.css({
width: $target.outerWidth(),
left: pos.left,
@@ -432,8 +393,8 @@ var BuildingBlock = Widget.extend({
return;
}
- if (!globalSelector.is($target)) {
- $target = globalSelector.closest($target);
+ if (!data.globalSelector.is($target)) {
+ $target = data.globalSelector.closest($target);
}
if (self.$active_snipped_id && self.$active_snipped_id.is($target)) {
@@ -462,14 +423,14 @@ var BuildingBlock = Widget.extend({
var template = self.templateOptions;
for (var k in template) {
var Option = opt[template[k]['option']];
- if (Option && Option.prototype.clean_for_save !== dummy) {
+ if (Option && Option.prototype.clean_for_save !== editor.dummy) {
template[k].selector.all().filter(function () {
- var node = this;
- while (!/o_dirty|o_editable/.test(node.className) && node !== document) {
- node = node.parentNode;
- }
- return node.className.indexOf("o_dirty") !== -1;
- }).each(function () {
+ var node = this;
+ while (!/o_dirty|o_editable/.test(node.className) && node !== document) {
+ node = node.parentNode;
+ }
+ return node.className.indexOf("o_dirty") !== -1;
+ }).each(function () {
new Option(self, null, $(this), k).clean_for_save();
});
}
@@ -505,7 +466,7 @@ var BuildingBlock = Widget.extend({
create_snippet_editor: function ($snippet) {
if (typeof $snippet.data("snippet-editor") === 'undefined') {
if (!this.activate_overlay_zones($snippet).length) return;
- $snippet.data("snippet-editor", new Editor(this, $snippet));
+ $snippet.data("snippet-editor", new data.Editor(this, $snippet));
}
},
@@ -515,7 +476,7 @@ var BuildingBlock = Widget.extend({
var $tumb = $snippets.find(".oe_snippet_thumbnail_img:first");
var left = $tumb.outerWidth()/2;
var top = $tumb.outerHeight()/2;
- var $toInsert, dropped, $snippet, action, snipped_id;
+ var $toInsert, dropped, $snippet;
$snippets.draggable({
greedy: true,
@@ -535,7 +496,6 @@ var BuildingBlock = Widget.extend({
var $base_body = $snippet.find('.oe_snippet_body');
var $selector_siblings = $();
var $selector_children = $();
- var vertical = false;
var temp = self.templateOptions;
for (var k in temp) {
if ($base_body.is(temp[k].base_selector)) {
@@ -553,7 +513,7 @@ var BuildingBlock = Widget.extend({
$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");
+ console.warn($snippet.find(".oe_snippet_thumbnail_title").text() + " have not insert action: data-drop-near or data-drop-in");
return;
}
@@ -577,7 +537,7 @@ var BuildingBlock = Widget.extend({
},
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) {
@@ -587,12 +547,12 @@ var BuildingBlock = Widget.extend({
}
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;
+ var rte = self.getParent().rte;
if (prev) {
$toInsert.detach();
@@ -638,7 +598,7 @@ var BuildingBlock = Widget.extend({
// call a method on a snippet and all his children
call_for_all_snippets: function ($snippet, callback) {
var self = this;
- $snippet.add(globalSelector.all($snippet)).each(function () {
+ $snippet.add(data.globalSelector.all($snippet)).each(function () {
var $snippet = $(this);
setTimeout(function () {
self.create_snippet_editor($snippet);
@@ -652,8 +612,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 () {
- return $(this).data('option') === id;
- }).first();
+ return $(this).data('option') === id;
+ }).first();
},
// Create element insertion drop zones. two css selectors can be provided
@@ -677,10 +637,10 @@ var BuildingBlock = Widget.extend({
var test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR"));
if (test) {
$drop.addClass("oe_vertical").css({
- 'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
- 'float': 'none',
- 'display': 'inline-block'
- });
+ '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));
}
@@ -688,14 +648,14 @@ var BuildingBlock = Widget.extend({
$drop = $drop.clone();
$zone.prepend($drop);
- var node = $drop[0].nextSibling;
- var test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR"));
+ node = $drop[0].nextSibling;
+ test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR"));
if (test) {
$drop.addClass("oe_vertical").css({
- 'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
- 'float': 'none',
- 'display': 'inline-block'
- });
+ '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));
}
@@ -816,8 +776,8 @@ var BuildingBlock = Widget.extend({
if ($target.data('overlay') && $target.data('overlay').hasClass("oe_active")) {
self.cover_target($target.data('overlay'), $target);
}
- },50);
- });
+ }, 50);
+ });
var resize = function () {
if ($zone.parent().length) {
@@ -834,9 +794,11 @@ var BuildingBlock = Widget.extend({
}
});
-/* ----- Editor (object who contain overlay and the option list) ---- */
-
-var Editor = Class.extend({
+/**
+ * Snippet editor Editor class.
+ * Management of the overlay and option list for a snippet.
+ */
+data.Editor = Class.extend({
init: function (BuildingBlock, dom) {
this.buildingBlock = BuildingBlock;
this.$target = $(dom);
@@ -874,12 +836,12 @@ var Editor = Class.extend({
_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;
@@ -898,12 +860,12 @@ var Editor = Class.extend({
self.$overlay.addClass("hidden");
var $selector_siblings;
- for (var i=0; i<self.selector_siblings.length; i++) {
+ 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 (var i=0; i<self.selector_children.length; i++) {
+ 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());
}
@@ -931,7 +893,7 @@ var Editor = Class.extend({
$(".oe_drop_clone, .oe_drop_to_remove").remove();
if (this.dropped) {
- this.buildingBlock.parent.rte.historyRecordUndo(this.$target);
+ this.buildingBlock.getParent().rte.historyRecordUndo(this.$target);
if (prev) {
this.$target.insertAfter(prev);
@@ -961,6 +923,7 @@ var Editor = Class.extend({
this.styles = {};
this.selector_siblings = [];
this.selector_children = [];
+
_.each(this.buildingBlock.templateOptions, function (val, option_id) {
if (!val.selector.is(self.$target)) {
return;
@@ -979,7 +942,7 @@ var Editor = Class.extend({
this.$overlay.find(".oe_snippet_move, .oe_snippet_clone, .oe_snippet_remove").addClass('hidden');
}
- if ($ul.find("li").length) {
+ if ($ul.children().length) {
$styles.removeClass("hidden");
}
this.$overlay.find('[data-toggle="dropdown"]').dropdown();
@@ -988,10 +951,7 @@ var Editor = Class.extend({
get_parent_block: function () {
var self = this;
var $button = this.$overlay.find('.oe_snippet_parent');
- var $parent = this.$target.parents().filter(function () { return $(this).data("snippet-editor"); });
- if (!$parent.length) {
- $parent = globalSelector.closest(this.$target.parent());
- }
+ var $parent = data.globalSelector.closest(this.$target.parent());
if ($parent.length) {
$button.removeClass("hidden");
$button.off("click").on('click', function (event) {
@@ -1010,7 +970,6 @@ var Editor = Class.extend({
* This method is called after init and _readXMLData
*/
start: function () {
- var self = this;
if (!this.$target.parent().is(':o_editable')) {
this.$overlay.find('.oe_snippet_move, .oe_snippet_clone, .oe_snippet_remove').remove();
} else {
@@ -1024,7 +983,7 @@ var Editor = Class.extend({
event.preventDefault();
var $clone = this.$target.clone(false);
- this.buildingBlock.parent.rte.historyRecordUndo(this.$target);
+ this.buildingBlock.getParent().rte.historyRecordUndo(this.$target);
this.$target.after($clone);
this.buildingBlock.call_for_all_snippets($clone, function (editor, $snippet) {
@@ -1039,7 +998,7 @@ var Editor = Class.extend({
event.preventDefault();
this.on_blur();
- this.buildingBlock.parent.rte.historyRecordUndo(this.$target);
+ this.buildingBlock.getParent().rte.historyRecordUndo(this.$target);
var index = _.indexOf(this.buildingBlock.snippets, this.$target.get(0));
this.buildingBlock.call_for_all_snippets(this.$target, function (editor, $snippet) {
@@ -1049,8 +1008,6 @@ var Editor = Class.extend({
});
delete this.buildingBlock.snippets[index];
- var $editable = this.$target.closest(".o_editable");
-
// remove node and his empty
var node = this.$target.parent()[0];
@@ -1103,11 +1060,42 @@ var Editor = Class.extend({
},
});
-var data = {
- Class: BuildingBlock,
- Editor: Editor,
- globalSelector: globalSelector,
-};
-return data;
+/**
+ * Add the ability on the main editor class to instantiate the snippet editor component
+ */
+editor.Class.include({
+ init: function () {
+ var self = this;
+ var res = this._super.apply(this, arguments);
+ var $editable = this.rte.editable();
+ this.buildingBlock = new data.Class(this, $editable);
+ this.buildingBlock.on("snippets:ready", this, function () {
+ self.trigger("snippets:ready");
+ });
+ return res;
+ },
+ start: function () {
+ this.buildingBlock.insertAfter(this.$el);
+ this.rte.editable().find("*").off('mousedown mouseup click');
+ return this._super.apply(this, arguments);
+ },
+ save: function () {
+ this.buildingBlock.clean_for_save();
+ return this._super.apply(this, arguments);
+ },
+});
+
+/**
+ * Add the ability the restart the animations
+ */
+editor.Class.include({
+ start: function () {
+ animation.stop();
+ return this._super.apply(this, arguments).then(function () {
+ animation.start(true);
+ });
+ },
+});
+return data;
});