[FIX] mass_mailing: properly manage td/th elements
Refactore width-x snippet option and create another option to handle cloning and removing td elements properly. * on_focus: the handle to resize are now hidden when the td/th is alone on its row * on_clone: when cloning a td element which is alone on its row, it is instead cloned in a new row. If not, empty td are added on the whole column to maintain table integrity. * on_remove: handle removing td in complex table
This commit is contained in:
@@ -16,18 +16,16 @@ if ($editable_area.length === 0 || !$editable_area.is(".o_mail_area")) {
|
||||
// Snippet option for resizing image and column width inline like excel
|
||||
options.registry["width-x"] = options.Class.extend({
|
||||
start: function () {
|
||||
this.container_width = 600;
|
||||
var parent = this.$target.closest('[data-max-width]');
|
||||
if (parent.length) {
|
||||
this.container_width = parseInt(parent.attr('data-max-width'));
|
||||
}
|
||||
this.container_width = this.$target.parent().closest("td, table, div").width();
|
||||
|
||||
var self = this;
|
||||
var offset, sib_offset, target_width, sib_width;
|
||||
var $body = $(document.body);
|
||||
this.is_image = false;
|
||||
this._super();
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
this.$overlay.find(".oe_handle.e, .oe_handle.w").removeClass("readonly");
|
||||
if (this.$target.is('img')) {
|
||||
if (this.$target.is("img")) {
|
||||
this.$overlay.find(".oe_handle.w").addClass("readonly");
|
||||
this.$overlay.find(".oe_snippet_move, .oe_snippet_clone").addClass("hidden");
|
||||
this.is_image=true;
|
||||
@@ -44,88 +42,95 @@ options.registry["width-x"] = options.Class.extend({
|
||||
if (self.is_image) { compass = "image"; }
|
||||
self.buildingBlock.editor_busy = true;
|
||||
|
||||
var $body = $(document.body);
|
||||
|
||||
var body_mousemove = function (event) {
|
||||
$body.on("mousemove.mass_mailing_width_x", function (event) {
|
||||
event.preventDefault();
|
||||
offset = self.$target.offset().left;
|
||||
target_width = self.get_max_width(self.$target);
|
||||
if (compass === 'e' && self.$target.next().offset()) {
|
||||
sib_width = self.get_max_width(self.$target.next());
|
||||
sib_offset = self.$target.next().offset().left;
|
||||
self.change_width(event, self.$target, target_width, offset ,'plus');
|
||||
self.change_width(event, self.$target.next(), sib_width, sib_offset ,'minus');
|
||||
self.change_width(event, self.$target, target_width, offset, true);
|
||||
self.change_width(event, self.$target.next(), sib_width, sib_offset, false);
|
||||
}
|
||||
if (compass === 'w' && self.$target.prev().offset()) {
|
||||
sib_width = self.get_max_width(self.$target.prev());
|
||||
sib_offset = self.$target.prev().offset().left;
|
||||
self.change_width(event, self.$target, target_width, offset ,'minus');
|
||||
self.change_width(event, self.$target.prev(), sib_width, sib_offset, 'plus');
|
||||
self.change_width(event, self.$target, target_width, offset, false);
|
||||
self.change_width(event, self.$target.prev(), sib_width, sib_offset, true);
|
||||
}
|
||||
if (compass === 'image') {
|
||||
self.change_width(event, self.$target, target_width, offset ,'plus');
|
||||
self.change_width(event, self.$target, target_width, offset, true);
|
||||
}
|
||||
};
|
||||
var body_mouseup = function () {
|
||||
$body.unbind('mousemove', body_mousemove);
|
||||
$body.unbind('mouseup', body_mouseup);
|
||||
});
|
||||
$body.on("mouseup.mass_mailing_width_x", function () {
|
||||
$body.off('.mass_mailing_width_x');
|
||||
self.buildingBlock.editor_busy = false;
|
||||
self.$target.removeClass("resize_editor_busy");
|
||||
};
|
||||
$body.mousemove(body_mousemove);
|
||||
$body.mouseup(body_mouseup);
|
||||
});
|
||||
});
|
||||
},
|
||||
change_width: function (event, target ,target_width, offset, type) {
|
||||
var self = this;
|
||||
var width;
|
||||
if (type === 'plus') {
|
||||
width = event.pageX-offset;
|
||||
} else {
|
||||
width = offset + target_width - event.pageX;
|
||||
}
|
||||
target.css("width", width + "px");
|
||||
self.buildingBlock.cover_target(self.$overlay, self.$target);
|
||||
return;
|
||||
change_width: function (event, target, target_width, offset, grow) {
|
||||
target.css("width", grow ? (event.pageX - offset) : (offset + target_width - event.pageX));
|
||||
this.buildingBlock.cover_target(this.$overlay, this.$target);
|
||||
},
|
||||
get_int_width: function ($el) {
|
||||
var el_width = $el.css('width');
|
||||
return parseInt(el_width);
|
||||
get_int_width: function (el) {
|
||||
return parseInt($(el).css("width"), 10);
|
||||
},
|
||||
get_max_width: function ($el) {
|
||||
var max_width = 0;
|
||||
var self = this;
|
||||
_.each($el.siblings(),function(sib){
|
||||
max_width += self.get_int_width($(sib));
|
||||
});
|
||||
return this.container_width - max_width;
|
||||
return this.container_width - _.reduce(_.map($el.siblings(), this.get_int_width), function (memo, w) { return memo + w; });
|
||||
},
|
||||
on_focus: function () {
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
if (this.$target.is("td, th")) {
|
||||
this.$overlay.find(".oe_handle.e, .oe_handle.w").toggleClass("readonly", this.$target.siblings().length === 0);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
options.registry.table_item = options.Class.extend({
|
||||
on_clone: function ($clone) {
|
||||
var clone_index = $(this.$target).index();
|
||||
var $table = this.$target.parents('table[data-max-width]');
|
||||
if ($table.length === 1){
|
||||
_.each($table.find('tbody>tr'),function(row){
|
||||
var clone_selector = 'td:eq(' + clone_index + ')';
|
||||
var $col_to_clone = $(row).find(clone_selector);
|
||||
if ($col_to_clone.length !== 0){
|
||||
$col_to_clone.after($col_to_clone.clone());
|
||||
}
|
||||
this._super.apply(this, arguments);
|
||||
|
||||
// If we cloned a td or th element...
|
||||
if (this.$target.is("td, th")) {
|
||||
// ... and that the td or th element was alone on its row ...
|
||||
if (this.$target.siblings().length === 1) {
|
||||
var $tr = $clone.parent();
|
||||
$tr.clone().empty().insertAfter($tr).append($clone); // ... move the clone in a new row instead
|
||||
return;
|
||||
}
|
||||
|
||||
// ... if not, if the clone neighbor is an empty cell, remove this empty cell (like if the clone content had been put in that cell)
|
||||
var $next = $clone.next();
|
||||
if ($next.length && $next.text().trim() === "") {
|
||||
$next.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// ... if not, insert an empty col in each other row, at the index of the clone
|
||||
var width = $clone.width();
|
||||
var $trs = this.$target.closest("table").children("thead, tbody, tfoot").addBack().children("tr").not(this.$target.parent());
|
||||
_.each($trs.children(":nth-child(" + this.$target.index() + ")"), function (col) {
|
||||
$(col).after($("<td/>", {style: "width: " + width + "px;"}));
|
||||
});
|
||||
}
|
||||
this._super($clone);
|
||||
this.buildingBlock.cover_target(this.$overlay, this.$target);
|
||||
},
|
||||
on_remove: function () {
|
||||
var remove_index = $(this.$target).index();
|
||||
var $table = this.$target.parents('table[data-max-width]');
|
||||
if ($table.length === 1){
|
||||
_.each($table.find('tbody>tr'),function(row){
|
||||
var remove_selector = 'td:eq(' + remove_index + ')';
|
||||
$(row).find(remove_selector).remove();
|
||||
});
|
||||
}
|
||||
this._super.apply(this, arguments);
|
||||
this.buildingBlock.cover_target(this.$overlay, this.$target);
|
||||
|
||||
// If we are removing a td or th element which was not alone on its row ...
|
||||
if (this.$target.is("td, th") && this.$target.siblings().length > 0) {
|
||||
var $trs = this.$target.closest("table").children("thead, tbody, tfoot").addBack().children("tr").not(this.$target.parent());
|
||||
if ($trs.length) { // ... if there are other rows in the table ...
|
||||
var $last_tds = $trs.children(":last-child");
|
||||
if (_.reduce($last_tds, function (memo, td) { return memo + (td.innerHTML || ""); }, "").trim() === "") {
|
||||
$last_tds.remove(); // ... remove the potential full empty column in the table
|
||||
} else {
|
||||
this.$target.parent().append("<td/>"); // ... else, if there is no full empty column, append an empty col in the current row
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
data-selector="img, .mv, .col_mv, td, th">
|
||||
</div>
|
||||
|
||||
<div data-js="table_item" data-selector="td, th"/>
|
||||
|
||||
<div data-js="table_row"
|
||||
data-selector="tr:has(> .row), tr:has(> .col_mv)"
|
||||
data-drop-near="tr:has(> .row), tr:has(> .col_mv)">
|
||||
|
||||
Reference in New Issue
Block a user