odoo.define('web_editor.snippet.editor', function (require) {
'use strict';
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();
this._super();
},
});
/* ----- SNIPPET SELECTOR ---- */
$.extend($.expr[':'],{
hasData: function(node,i,m){
return !!_.toArray(node.dataset).length;
},
data: function(node,i,m){
return $(node).data(m[3]);
}
});
var 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({
template: 'web_editor.snippets',
activeSnippets: [],
init: function (parent, $editable) {
this.parent = parent;
this.$editable = $editable;
this._super.apply(this, arguments);
if(!$('#oe_manipulators').length){
$("
").appendTo('body');
}
this.$active_snipped_id = false;
this.snippets = [];
data.instance = this;
},
start: function() {
var self = this;
this.$snippet = $("#oe_snippets");
this.$el
.on("mouseenter", function () { self.show(); })
.on("mouseleave", function (event) { if (event.clientX>0 && event.clientY>0) self.hide(); });
$(window).resize(function () {
setTimeout('$(document).click()',0);
});
this.fetch_snippet_templates();
this.bind_snippet_click_editor();
$(document).on('click', '.dropdown-submenu a[tabindex]', function (e) {
e.preventDefault();
});
var _isNotBreakable = $.summernote.core.dom.isNotBreakable;
$.summernote.core.dom.isNotBreakable = function (node) {
return _isNotBreakable(node) || $(node).is('div') || globalSelector.is($(node));
};
$(window).on('resize', function () {
if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) {
self.cover_target(self.$active_snipped_id.data("snippet-editor").$overlay, self.$active_snipped_id);
}
});
$(document).on('mousemove', function () {
if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) {
self.$active_snipped_id.data("snippet-editor").$overlay.removeClass('o_keypress');
}
});
$(document).on('keydown', function (event) {
if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) {
self.$active_snipped_id.data("snippet-editor").$overlay.addClass('o_keypress');
}
if ((event.metaKey || (event.ctrlKey && !event.altKey)) && event.shiftKey && event.keyCode >= 48 && event.keyCode <= 57) {
self.$snippet.find('.scroll:first > ul li:eq('+(event.keyCode-49)+') a').trigger("click");
self.show();
event.preventDefault();
}
});
},
_get_snippet_url: function () {
return '/web_editor/snippets';
},
_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)";
if (no_check) {
return {
closest: function ($from, parentNode) {
return $from.closest(selector, parentNode);
},
all: function ($from) {
return $from ? $from.find(selector) : $(selector);
},
is: function ($from) {
return $from.is(selector);
}
};
} else {
var selector = selector.split(/\s*,/).join(":o_editable, ") + ":o_editable";
return {
closest: function ($from, parentNode) {
var parents = self.$editable.get();
return $from.closest(selector, parentNode).filter(function () {
var node = this;
while (node.parentNode) {
if (parents.indexOf(node)!==-1) {
return true;
}
node = node.parentNode;
}
return false;
});
},
all: is_children ? function ($from) {
return ($from || self.$editable).find(selector);
} : function ($from) {
return $from ? $from.find(selector) : self.$editable.filter(selector).add(self.$editable.find(selector));
},
is: function ($from) {
return $from.is(selector);
}
};
}
},
fetch_snippet_templates: function () {
var self = this;
var url = this._get_snippet_url();
if (!url || !url.length) {
this.$snippet.detach();
return;
}
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");
if (!$scroll.length) {
throw new Error("Wrong snippets xml definition");
}
$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');});
// t-snippet
$html.find('[data-oe-type="snippet"][data-oe-name]').each(function () {
var $div = $('').insertAfter(this).append(this).attr('name', $(this).data('oe-name'));
});
// end
self.templateOptions = [];
var selector = [];
var $styles = $html.find("[data-js], [data-selector]");
$styles.each(function () {
var $style = $(this);
var no_check = $style.data('no-check');
var option_id = $style.data('js');
var option = {
'option' : option_id,
'base_selector': $style.data('selector'),
'selector': self._add_check_selector($style.data('selector'), no_check),
'$el': $style,
'drop-near': $style.data('drop-near') && self._add_check_selector($style.data('drop-near'), no_check, true),
'drop-in': $style.data('drop-in') && self._add_check_selector($style.data('drop-in'), no_check),
'data': $style.data()
};
self.templateOptions.push(option);
selector.push(option.selector);
});
$styles.addClass("hidden");
globalSelector.closest = function ($from) {
var $temp;
var $target;
var len = selector.length;
for (var i = 0; i'+
''+
''+
'');
$div.find('span').text($(this).attr("name"));
$(this).prepend($div);
// from t-snippet
var thumbnail = $("[data-oe-thumbnail]", this).data("oe-thumbnail");
if (thumbnail) {
$div.find('.oe_snippet_thumbnail_img').css('background-image', 'url(' + thumbnail + ')');
}
// end
}
if (!$(this).data("selector")) {
$("> *:not(.oe_snippet_thumbnail)", this).addClass('oe_snippet_body');
}
number++;
});
// hide scroll if no snippets defined
if (!number) {
this.$snippet.detach();
} else {
this.$el.find("#o_left_bar").removeClass("hidden");
}
$("body").toggleClass("editor_has_snippets", !!number);
// select all default text to edit (if snippet default text)
self.$snippets.find('.oe_snippet_body, .oe_snippet_body *')
.contents()
.filter(function() {
return this.nodeType === 3 && this.textContent.match(/\S/);
}).parent().addClass("o_default_snippet_text");
$(document).on("mouseup", ".o_default_snippet_text", function (event) {
$(event.target).selectContent();
});
$(document).on("keyup", function (event) {
var r = $.summernote.core.range.create();
$(r && r.sc).closest(".o_default_snippet_text").removeClass("o_default_snippet_text");
});
// end
// clean t-oe
$html.find('[data-oe-model], [data-oe-type]').each(function () {
for (var k=0; k middle) {
break;
}
last = $li[k];
}
$(last).addClass("active");
});
// end
// display scrollbar
$(window).on('resize', function () {
$scroll.css("overflow", "");
var height = $left_bar.height() - $ul.outerHeight();
$scroll.css("height", height);
var $last = $scroll.children(":visible").last().children(".o_panel_body");
$last.css({'min-height': (height-$last.prev().outerHeight())+'px'});
if ($scroll[0].scrollHeight + $ul[0].scrollHeight > document.body.clientHeight) {
$scroll.css("overflow", "auto").css("width", "226px");
} else {
$scroll.css("width", "");
}
}).trigger('resize');
// end
self.make_snippet_draggable(self.$snippets);
},
cover_target: function ($el, $target){
if($el.data('not-cover_target')) return;
var pos = $target.offset();
var mt = parseInt($target.css("margin-top") || 0);
var mb = parseInt($target.css("margin-bottom") || 0);
var width = $target.outerWidth();
var bigger = pos.left+width > $("body").outerWidth()-8;
$el.css({
'width': width,
'top': pos.top - mt - 5,
'left': pos.left-1
});
$el.find(".oe_handle.e,.oe_handle.w").css({'height': $target.outerHeight() + mt + mb+1});
if (bigger) {
$el.find(".oe_handle.e").css({right: 0, margin: 0})
.find("div").css({right: 0, left: 'auto'});
} else {
$el.find(".oe_handle.e").css({right: "", margin: ""})
.find("div").css({right: "", left: ""});
}
$el.find(".oe_handle.s").css({'top': $target.outerHeight() + mt + mb});
$el.find(".oe_handle.size").css({'top': $target.outerHeight() + mt});
$el.find(".oe_handle.s,.oe_handle.n").css({'width': width-2});
},
show_blocks: function () {
var self = this;
var cache = {};
this.$snippet.find(".o_panel").each(function () {
var catcheck = false;
var $category = $(this);
$category.find(".oe_snippet_body").each(function () {
var $snippet = $(this);
var check = false;
for (var k in self.templateOptions) {
var option = self.templateOptions[k];
if ($snippet.is(option.base_selector)) {
cache[k] = cache[k] || {
'drop-near': option['drop-near'] ? option['drop-near'].all() : [],
'drop-in': option['drop-in'] ? option['drop-in'].all() : []
};
if (cache[k]['drop-near'].length || cache[k]['drop-in'].length) {
catcheck = true;
check = true;
break;
}
}
}
if (check) {
$snippet.closest(".oe_snippet").removeClass("disable");
} else {
$snippet.closest(".oe_snippet").addClass("disable");
}
});
$('#oe_snippets .scroll a[data-toggle="tab"][href="#' + $category.attr("id") + '"]').toggle(catcheck);
});
},
show: function () {
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;
$(document).on('click', '*', function (event) {
var srcElement = event.srcElement || (event.originalEvent && (event.originalEvent.originalTarget || event.originalEvent.target) || event.target);
if (self.editor_busy || snipped_event_flag===srcElement || !srcElement) {
return;
}
snipped_event_flag = srcElement;
setTimeout(function () {snipped_event_flag = false;}, 0);
var $target = $(srcElement);
if ($target.closest(".oe_overlay, .note-popover").length) {
return;
}
if (!globalSelector.is($target)) {
$target = globalSelector.closest($target);
}
if (self.$active_snipped_id && self.$active_snipped_id.is($target)) {
return;
}
self.make_active($target);
});
},
snippet_blur: function ($snippet) {
if ($snippet) {
if ($snippet.data("snippet-editor")) {
$snippet.data("snippet-editor").on_blur();
}
}
},
snippet_focus: function ($snippet) {
if ($snippet) {
if ($snippet.data("snippet-editor")) {
$snippet.data("snippet-editor").on_focus();
}
}
},
clean_for_save: function () {
var self = this;
var opt = options.registry;
var template = self.templateOptions;
for (var k in template) {
var Option = opt[template[k]['option']];
if (Option && Option.prototype.clean_for_save !== 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 () {
new Option(self, null, $(this), k).clean_for_save();
});
}
}
this.$editable.find("*[contentEditable], *[attributeEditable]")
.removeAttr('contentEditable')
.removeProp('contentEditable')
.removeAttr('attributeEditable')
.removeProp('attributeEditable');
},
make_active: function ($snippet) {
if ($snippet && this.$active_snipped_id && this.$active_snipped_id.get(0) === $snippet.get(0)) {
return;
}
if (this.$active_snipped_id) {
this.snippet_blur(this.$active_snipped_id);
this.$active_snipped_id = false;
}
if ($snippet && $snippet.length) {
if(_.indexOf(this.snippets, $snippet.get(0)) === -1) {
this.snippets.push($snippet.get(0));
}
this.$active_snipped_id = $snippet;
this.create_snippet_editor(this.$active_snipped_id);
this.cover_target($snippet.data('overlay'), $snippet);
this.snippet_focus($snippet);
}
this.$snippet.trigger('snippet-activated', $snippet);
if ($snippet) {
$snippet.trigger('snippet-activated', $snippet);
}
},
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));
}
},
// activate drag and drop for the snippets in the snippet toolbar
make_snippet_draggable: function($snippets){
var self = this;
var $tumb = $snippets.find(".oe_snippet_thumbnail_img:first");
var left = $tumb.outerWidth()/2;
var top = $tumb.outerHeight()/2;
var $toInsert, dropped, $snippet, action, snipped_id;
$snippets.draggable({
greedy: true,
helper: 'clone',
zIndex: '1000',
appendTo: 'body',
cursor: "move",
handle: ".oe_snippet_thumbnail",
cursorAt: {
'left': left,
'top': top
},
start: function(){
self.hide();
dropped = false;
// snippet_selectors => to get drop-near, drop-in
$snippet = $(this);
var $base_body = $snippet.find('.oe_snippet_body');
var $selector_siblings = $();
var $selector_children = $();
var vertical = false;
var temp = self.templateOptions;
for (var k in temp) {
if ($base_body.is(temp[k].base_selector)) {
if (temp[k]['drop-near']) {
if (!$selector_siblings) $selector_siblings = temp[k]['drop-near'].all();
else $selector_siblings = $selector_siblings.add(temp[k]['drop-near'].all());
}
if (temp[k]['drop-in']) {
if (!$selector_children) $selector_children = temp[k]['drop-in'].all();
else $selector_children = $selector_children.add(temp[k]['drop-in'].all());
}
}
}
$toInsert = $base_body.clone();
if (!$selector_siblings.length && !$selector_children.length) {
console.debug($snippet.find(".oe_snippet_thumbnail_title").text() + " have not insert action: data-drop-near or data-drop-in");
return;
}
self.activate_insertion_zones($selector_siblings, $selector_children);
$('.oe_drop_zone').droppable({
over: function(){
dropped = true;
$(this).first().after($toInsert);
},
out: function(){
var prev = $toInsert.prev();
if(this === prev[0]){
dropped = false;
$toInsert.detach();
}
}
});
},
stop: function(ev, ui){
$toInsert.removeClass('oe_snippet_body');
if (! dropped && self.$editable.find('.oe_drop_zone') && ui.position.top > 3) {
var el = self.$editable.find('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first();
if (el.length) {
el.after($toInsert);
dropped = true;
}
}
self.$editable.find('.oe_drop_zone').droppable('destroy').remove();
if (dropped) {
var prev = $toInsert.first()[0].previousSibling;
var next = $toInsert.last()[0].nextSibling;
var rte = self.parent.rte;
if (prev) {
$toInsert.detach();
rte.historyRecordUndo($(prev));
$toInsert.insertAfter(prev);
} else if (next) {
$toInsert.detach();
rte.historyRecordUndo($(next));
$toInsert.insertBefore(next);
} else {
var $parent = $toInsert.parent();
$toInsert.detach();
rte.historyRecordUndo($parent);
$parent.prepend($toInsert);
}
$toInsert.closest(".o_editable").trigger("content_changed");
var $target = false;
$target = $toInsert;
setTimeout(function () {
self.$snippet.trigger('snippet-dropped', $target);
animation.start(true, $target);
self.call_for_all_snippets($target, function (editor, $snippet) {
editor.drop_and_build_snippet();
});
self.create_snippet_editor($target);
self.cover_target($target.data('overlay'), $target);
$target.closest(".o_editable").trigger("content_changed");
self.make_active($target);
},0);
} else {
$toInsert.remove();
}
},
});
},
// call a method on a snippet and all his children
call_for_all_snippets: function ($snippet, callback) {
var self = this;
$snippet.add(globalSelector.all($snippet)).each(function () {
var $snippet = $(this);
setTimeout(function () {
self.create_snippet_editor($snippet);
if ($snippet.data("snippet-editor")) {
callback.call(self, $snippet.data("snippet-editor"), $snippet);
}
});
});
},
// return the original snippet in the editor bar from a snippet id (string)
get_snippet_from_id: function(id){
return $('.oe_snippet').filter(function(){
return $(this).data('option') === id;
}).first();
},
// Create element insertion drop zones. two css selectors can be provided
// selector.children -> will insert drop zones as direct child of the selected elements
// in case the selected elements have children themselves, dropzones will be interleaved
// with them.
// selector.siblings -> will insert drop zones after and before selected elements
activate_insertion_zones: function($selector_siblings, $selector_children){
var self = this;
var zone_template = $("");
if ($selector_children) {
$selector_children.each(function (){
var $zone = $(this);
var css = window.getComputedStyle(this);
var float = css.float || css.cssFloat;
var $drop = zone_template.clone();
$zone.append($drop);
var node = $drop[0].previousSibling;
var test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR"));
if (test) {
$drop.addClass("oe_vertical oe_vertical_text").css({
'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
'float': 'none',
'display': 'inline-block'
});
} else if (float === "left" || float === "right") {
$drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.children().last().outerHeight()), 30));
}
$drop = $drop.clone();
$zone.prepend($drop);
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({
'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
'float': 'none',
'display': 'inline-block'
});
} else if (float === "left" || float === "right") {
$drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.children().first().outerHeight()), 30));
}
if (test) {
$drop.css({'float': 'none', 'display': 'inline-block'});
}
});
// add children near drop zone
$selector_siblings = $(_.uniq(($selector_siblings || $()).add($selector_children.children()).get()));
}
if ($selector_siblings) {
$selector_siblings.filter(':not(.oe_drop_zone):not(.oe_drop_clone)').each(function (){
var $zone = $(this);
var $drop;
var css = window.getComputedStyle(this);
var float = css.float || css.cssFloat;
if($zone.prev('.oe_drop_zone:visible').length === 0){
$drop = zone_template.clone();
if (float === "left" || float === "right") {
$drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.prev().outerHeight() || Infinity), 30));
}
$zone.before($drop);
}
if($zone.next('.oe_drop_zone:visible').length === 0){
$drop = zone_template.clone();
if (float === "left" || float === "right") {
$drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.next().outerHeight() || Infinity), 30));
}
$zone.after($drop);
}
});
}
var count;
do {
count = 0;
$zones = self.$editable.find('.oe_drop_zone > .oe_drop_zone').remove(); // no recursive zones
count += $zones.length;
$zones.remove();
} while (count > 0);
// Cleaning consecutive zone and up zones placed between floating or inline elements. We do not like these kind of zones.
var $zones = self.$editable.find('.oe_drop_zone:not(.oe_vertical)');
$zones.each(function (){
var zone = $(this);
var prev = zone.prev();
var next = zone.next();
// remove consecutive zone
if (prev.is('.oe_drop_zone') || next.is('.oe_drop_zone')) {
zone.remove();
return;
}
var float_prev = prev.css('float') || 'none';
var float_next = next.css('float') || 'none';
var disp_prev = prev.css('display') || null;
var disp_next = next.css('display') || null;
if( (float_prev === 'left' || float_prev === 'right')
&& (float_next === 'left' || float_next === 'right') ){
zone.remove();
}else if( !( disp_prev === null
|| disp_next === null
|| disp_prev === 'block'
|| disp_next === 'block' )){
zone.remove();
}
});
},
// generate drop zones covering the elements selected by the selector
// we generate overlay drop zones only to get an idea of where the snippet are, the drop
activate_overlay_zones: function($targets){
var self = this;
function is_visible($el){
return $el.css('display') != 'none'
&& $el.css('opacity') != '0'
&& $el.css('visibility') != 'hidden';
}
// filter out invisible elements
$targets = $targets.filter(function(){ return is_visible($(this)); });
// filter out elements with invisible parents
$targets = $targets.filter(function(){
var parents = $(this).parents().filter(function(){ return !is_visible($(this)); });
return parents.length === 0;
});
$targets.each(function () {
var $target = $(this);
if (!$target.data('overlay')) {
var $zone = $(qweb.render('web_editor.snippet_overlay'));
// fix for pointer-events: none with ie9
if (document.body && document.body.addEventListener) {
$zone.on("click mousedown mousedown", function passThrough(event) {
event.preventDefault();
$target.each(function() {
// check if clicked point (taken from event) is inside element
event.srcElement = this;
$(this).trigger(event.type);
});
return false;
});
}
$zone.appendTo('#oe_manipulators');
$zone.data('target',$target);
$target.data('overlay',$zone);
var timer;
$target.closest('.o_editable').on("content_changed", function (event) {
clearTimeout(timer);
timer = setTimeout(function () {
if ($target.data('overlay') && $target.data('overlay').hasClass("oe_active")) {
self.cover_target($target.data('overlay'), $target);
}
},50);
});
var resize = function () {
if ($zone.parent().length) {
self.cover_target($zone, $target);
} else {
$('body').off("resize", resize);
}
};
$('body').on("resize", resize);
}
self.cover_target($target.data('overlay'), $target);
});
return $targets;
}
});
/* ----- Editor (object who contain overlay and the option list) ---- */
var Editor = Class.extend({
init: function (BuildingBlock, dom) {
this.buildingBlock = BuildingBlock;
this.$target = $(dom);
this.$overlay = this.$target.data('overlay');
this.load_style_options();
this.get_parent_block();
this.start();
},
// activate drag and drop for the snippets in the snippet toolbar
_drag_and_drop: function(){
var self = this;
this.dropped = false;
this.$overlay.draggable({
greedy: true,
appendTo: 'body',
cursor: "move",
handle: ".oe_snippet_move",
cursorAt: {
left: 18,
top: 14
},
helper: function() {
var $clone = $(this).clone().css({width: "24px", height: "24px", border: 0});
$clone.find(".oe_overlay_options >:not(:contains(.oe_snippet_move)), .oe_handle").remove();
$clone.find(":not(.glyphicon)").css({position: 'absolute', top: 0, left: 0});
$clone.appendTo("body").removeClass("hidden");
return $clone;
},
start: _.bind(self._drag_and_drop_start, self),
stop: _.bind(self._drag_and_drop_stop, self)
});
},
_drag_and_drop_after_insert_dropzone: function (){},
_drag_and_drop_active_drop_zone: function ($zones){
var self = this;
$zones.droppable({
over: function(){
$(".oe_drop_zone.hide").removeClass("hide");
$(this).addClass("hide").first().after(self.$target);
self.dropped = true;
},
out: function(){
$(this).removeClass("hide");
self.$target.detach();
self.dropped = false;
},
});
},
_drag_and_drop_start: function (){
var self = this;
self.buildingBlock.hide();
self.buildingBlock.editor_busy = true;
self.size = {
width: self.$target.width(),
height: self.$target.height()
};
self.$target.after("");
self.$target.detach();
self.$overlay.addClass("hidden");
var $selector_siblings;
for (var i=0; i