[MERGE] website, web_editor, website_sale: various changes

- Snippet options reorganization (background, gallery)
- Website menu reorganization
- Gallery snippet edition behaviors
- Various editor behaviors

See merge sub-commits for details.

task-30407
This commit is contained in:
qsm-odoo
2017-06-14 17:55:16 +02:00
11 changed files with 175 additions and 114 deletions
+11 -1
View File
@@ -535,7 +535,6 @@ var RTE = Widget.extend({
}
if ($editable.length && (!this.$last || this.$last[0] !== $editable[0]) &&
($target.closest('[contenteditable]').attr('contenteditable') || "").toLowerCase() !== 'false') {
$editable.summernote(this.config($editable));
$editable.data('NoteHistory', history);
@@ -578,6 +577,17 @@ var RTE = Widget.extend({
_.defer(function () {
self.historyRecordUndo($target, 'activate', true);
});
// To Fix Google Chrome Tripleclick Issue, which selects the ending
// whitespace characters (so Tripleclicking then typing text will remove
// the whole paragraph instead of its content).
// http://stackoverflow.com/questions/38467334/why-does-google-chrome-always-add-space-after-selected-text
if ($.browser.chrome === true && event.originalEvent.detail === 3) {
var currentSelection = range.create();
if (currentSelection.sc.parentNode === currentSelection.ec) {
range.create(currentSelection.sc, currentSelection.so, currentSelection.sc, currentSelection.sc.length).select();
}
}
},
editable: function () {
@@ -67,8 +67,8 @@ renderer.createPalette = function ($container, options) {
var $palettes = $container.find(".note-color .note-color-palette");
$palettes.prepend(html);
var $bg = $palettes.first().find("button:not(.note-color-btn)").addClass("note-color-btn");
var $fore = $palettes.last().find("button:not(.note-color-btn)").addClass("note-color-btn");
var $bg = $palettes.filter(":even").find("button:not(.note-color-btn)").addClass("note-color-btn");
var $fore = $palettes.filter(":odd").find("button:not(.note-color-btn)").addClass("note-color-btn");
$bg.each(function () {
var $el = $(this);
var className = 'bg-' + $el.data('color');
@@ -146,10 +146,7 @@ renderer.tplPopovers = function (lang, options) {
})).appendTo($resizefa);
}
var $colorfa = $airPopover.find('.note-color').clone();
$colorfa.find(".btn-group:first").remove();
$colorfa.find("ul.dropdown-menu").css('min-width', '172px');
$colorfa.find('button[data-event="color"]').attr('data-value', '{"foreColor": "#f00"}')
.find("i").css({'background': '', 'color': '#f00'});
$resizefa.after($colorfa);
// show dialog box and delete
@@ -454,7 +451,7 @@ $.summernote.pluginEvents.visible = function (event, editor, layoutInfo) {
if (($node.is('[data-oe-type="html"]') || $node.is('[data-oe-field="arch"]')) &&
$node.hasClass("o_editable") &&
!$node[0].children.length &&
"h1 h2 h3 h4 h5 h6 p b bold i u code sup strong small pre th td".toUpperCase().indexOf($node[0].nodeName) === -1) {
"h1 h2 h3 h4 h5 h6 p b bold i u code sup strong small pre th td span".toUpperCase().indexOf($node[0].nodeName) === -1) {
var p = $('<p><br/></p>')[0];
$node.append( p );
range.createFromNode(p.firstChild).select();
@@ -849,6 +846,7 @@ eventHandler.attach = function (oLayoutInfo, options) {
if ($(e.target).closest(".note-toolbar").length) return; // prevent icon edition of top bar for default summernote
show_tooltip = false;
callback();
e.stopImmediatePropagation();
});
oLayoutInfo.editor().on("click", selector, function (e) {
@@ -585,7 +585,7 @@ odoo.define('web_editor.snippets.options', function (require) {
.on("background-color-event.background-option", (function (e, type) {
e.stopPropagation();
if (e.currentTarget !== e.target) return;
this.$el.find("li:first > a").trigger(type);
this.$el.find("li[data-background=''] > a").trigger(type);
}).bind(this));
},
background: function (type, value, $li) {
+46 -16
View File
@@ -1872,23 +1872,51 @@ $.summernote.pluginEvents.removeFormat = function (event, editor, layoutInfo, va
var fn_boutton_updateRecentColor = eventHandler.modules.toolbar.button.updateRecentColor;
eventHandler.modules.toolbar.button.updateRecentColor = function (elBtn, sEvent, sValue) {
fn_boutton_updateRecentColor.call(this, elBtn, sEvent, sValue);
var font = $(elBtn).closest('.note-color').find('.note-recent-color i')[0];
var $recentcolor = $.find('.note-recent-color i');
var $recentcolorbtn = $.find('.note-recent-color');
if (sEvent === "foreColor") {
if (sValue.indexOf('text-') !== -1) {
font.className += ' ' + sValue;
font.style.color = '';
//find last used color for fonts or for icons
//set this color into recentcolor button of both font and icon
for (var i in $recentcolor) {
var $font = $recentcolor[i];
var $button = $($recentcolorbtn[i]);
var className = $font.className.split(/\s+/);
if (sEvent === "foreColor") {
//set class for forecolor to recentcolor button font-icon
for (var k=2; k<className.length; k++) {
if (className[k].length && className[k].slice(0,5) === "text-") {
className.splice(k,1);
k--;
}
}
if (sValue.indexOf('text-') !== -1) {
$font.className = className.join(' ') + ' ' + sValue;
$font.style.color = '';
} else {
$font.className = $font.className.replace(/(^|\s+)text-\S+/, '');
$font.style.color = sValue !== 'inherit' ? sValue : "";
}
} else {
font.className = font.className.replace(/(^|\s+)text-\S+/);
font.style.color = sValue !== 'inherit' ? sValue : "";
//set class for backcolor to recentcolor button font-icon
for (var k=2; k<className.length; k++) {
if (className[k].length && className[k].slice(0,3) === "bg-") {
className.splice(k,1);
k--;
}
}
if (sValue.indexOf('bg-') !== -1) {
$font.className =className.join(' ') + ' ' + sValue;
$font.style.backgroundColor = "";
} else {
$font.className = $font.className.replace(/(^|\s+)bg-\S+/, '');
$font.style.backgroundColor = sValue !== 'inherit' ? sValue : "";
}
}
} else {
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 : "";
if (sValue !== 'inherit') {
//set attribute for color to the recentcolor button
var colorInfo = JSON.parse($button.attr('data-value'));
colorInfo[sEvent] = sValue;
$button.attr('data-value', JSON.stringify(colorInfo));
}
}
return false;
@@ -2089,8 +2117,9 @@ $.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color
}
// remove node without attributes (move content), and merge the same nodes
var className2, style, style2, $prev;
for (var i=0; i<nodes.length; i++) {
if (!dom.isImgFont(node)) {
var className2, style, style2, $prev;
for (var i=0; i<nodes.length; i++) {
node = nodes[i];
if ((dom.isText(node) || dom.isBR(node)) && !dom.isVisibleText(node)) {
@@ -2128,6 +2157,7 @@ $.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color
continue;
}
}
}
}
range.create(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset).select();
+2 -2
View File
@@ -61,7 +61,7 @@ odoo.define('web_editor.tour', function (require) {
trigger: ".note-color button.dropdown-toggle",
}, {
content: "change text color",
trigger: "button[data-event=foreColor]:first",
trigger: ".btn-group.open button[data-event=foreColor]:first",
}, {
content: "change selection to change text bg-color again",
trigger: '#editable_area > section .row > div:first h1 font:eq(2)',
@@ -218,7 +218,7 @@ odoo.define('web_editor.tour', function (require) {
}, {
content: "add ul content",
trigger: '#editable_area > section .row > div:first',
extra_trigger: 'body:not(:has(#editable_area > section .row > div:first p:eq(4), #editable_area > section .row > div:eq(3))) #editable_area > section .row > div:first p:eq(3)',
extra_trigger: 'body:not(:has(#editable_area > section .row > div:first p:eq(5), #editable_area > section .row > div:eq(3))) #editable_area > section .row > div:first p:eq(3)',
run: function () {
var html = ' <ul> '+
'\n <li> <p>Batnae municipium. </p></li>'+
+12 -5
View File
@@ -199,6 +199,7 @@ var MediaDialog = Dialog.extend({
this.final_data = [media, self.old_media];
$(document.body).trigger("media-saved", this.final_data);
$(self.old_media).trigger("save", this.final_data);
// Update editor bar after image edition (in case the image change to icon or other)
_.defer(function () {
@@ -305,11 +306,12 @@ var ImageDialog = Widget.extend({
var img = _.select(this.images, function (v) { return v.id === attachment.id; });
if (img.length) {
this.images.splice(this.images.indexOf(img[0]),1);
} else {
this.images.push(attachment);
}
} else {
this.images = [];
this.images = [attachment];
}
this.images.push(attachment);
},
save: function () {
if (this.options.select_images) {
@@ -370,6 +372,7 @@ var ImageDialog = Widget.extend({
this.push(attachment);
this.$('input.url').val('');
this.search();
this.images = [];
},
form_submit: function (event) {
var self = this;
@@ -482,20 +485,24 @@ var ImageDialog = Widget.extend({
},
select_existing: function (e) {
var $img = $(e.currentTarget);
if (!this.options.select_images) {
this.$('.o_existing_attachment_cell.o_selected').removeClass("o_selected");
$img.closest('.o_existing_attachment_cell').addClass('o_selected');
} else {
$img.closest('.o_existing_attachment_cell').toggleClass('o_selected');
}
var attachment = _.find(this.records, function (record) { return record.id === $img.data('id'); });
this.push(attachment);
this.selected_existing();
},
selected_existing: function () {
var self = this;
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('.o_existing_attachment_cell').addClass("o_selected");
return $select;
},
try_remove: function (e) {
@@ -1143,7 +1150,7 @@ var LinkDialog = Dialog.extend({
},
onkeyup: function (e) {
var $e = $(e.target);
var is_link = ($e.val()||'').length && $e.val().indexOf("@") === -1;
var is_link = $e.val().indexOf("@") === -1;
this.$('input.window-new').closest("div").toggle(is_link);
this.preview();
},
@@ -36,6 +36,12 @@ options.registry.gallery = options.Class.extend({
this._temp_mode = this.$el.find("data-mode").data("mode");
this._temp_col = this.$el.find("data-columns").data("columns");
var self = this;
this.$target.on('click', '.o_add_images', function (e) {
e.stopImmediatePropagation();
self.images_add('click');
});
},
drop_and_build_snippet: function () {
var uuid = new Date().getTime();
@@ -70,7 +76,7 @@ options.registry.gallery = options.Class.extend({
return this.$target.find("img").off('save').on('save', function (event, img) {
var $parent = $(img).parent();
$parent.addClass("saved_active");
var index = self.$target.find(".item.saved_active").index();
var index = self.$target.find(".item.active").index();
$parent.removeClass("saved_active");
self.$target.find(".carousel:first li[data-target]:eq("+index+")").css("background-image", "url("+$(img).attr("src")+")");
});
@@ -202,7 +208,7 @@ options.registry.gallery = options.Class.extend({
$slideshow = $(qweb.render('website.gallery.slideshow', params));
this.replace($slideshow);
this.$target.find(".item img").each(function (index) {
$(this).attr('data-index', index).data('index', index);
$(this).attr({'data-index': index, 'contenteditable': true});
});
this.$target.css("height", Math.round(window.innerHeight*0.7));
@@ -245,7 +251,18 @@ options.registry.gallery = options.Class.extend({
},
images_rm : function (type) {
if(type !== "click") return;
this.replace($('<div class="alert alert-info css_editable_mode_display"/>').text(_t("Add Images from the 'Customize' menu")));
var $addImg = $('<div>', {
class: 'alert alert-info css_editable_mode_display text-center',
});
var $text = $('<span>', {
class: 'o_add_images',
style: 'cursor: pointer;',
text: _t(" Add Images"),
});
var $icon = $('<i>', {
class: ' fa fa-plus-circle',
});
this.replace($addImg.append($icon).append($text));
},
sizing : function () { // done via css, keep it to avoid undefined error
},
+56 -56
View File
@@ -280,7 +280,7 @@
<template id="s_image_gallery" name="Image Gallery">
<section class="o_gallery o_spc-medium o_slideshow s_image_gallery" data-columns="3" style="height: 500px; overflow: hidden;">
<div class="container">
<div class="alert alert-info css_editable_mode_display">Add Images from the 'Customize' menu</div>
<div class="alert alert-info css_editable_mode_display text-center" ><span class="o_add_images" style="cursor: pointer;"><i class="fa fa-plus-circle"/> Add Images</span></div>
</div>
</section>
</template>
@@ -735,59 +735,10 @@
<template id="snippet_options">
<t t-call="web_editor.snippet_options"/>
<div data-js='background'
data-selector="section, :not(.o_gallery > .container) > .carousel, .parallax, .s_banner .carousel-content">
<li class="dropdown-submenu">
<a tabindex="-1" href="#"><i class="fa fa-picture-o"/>Background Image</a>
<ul class="dropdown-menu">
<li data-background=""><a href="#">None</a></li>
<li class="divider"></li>
<li data-choose_image="choose_image"><a href="#"><b>Set Custom Image...</b></a></li>
<li class="divider"></li>
<li data-background="/web/image/website.s_background_image_01"><a href="#">Peak</a></li>
<li data-background="/web/image/website.s_background_image_02"><a href="#">Downtown</a></li>
<li data-background="/web/image/website.s_background_image_03"><a href="#">Panama Sky</a></li>
<li data-background="/web/image/website.s_background_image_04"><a href="#">Cubes</a></li>
<li data-background="/web/image/website.s_background_image_05"><a href="#">Building Profile</a></li>
<li data-background="/web/image/website.s_background_image_06"><a href="#">Type</a></li>
<li data-background="/web/image/website.s_background_image_07"><a href="#">People</a></li>
<li data-background="/web/image/website.s_background_image_08"><a href="#">City</a></li>
<li data-background="/web/image/website.s_background_image_09"><a href="#">Sails</a></li>
</ul>
</li>
</div>
<div data-js='background_position'
data-selector="section, :not(.o_gallery > .container) > .carousel, .s_banner .carousel-content">
<li class="background_position_li" data-background_position="background_position">
<a tabindex="-1" href="#"><i class="fa fa-arrows"/>Background Image Sizing</a>
</li>
</div>
<div data-js="colorpicker"
data-selector="section:not(.parallax), :not(.o_gallery > .container) > .carousel, .s_comparisons .panel, .s_faq_collapse .panel-body, .s_faq_collapse .panel-heading">
<li class="dropdown-submenu">
<a tabindex="-1" href="#"><i class="fa fa-eyedropper"/>Background Color</a>
<ul class="dropdown-menu">
<li></li>
</ul>
</li>
</div>
<div data-js="colorpicker"
data-selector=".s_text_block_image_fw .row > div, .s_banner .carousel-content"
data-palette-exclude="grayscale"
data-palette-default="transparent_grayscale"
data-palette-title="Overlay Color">
<li class="dropdown-submenu">
<a tabindex="-1" href="#"><i class="fa fa-eyedropper"/>Overlay color</a>
<ul class="dropdown-menu">
<li></li>
</ul>
</li>
</div>
<div data-js='gallery' data-selector=".o_gallery">
<li data-images_add="true"><a href="#"><i class="fa fa-plus-circle"/>Add images</a></li>
<li data-images_rm="true"><a href="#"><i class="fa fa-trash"/>Remove all images</a></li>
<li class="separator"/>
<li class="dropdown-submenu">
<a tabindex="-2" href="#"><i class="fa fa-magic"/>Mode</a>
<ul class="dropdown-menu">
@@ -839,9 +790,58 @@
<li data-styling="shadow"><a href="#">Shadows</a></li>
</ul>
</li>
<li class="separator"></li>
<li data-images_add="true"><a href="#"><i class="fa fa-plus-circle"/>Add images</a></li>
<li data-images_rm="true"><a href="#"><i class="fa fa-trash"/>Remove all images</a></li>
<li class="separator"/>
</div>
<div data-js='background'
data-selector="section, :not(.o_gallery > .container) > .carousel, .parallax, .s_banner .carousel-content">
<li class="dropdown-submenu">
<a tabindex="-1" href="#"><i class="fa fa-picture-o"/>Background Image</a>
<ul class="dropdown-menu">
<li data-choose_image="choose_image"><a href="#"><b>Set Custom Image...</b></a></li>
<li class="divider"></li>
<li data-background="" class="none"><a href="#">None</a></li>
<li class="divider"></li>
<li data-background="/web/image/website.s_background_image_01"><a href="#">Peak</a></li>
<li data-background="/web/image/website.s_background_image_02"><a href="#">Downtown</a></li>
<li data-background="/web/image/website.s_background_image_03"><a href="#">Panama Sky</a></li>
<li data-background="/web/image/website.s_background_image_04"><a href="#">Cubes</a></li>
<li data-background="/web/image/website.s_background_image_05"><a href="#">Building Profile</a></li>
<li data-background="/web/image/website.s_background_image_06"><a href="#">Type</a></li>
<li data-background="/web/image/website.s_background_image_07"><a href="#">People</a></li>
<li data-background="/web/image/website.s_background_image_08"><a href="#">City</a></li>
<li data-background="/web/image/website.s_background_image_09"><a href="#">Sails</a></li>
</ul>
</li>
</div>
<div data-js='background_position'
data-selector="section, :not(.o_gallery > .container) > .carousel, .s_banner .carousel-content">
<li class="background_position_li" data-background_position="background_position">
<a tabindex="-1" href="#"><i class="fa fa-arrows"/>Background Image Sizing</a>
</li>
</div>
<div data-js="colorpicker"
data-selector="section:not(.parallax), :not(.o_gallery > .container) > .carousel">
<li class="dropdown-submenu">
<a tabindex="-1" href="#"><i class="fa fa-eyedropper"/>Background Color</a>
<ul class="dropdown-menu">
<li></li>
</ul>
</li>
</div>
<div data-js="colorpicker"
data-selector=".s_text_block_image_fw .row > div, .s_banner .carousel-content"
data-palette-exclude="grayscale"
data-palette-default="transparent_grayscale"
data-palette-title="Overlay Color">
<li class="dropdown-submenu">
<a tabindex="-1" href="#"><i class="fa fa-eyedropper"/>Overlay color</a>
<ul class="dropdown-menu">
<li></li>
</ul>
</li>
</div>
<div data-js='gallery_img' data-selector=".o_gallery img">
@@ -45,9 +45,9 @@
<li class="dropdown" id="customize-menu">
<a class="dropdown-toggle waves" data-toggle="dropdown" href="#" id="customize-menu-button">Customize</a>
<ul class="dropdown-menu" role="menu">
<li id="html_editor"><a data-action="ace" href="#advanced-view-editor">HTML/CSS Editor</a></li>
<li id="theme_customize"><a href="#">Customize Theme</a></li>
<li id="install_apps"><a href="/web#return_label=Website&amp;action=website.action_module_website">Install Apps</a></li>
<li id="html_editor"><a data-action="ace" href="#advanced-view-editor">HTML/CSS Editor</a></li>
<li id="install_apps"><a href="/web#action=website.action_website_configuration">Add Features</a></li>
<li class="divider"/>
</ul>
</li>
@@ -499,6 +499,12 @@ ul.wizard li {
background: #fbfbfb;
}
ul.wizard li .o_link_disable{
text-decoration: none;
color: inherit;
cursor: text;
}
ul.wizard li .chevron {
position: absolute;
top: 0;
+15 -22
View File
@@ -480,7 +480,7 @@
<span t-field="product.availability_warning" />
</div>
<hr t-if="product.description_sale" />
<div>
<div class="o_not_editable">
<p t-field="product.description_sale" class="text-muted" />
</div>
<hr />
@@ -731,29 +731,22 @@
<template id="wizard_checkout" name="Wizard Checkout">
<ul class="wizard pull-right hidden-xs">
<li t-att-class="step==10 and 'text-primary' or 'text-muted'" id="step10">
<t t-if="step&gt;10 and step&lt;50">
<a href="/shop/cart" class="text-success">
Review Order<span class="chevron"></span>
</a>
</t>
<t t-if="not (step&gt;10 and step&lt;50)">
Review Order<span class="chevron"></span>
</t>
<t t-set="step_review_order" t-value="step&gt;10 and step&lt;50"/>
<a t-att-href="step_review_order and '/shop/cart' or '#'" t-att-class="step_review_order and 'text-success' or 'o_link_disable'">
<span>Review Order</span>
</a>
<span class="chevron"/>
</li>
<li t-att-class="(step==20 and 'text-primary') or 'text-muted'" id="step20">
<t t-if="step&gt;20 and step&lt;50">
<a href="/shop/checkout" class="text-success">
<!-- billing if not loggedin - TODO -->
<t>Billing</t>
<t t-if="not website_sale_order or not website_sale_order.website_order_line or not website_sale_order.only_services" groups="sale.group_delivery_invoice_address"> &amp; Shipping</t>
<span class="chevron"/>
</a>
</t>
<t t-if="not (step&gt;20 and step&lt;50)">
<t>Billing</t>
<t t-if="not website_sale_order or not website_sale_order.website_order_line or not website_sale_order.only_services" groups="sale.group_delivery_invoice_address"> &amp; Shipping</t>
<!-- why website_sale_order is not set here ? -->
<t t-set="step_billing" t-value="step&gt;20 and step&lt;50"/>
<a t-att-href="step_billing and '/shop/checkout' or '#'" t-att-class="step_billing and 'text-success' or ('o_link_disable' + ('' if step == 20 else ' text-muted'))">
<!-- billing if not loggedin - TODO -->
<t t-set="website_sale_order" t-value="website.sale_get_order()" />
<span>Billing</span>
<t t-if="not website_sale_order or not website_sale_order.website_order_line or not website_sale_order.only_services"><span> &amp; Shipping</span></t>
<span class="chevron"/>
</t>
</a>
</li>
<li t-att-class="(step==40 and 'text-primary') or 'text-muted'" id="step40">
Payment<span class="chevron"></span>
@@ -1480,7 +1473,7 @@
<div class="container oe_website_sale">
<div class="row">
<div class="col-md-9">
<h1 class="mb32">Order <em t-field="order.name" /> <t t-if="order.state == 'sale'">Confirmed</t></h1>
<h1 class="mb32"><span>Order</span> <em t-field="order.name" /> <t t-if="order.state == 'sale'"><span>Confirmed</span></t></h1>
<div class="thanks_msg">
<h2>Thank you for your order.
<a class="btn btn-primary pull-right hidden-xs" href="/shop/print" target="_blank"><i class="fa fa-print"></i> Print</a>