(function () {
'use strict';
/* Building block / Snippet Editor
The building blocks appear in the edit bar website. These prebuilt html block
allowing the designer to easily generate content on a page (drag and drop).
Options allow snippets to add customizations part html code according to their
selector (jQuery) and javascript object.
How to create content?
Designers can add their own html block in the "snippets" (/website/views/snippets.xml).
The block must be added in one of four menus (structure, content, feature or effect).
Structure:
');
this['snippet-option-id'] = snippet_id;
var $option = website.snippet.templateOptions[snippet_id].$el;
this.$el = $option.find(">li").clone();
this.data = $option.data();
this.required = this.$el.data("required");
this.set_active();
this.$el.find('li[data-value] a').on('mouseenter mouseleave click', _.bind(this._mouse, this));
this.$el.not(':not([data-value])').find("a").on('mouseenter mouseleave click', _.bind(this._mouse, this));
this.$target.on('snippet-style-reset', _.bind(this.set_active, this));
this.start();
},
_mouse: function (event) {
var self = this;
if (event.type === 'mouseleave') {
if (!this.over) return;
this.over = false;
} else if (event.type === 'click') {
this.over = false;
}else {
this.over = true;
}
var $prev, $next;
if (event.type === 'mouseleave') {
$prev = $(event.currentTarget).parent();
$next = this.$el.find("li[data-value].active");
} else {
$prev = this.$el.find("li[data-value].active");
$next = $(event.currentTarget).parent();
}
if (!$prev.length) {
$prev = false;
}
if ($prev && $prev[0] === $next[0]) {
$next = false;
if (this.required) {
return;
}
}
var np = {'$next': $next, '$prev': $prev};
if (event.type === 'click') {
setTimeout(function () {
self.set_active();
self.$target.trigger("snippet-style-change", [self, np]);
},0);
this.select({'$next': $next, '$prev': $prev});
} else {
setTimeout(function () {
self.$target.trigger("snippet-style-preview", [self, np]);
},0);
this.preview(np);
}
},
/* set_active
* select and set item active or not (add highlight item and his parents)
* called before start
*/
set_active: function () {
var self = this;
this.$el.find('li').removeClass("active");
var $active = this.$el.find('li[data-value]')
.filter(function () {
var $li = $(this);
return ($li.data('value') && self.$target.hasClass($li.data('value')));
})
.first()
.addClass("active");
this.$el.find('li:has(li[data-value].active)').addClass("active");
},
start: function () {
},
onFocus : function () {
},
onBlur : function () {
},
on_clone: function ($clone) {
},
on_remove: function () {
},
drop_and_build_snippet: function () {
},
select: function (np) {
var self = this;
// add or remove html class
if (np.$prev && this.required) {
this.$target.removeClass(np.$prev.data('value' || ""));
}
if (np.$next) {
this.$target.addClass(np.$next.data('value') || "");
}
},
preview: function (np) {
var self = this;
// add or remove html class
if (np.$prev) {
this.$target.removeClass(np.$prev.data('value') || "");
}
if (np.$next) {
this.$target.addClass(np.$next.data('value') || "");
}
},
clean_for_save: dummy
});
website.snippet.options.background = website.snippet.Option.extend({
_get_bg: function () {
return this.$target.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, "");
},
_set_bg: function (src) {
this.$target.css("background-image", src && src !== "" ? 'url(' + src + ')' : "");
},
start: function () {
this._super();
var src = this._get_bg();
this.$el.find("li[data-value].active.oe_custom_bg").data("src", src);
},
select: function(np) {
var self = this;
this._super(np);
if (np.$next) {
if (np.$next.hasClass("oe_custom_bg")) {
var $image = $('
');
$image.attr("src", np.$prev ? np.$prev.data("src") : '');
$image.appendTo(self.$target);
self.element = new CKEDITOR.dom.element($image[0]);
var editor = new website.editor.MediaDialog(self, self.element);
editor.appendTo(document.body);
editor.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden');
$image.on('saved', self, function (o) {
var src = $image.attr("src");
self._set_bg(src);
np.$next.data("src", src);
self.$target.trigger("snippet-style-change", [self, np]);
$image.remove();
});
editor.on('cancel', self, function () {
if (!np.$prev || np.$prev.data("src") === "") {
self.$target.removeClass(np.$next.data("value"));
self.$target.trigger("snippet-style-change", [self, np]);
}
$image.remove();
});
} else {
this._set_bg(np.$next.data("src"));
}
} else {
this._set_bg(false);
this.$target.removeClass(np.$prev.data("value"));
}
},
preview: function (np) {
this._super(np);
if (np.$next) {
this._set_bg(np.$next.data("src"));
}
},
set_active: function () {
var self = this;
var bg = self.$target.css("background-image");
this.$el.find('li').removeClass("active");
this.$el.find('li').removeClass("btn-primary");
var $active = this.$el.find('li[data-value]')
.filter(function () {
var $li = $(this);
return ($li.data('src') && bg.indexOf($li.data('src')) >= 0) ||
(!$li.data('src') && self.$target.hasClass($li.data('value')));
})
.first();
if (!$active.length) {
$active = this.$target.css("background-image") !== 'none' ?
this.$el.find('li[data-value].oe_custom_bg') :
this.$el.find('li[data-value=""]');
}
//don't set active on an OpenDialog link, else it not possible to click on it again after.
// TODO in Saas-4 - Once bootstrap is in less
// - add a class active-style to get the same display but without the active behaviour used by bootstrap in JS.
var classStr = _.string.contains($active[0].className, "oe_custom_bg") ? "btn-primary" : "active";
$active.addClass(classStr);
this.$el.find('li:has(li[data-value].active)').addClass(classStr);
}
});
website.snippet.options.slider = website.snippet.Option.extend({
unique_id: function () {
var id = 0;
$(".carousel").each(function () {
var cid = 1 + parseInt($(this).attr("id").replace(/[^0123456789]/g, ''),10);
if (id < cid) id = cid;
});
return "myCarousel" + id;
},
drop_and_build_snippet: function() {
this.id = this.unique_id();
this.$target.attr("id", this.id);
this.$target.find("[data-slide]").attr("data-cke-saved-href", "#" + this.id);
this.$target.find("[data-target]").attr("data-target", "#" + this.id);
this.rebind_event();
},
on_clone: function ($clone) {
var id = this.unique_id();
$clone.attr("id", id);
$clone.find("[data-slide]").attr("href", "#" + id);
$clone.find("[data-slide-to]").attr("data-target", "#" + id);
},
// rebind event to active carousel on edit mode
rebind_event: function () {
var self = this;
this.$target.find('.carousel-indicators [data-slide-to]').off('click').on('click', function () {
self.$target.carousel(+$(this).data('slide-to')); });
this.$target.attr('contentEditable', 'false');
this.$target.find('.oe_structure, .content.row, [data-slide]').attr('contentEditable', 'true');
},
clean_for_save: function () {
this._super();
this.$target.find(".item").removeClass("next prev left right active");
this.$target.find(".item:first").addClass("active");
this.$indicators.find('li').removeClass('active');
this.$indicators.find('li:first').addClass('active');
},
start : function () {
var self = this;
this._super();
this.$target.carousel({interval: false});
this.id = this.$target.attr("id");
this.$inner = this.$target.find('.carousel-inner');
this.$indicators = this.$target.find('.carousel-indicators');
this.$el.find(".js_add").on('click', function () {self.on_add_slide(); return false;});
this.$el.find(".js_remove").on('click', function () {self.on_remove_slide(); return false;});
this.$target.carousel('pause');
this.rebind_event();
},
on_add_slide: function () {
var self = this;
var cycle = this.$inner.find('.item').length;
var $active = this.$inner.find('.item.active, .item.prev, .item.next').first();
var index = $active.index();
this.$target.find('.carousel-control, .carousel-indicators').removeClass("hidden");
this.$indicators.append('
');
// clone the best candidate from template to use new features
var $snippets = this.BuildingBlock.$snippets.find('.oe_snippet_body.carousel');
var point = 0;
var selection;
var className = _.compact(this.$target.attr("class").split(" "));
$snippets.each(function () {
var len = _.intersection(_.compact(this.className.split(" ")), className).length;
if (len > point) {
point = len;
selection = this;
}
});
var $clone = $(selection).find('.item:first').clone();
// insert
$clone.removeClass('active').insertAfter($active);
setTimeout(function() {
self.$target.carousel().carousel(++index);
self.rebind_event();
},0);
return $clone;
},
on_remove_slide: function () {
if (this.remove_process) {
return;
}
var self = this;
var new_index = 0;
var cycle = this.$inner.find('.item').length - 1;
var index = this.$inner.find('.item.active').index();
if (cycle > 0) {
this.remove_process = true;
var $el = this.$inner.find('.item.active');
self.$target.on('slid.bs.carousel', function (event) {
$el.remove();
self.$indicators.find("li:last").remove();
self.$target.off('slid.bs.carousel');
self.rebind_event();
self.remove_process = false;
if (cycle == 1) {
self.on_remove_slide(event);
}
});
setTimeout(function () {
self.$target.carousel( index > 0 ? --index : cycle );
}, 500);
} else {
this.$target.find('.carousel-control, .carousel-indicators').addClass("hidden");
}
},
});
website.snippet.options.carousel = website.snippet.options.slider.extend({
getSize: function () {
this.grid = this._super();
this.grid.size = 8;
return this.grid;
},
clean_for_save: function () {
this._super();
this.$target.css("background-image", "");
this.$target.removeClass(this._class);
},
load_style_options : function () {
this._super();
$(".snippet-style-size li[data-value='']").remove();
},
start : function () {
var self = this;
this._super();
// set background and prepare to clean for save
var add_class = function (c){
if (c) self._class = (self._class || "").replace(new RegExp("[ ]+" + c.replace(" ", "|[ ]+")), '') + ' ' + c;
return self._class || "";
};
this.$target.on('snippet-style-change snippet-style-preview', function (event, style, np) {
var $active = self.$target.find(".item.active");
if (style['snippet-option-id'] === "size") return;
if (style['snippet-option-id'] === "background") {
$active.css("background-image", self.$target.css("background-image"));
}
if (np.$prev) {
$active.removeClass(np.$prev.data("value"));
}
if (np.$next) {
$active.addClass(np.$next.data("value"));
add_class(np.$next.data("value"));
}
});
this.$target.on('slid', function () { // slide.bs.carousel
var $active = self.$target.find(".item.active");
self.$target
.css("background-image", $active.css("background-image"))
.removeClass(add_class($active.attr("class")))
.addClass($active.attr("class"))
.trigger("snippet-style-reset");
self.$target.carousel("pause");
});
this.$target.trigger('slid');
},
on_add_slide: function () {
var $clone = this._super();
// choose an other background
var bg = this.$target.data("snippet-option-ids").background;
if (!bg) return $clone;
var $styles = bg.$el.find("li[data-value]:not(.oe_custom_bg)");
var styles_index = $styles.index($styles.filter(".active")[0]);
$styles.removeClass("active");
var $select = $($styles[styles_index >= $styles.length-1 ? 0 : styles_index+1]);
$select.addClass("active");
$clone.css("background-image", $select.data("src") ? "url('"+ $select.data("src") +"')" : "");
$clone.addClass($select.data("value") || "");
return $clone;
},
// rebind event to active carousel on edit mode
rebind_event: function () {
var self = this;
this.$target.find('.carousel-control').off('click').on('click', function () {
self.$target.carousel( $(this).data('slide')); });
this._super();
/* Fix: backward compatibility saas-3 */
this.$target.find('.item.text_image, .item.image_text, .item.text_only').find('.container > .carousel-caption > div, .container > img.carousel-image').attr('contentEditable', 'true');
},
});
website.snippet.options.marginAndResize = website.snippet.Option.extend({
start: function () {
var self = this;
this._super();
var resize_values = this.getSize();
if (resize_values.n) this.$overlay.find(".oe_handle.n").removeClass("readonly");
if (resize_values.s) this.$overlay.find(".oe_handle.s").removeClass("readonly");
if (resize_values.e) this.$overlay.find(".oe_handle.e").removeClass("readonly");
if (resize_values.w) this.$overlay.find(".oe_handle.w").removeClass("readonly");
if (resize_values.size) this.$overlay.find(".oe_handle.size").removeClass("readonly");
this.$overlay.find(".oe_handle:not(.size), .oe_handle.size .size").on('mousedown', function (event){
event.preventDefault();
var $handle = $(this);
var resize_values = self.getSize();
var compass = false;
var XY = false;
if ($handle.hasClass('n')) {
compass = 'n';
XY = 'Y';
}
else if ($handle.hasClass('s')) {
compass = 's';
XY = 'Y';
}
else if ($handle.hasClass('e')) {
compass = 'e';
XY = 'X';
}
else if ($handle.hasClass('w')) {
compass = 'w';
XY = 'X';
}
else if ($handle.hasClass('size')) {
compass = 'size';
XY = 'Y';
}
var resize = resize_values[compass];
if (!resize) return;
if (compass === 'size') {
var offset = self.$target.offset().top;
if (self.$target.css("background").match(/rgba\(0, 0, 0, 0\)/)) {
self.$target.addClass("resize_editor_busy");
}
} else {
var xy = event['page'+XY];
var current = resize[2] || 0;
_.each(resize[0], function (val, key) {
if (self.$target.hasClass(val)) {
current = key;
}
});
var begin = current;
var beginClass = self.$target.attr("class");
var regClass = new RegExp("\\s*" + resize[0][begin].replace(/[-]*[0-9]+/, '[-]*[0-9]+'), 'g');
}
self.BuildingBlock.editor_busy = true;
var cursor = $handle.css("cursor")+'-important';
var $body = $(document.body);
$body.addClass(cursor);
var body_mousemove = function (event){
event.preventDefault();
if (compass === 'size') {
var dy = event.pageY-offset;
dy = dy - dy%resize;
if (dy <= 0) dy = resize;
self.$target.css("height", dy+"px");
self.$target.css("overflow", "hidden");
self.on_resize(compass, null, dy);
self.BuildingBlock.cover_target(self.$overlay, self.$target);
return;
}
var dd = event['page'+XY] - xy + resize[1][begin];
var next = current+1 === resize[1].length ? current : (current+1);
var prev = current ? (current-1) : 0;
var change = false;
if (dd > (2*resize[1][next] + resize[1][current])/3) {
self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, ''));
self.$target.addClass(resize[0][next]);
current = next;
change = true;
}
if (prev != current && dd < (2*resize[1][prev] + resize[1][current])/3) {
self.$target.attr("class", (self.$target.attr("class")||'').replace(regClass, ''));
self.$target.addClass(resize[0][prev]);
current = prev;
change = true;
}
if (change) {
self.on_resize(compass, beginClass, current);
self.BuildingBlock.cover_target(self.$overlay, self.$target);
}
};
var body_mouseup = function(){
$body.unbind('mousemove', body_mousemove);
$body.unbind('mouseup', body_mouseup);
$body.removeClass(cursor);
self.BuildingBlock.editor_busy = false;
self.$target.removeClass("resize_editor_busy");
};
$body.mousemove(body_mousemove);
$body.mouseup(body_mouseup);
});
this.$overlay.find(".oe_handle.size .auto_size").on('click', function (event){
self.$target.css("height", "");
self.$target.css("overflow", "");
self.BuildingBlock.cover_target(self.$overlay, self.$target);
return false;
});
},
getSize: function () {
this.grid = {};
return this.grid;
},
onFocus : function () {
this._super();
this.change_cursor();
},
change_cursor : function () {
var _class = this.$target.attr("class") || "";
var col = _class.match(/col-md-([0-9-]+)/i);
col = col ? +col[1] : 0;
var offset = _class.match(/col-md-offset-([0-9-]+)/i);
offset = offset ? +offset[1] : 0;
var overlay_class = this.$overlay.attr("class").replace(/(^|\s+)block-[^\s]*/gi, '');
if (col+offset >= 12) overlay_class+= " block-e-right";
if (col === 1) overlay_class+= " block-w-right block-e-left";
if (offset === 0) overlay_class+= " block-w-left";
var mb = _class.match(/mb([0-9-]+)/i);
mb = mb ? +mb[1] : 0;
if (mb >= 128) overlay_class+= " block-s-bottom";
else if (!mb) overlay_class+= " block-s-top";
var mt = _class.match(/mt([0-9-]+)/i);
mt = mt ? +mt[1] : 0;
if (mt >= 128) overlay_class+= " block-n-top";
else if (!mt) overlay_class+= " block-n-bottom";
this.$overlay.attr("class", overlay_class);
},
/* on_resize
* called when the box is resizing and the class change, before the cover_target
* @compass: resize direction : 'n', 's', 'e', 'w'
* @beginClass: attributes class at the begin
* @current: curent increment in this.grid
*/
on_resize: function (compass, beginClass, current) {
this.change_cursor();
}
});
website.snippet.options["margin-y"] = website.snippet.options.marginAndResize.extend({
getSize: function () {
this.grid = this._super();
var grid = [0,4,8,16,32,48,64,92,128];
this.grid = {
// list of class (Array), grid (Array), default value (INT)
n: [_.map(grid, function (v) {return 'mt'+v;}), grid],
s: [_.map(grid, function (v) {return 'mb'+v;}), grid],
// INT if the user can resize the snippet (resizing per INT px)
size: null
};
return this.grid;
},
});
website.snippet.options["margin-x"] = website.snippet.options.marginAndResize.extend({
getSize: function () {
this.grid = this._super();
var width = this.$target.parents(".row:first").first().outerWidth();
var grid = [1,2,3,4,5,6,7,8,9,10,11,12];
this.grid.e = [_.map(grid, function (v) {return 'col-md-'+v;}), _.map(grid, function (v) {return width/12*v;})];
var grid = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11];
this.grid.w = [_.map(grid, function (v) {return 'col-md-offset-'+v;}), _.map(grid, function (v) {return width/12*v;}), 12];
return this.grid;
},
_drag_and_drop_after_insert_dropzone: function(){
var self = this;
var $zones = $(".row:has(> .oe_drop_zone)").each(function () {
var $row = $(this);
var width = $row.innerWidth();
var pos = 0;
while (width > pos + self.size.width) {
var $last = $row.find("> .oe_drop_zone:last");
$last.each(function () {
pos = $(this).position().left;
});
if (width > pos + self.size.width) {
$row.append("
");
var $add_drop = $last.clone();
$row.append($add_drop);
self._drag_and_drop_active_drop_zone($add_drop);
}
}
});
},
_drag_and_drop_start: function () {
this._super();
this.$target.attr("class",this.$target.attr("class").replace(/\s*(col-lg-offset-|col-md-offset-)([0-9-]+)/g, ''));
},
_drag_and_drop_stop: function () {
this.$target.addClass("col-md-offset-" + this.$target.prevAll(".oe_drop_to_remove").length);
this._super();
},
hide_remove_button: function() {
this.$overlay.find('.oe_snippet_remove').toggleClass("hidden", !this.$target.siblings().length);
},
onFocus : function () {
this._super();
this.hide_remove_button();
},
on_clone: function ($clone) {
var _class = $clone.attr("class").replace(/\s*(col-lg-offset-|col-md-offset-)([0-9-]+)/g, '');
$clone.attr("class", _class);
this.hide_remove_button();
return false;
},
on_remove: function () {
if (!this.$target.siblings().length) {
var $parent = this.$target.parents(".row:first");
if($parent.find("[class*='col-md']").length > 1) {
return false;
} else {
if (!$parent.data("snippet-editor")) {
this.BuildingBlock.create_overlay($parent);
}
$parent.data("snippet-editor").on_remove();
}
}
this._super();
this.hide_remove_button();
return false;
},
on_resize: function (compass, beginClass, current) {
if (compass === 'w') {
// don't change the right border position when we change the offset (replace col size)
var beginCol = Number(beginClass.match(/col-md-([0-9]+)|$/)[1] || 0);
var beginOffset = Number(beginClass.match(/col-md-offset-([0-9-]+)|$/)[1] || beginClass.match(/col-lg-offset-([0-9-]+)|$/)[1] || 0);
var offset = Number(this.grid.w[0][current].match(/col-md-offset-([0-9-]+)|$/)[1] || 0);
if (offset < 0) {
offset = 0;
}
var colSize = beginCol - (offset - beginOffset);
if (colSize <= 0) {
colSize = 1;
offset = beginOffset + beginCol - 1;
}
this.$target.attr("class",this.$target.attr("class").replace(/\s*(col-lg-offset-|col-md-offset-|col-md-)([0-9-]+)/g, ''));
this.$target.addClass('col-md-' + (colSize > 12 ? 12 : colSize));
if (offset > 0) {
this.$target.addClass('col-md-offset-' + offset);
}
}
this._super(compass, beginClass, current);
},
});
website.snippet.options["resize"] = website.snippet.options.marginAndResize.extend({
getSize: function () {
this.grid = this._super();
this.grid.size = 8;
return this.grid;
},
});
website.snippet.options.parallax = website.snippet.Option.extend({
getSize: function () {
this.grid = this._super();
this.grid.size = 8;
return this.grid;
},
on_resize: function (compass, beginClass, current) {
this.$target.data("snippet-view").set_values();
},
start : function () {
var self = this;
this._super();
if (!self.$target.data("snippet-view")) {
this.$target.data("snippet-view", new website.snippet.animationRegistry.parallax(this.$target));
}
this.scroll();
this.$target.on('snippet-style-change snippet-style-preview', function () {
self.$target.data("snippet-view").set_values();
});
this.$target.attr('contentEditable', 'false');
this.$target.find('> div > .oe_structure').attr('contentEditable', 'true'); // saas-3 retro-compatibility
this.$target.find('> div > div:not(.oe_structure) > .oe_structure').attr('contentEditable', 'true');
},
scroll: function () {
var self = this;
var $ul = this.$el.find('ul[name="parallax-scroll"]');
var $li = $ul.find("li");
var speed = this.$target.data('scroll-background-ratio') || 0.6 ;
$ul.find('[data-value="' + speed + '"]').addClass('active');
$li.on('click', function (event) {
$li.removeClass("active");
$(this).addClass("active");
var speed = $(this).data('value');
self.$target.attr('data-scroll-background-ratio', speed);
self.$target.data("snippet-view").set_values();
return false;
});
this.$target.data("snippet-view").set_values();
},
clean_for_save: function () {
this._super();
this.$target.find(".parallax")
.css("background-position", '')
.removeAttr("data-scroll-background-offset");
}
});
website.snippet.options.transform = website.snippet.Option.extend({
start: function () {
var self = this;
this._super();
this.$el.find(".clear-style").click(function (event) {
self.$target.removeClass("fa-spin").attr("style", "");
self.resetTransfo();
});
this.$el.find(".style").click(function (event) {
var settings = self.$target.data("transfo").settings;
self.$target.transfo({ hide: (settings.hide = !settings.hide) });
});
this.$overlay.find('.oe_snippet_clone, .oe_handles').addClass('hidden');
this.$overlay.find('[data-toggle="dropdown"]')
.on("mousedown", function () {
self.$target.transfo("hide");
});
},
resetTransfo: function () {
var self = this;
this.$target.transfo("destroy");
this.$target.transfo({
hide: true,
callback: function () {
var center = $(this).data("transfo").$markup.find('.transfo-scaler-mc').offset();
var $option = self.$overlay.find('.btn-group:first');
self.$overlay.css({
'top': center.top - $option.height()/2,
'left': center.left,
'position': 'absolute',
});
self.$overlay.find(".oe_overlay_options").attr("style", "width:0; left:0!important; top:0;");
self.$overlay.find(".oe_overlay_options > .btn-group").attr("style", "width:160px; left:-80px;");
}});
this.$target.data('transfo').$markup
.on("mouseover", function () {
self.$target.trigger("mouseover");
})
.mouseover();
},
onFocus : function () {
this.resetTransfo();
},
onBlur : function () {
this.$target.transfo("hide");
},
});
website.snippet.options.media = website.snippet.Option.extend({
start: function () {
var self = this;
this._super();
website.snippet.start_animation(true, this.$target);
$(document.body).on("media-saved", self, function (event, prev , item) {
self.editor.onBlur();
self.BuildingBlock.make_active(false);
if (self.$target.parent().data("oe-field") !== "image") {
self.BuildingBlock.make_active($(item));
}
});
this.$el.find(".edition").click(function (event) {
event.preventDefault();
event.stopPropagation();
self.element = new CKEDITOR.dom.element(self.$target[0]);
new website.editor.MediaDialog(self, self.element).appendTo(document.body);
});
},
onFocus : function () {
var self = this;
if (this.$target.parent().data("oe-field") === "image") {
this.$overlay.addClass("hidden");
self.element = new CKEDITOR.dom.element(self.$target[0]);
new website.editor.MediaDialog(self, self.element).appendTo(document.body);
self.BuildingBlock.make_active(false);
}
setTimeout(function () {
self.$target.find(".css_editable_mode_display").removeAttr("_moz_abspos");
},0);
},
});
website.snippet.Editor = openerp.Class.extend({
init: function (BuildingBlock, dom) {
this.BuildingBlock = BuildingBlock;
this.$target = $(dom);
this.$overlay = this.$target.data('overlay');
this.snippet_id = this.$target.data("snippet-id");
this._readXMLData();
this.load_style_options();
this.get_parent_block();
this.start();
},
/*
* _readXMLData
* Read data XML and set value into:
* this.$el :
* all xml data
* this.$overlay :
* Dom hover the $target who content options
*/
_readXMLData: function() {
var self = this;
if(this && this.BuildingBlock && this.BuildingBlock.$snippets) {
this.$el = this.BuildingBlock.$snippets.filter(function () { return $(this).data("snippet-id") == self.snippet_id; }).clone();
}
var $options = this.$overlay.find(".oe_overlay_options");
if ($options.find(".oe_options ul li").length) {
$options.find(".oe_options").removeClass("hidden");
}
},
// 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");
self.BuildingBlock.activate_insertion_zones({
siblings: self.selector_siblings,
children: self.selector_children,
vertical_children: self.selector_vertical_children,
});
$("body").addClass('move-important');
self._drag_and_drop_after_insert_dropzone();
self._drag_and_drop_active_drop_zone($('.oe_drop_zone'));
},
_drag_and_drop_stop: function (){
var self = this;
if (!self.dropped) {
$(".oe_drop_clone").after(self.$target);
}
self.$overlay.removeClass("hidden");
$("body").removeClass('move-important');
$('.oe_drop_zone').droppable('destroy').remove();
$(".oe_drop_clone, .oe_drop_to_remove").remove();
self.BuildingBlock.editor_busy = false;
self.get_parent_block();
setTimeout(function () {self.BuildingBlock.create_overlay(self.$target);},0);
},
load_style_options: function () {
var self = this;
var $styles = this.$overlay.find('.oe_options');
var $ul = $styles.find('ul:first');
this.styles = {};
this.selector_siblings = [];
this.selector_children = [];
this.selector_vertical_children = [];
_.each(website.snippet.templateOptions, function (val) {
if (!self.$target.is(val.selector)) {
return;
}
if (val['selector-siblings']) self.selector_siblings.push(val['selector-siblings']);
if (val['selector-children']) self.selector_children.push(val['selector-children']);
if (val['selector-vertical-children']) self.selector_vertical_children.push(val['selector-vertical-children']);
var style = val['snippet-option-id'];
var Editor = website.snippet.options[style] || website.snippet.Option;
var editor = self.styles[style] = new Editor(self.BuildingBlock, self, self.$target, style);
$ul.append(editor.$el.addClass("snippet-style-" + style));
});
this.selector_siblings = this.selector_siblings.join(",");
if (this.selector_siblings === "")
this.selector_siblings = false;
this.selector_children = this.selector_children.join(",");
if (this.selector_children === "")
this.selector_children = false;
this.selector_vertical_children = this.selector_vertical_children.join(",");
if (this.selector_vertical_children === "")
this.selector_vertical_children = false;
if (!this.selector_siblings && !this.selector_children && !this.selector_vertical_children) {
this.$overlay.find(".oe_snippet_move").addClass('hidden');
}
if ($ul.find("li").length) {
$styles.removeClass("hidden");
}
this.$overlay.find('[data-toggle="dropdown"]').dropdown();
},
get_parent_block: function () {
var self = this;
var $button = this.$overlay.find('.oe_snippet_parent');
var $parent = this.$target.parents(website.snippet.globalSelector).first();
if ($parent.length) {
$button.removeClass("hidden");
$button.off("click").on('click', function (event) {
event.preventDefault();
setTimeout(function () {
self.BuildingBlock.make_active($parent);
}, 0);
});
} else {
$button.addClass("hidden");
}
},
/*
* start
* This method is called after init and _readXMLData
*/
start: function () {
var self = this;
this.$overlay.on('click', '.oe_snippet_clone', _.bind(this.on_clone, this));
this.$overlay.on('click', '.oe_snippet_remove', _.bind(this.on_remove, this));
this._drag_and_drop();
},
on_clone: function () {
var $clone = this.$target.clone(false);
this.$target.after($clone);
for (var i in this.styles){
this.styles[i].on_clone($clone);
}
return false;
},
on_remove: function () {
this.onBlur();
var index = _.indexOf(this.BuildingBlock.snippets, this.$target.get(0));
for (var i in this.styles){
this.styles[i].on_remove();
}
delete this.BuildingBlock.snippets[index];
this.$target.remove();
this.$overlay.remove();
return false;
},
/*
* drop_and_build_snippet
* This method is called just after that a thumbnail is drag and dropped into a drop zone
* (after the insertion of this.$body, if this.$body exists)
*/
drop_and_build_snippet: function () {
for (var i in this.styles){
this.styles[i].drop_and_build_snippet();
}
},
/* onFocus
* This method is called when the user click inside the snippet in the dom
*/
onFocus : function () {
this.$overlay.addClass('oe_active');
for (var i in this.styles){
this.styles[i].onFocus();
}
},
/* onFocus
* This method is called when the user click outside the snippet in the dom, after a focus
*/
onBlur : function () {
for (var i in this.styles){
this.styles[i].onBlur();
}
this.$overlay.removeClass('oe_active');
},
});
})();