summaryrefslogtreecommitdiff
path: root/addons/website/static/src
diff options
context:
space:
mode:
authorqsm-odoo <qsm@odoo.com>2018-08-03 15:50:29 +0200
committerqsm-odoo <qsm@odoo.com>2018-08-10 16:47:53 +0200
commitbcbfd96740eaeaddc7ef85d298de232bc8687719 (patch)
treec0476f75dac786bbe0d70073bc1c65aefb4622ea /addons/website/static/src
parent358f050555b77c529b82adeccea904d74ba4f83f (diff)
[REF] website: review customize dialog JS
Diffstat (limited to 'addons/website/static/src')
-rw-r--r--addons/website/static/src/js/widgets/theme.js395
1 files changed, 180 insertions, 215 deletions
diff --git a/addons/website/static/src/js/widgets/theme.js b/addons/website/static/src/js/widgets/theme.js
index 766e77e4dd4..8e8eb20d030 100644
--- a/addons/website/static/src/js/widgets/theme.js
+++ b/addons/website/static/src/js/widgets/theme.js
@@ -1,31 +1,33 @@
odoo.define('website.theme', function (require) {
'use strict';
-var ajax = require('web.ajax');
+var config = require('web.config');
var core = require('web.core');
-var session = require('web.session');
-var Widget = require('web.Widget');
+var Dialog = require('web.Dialog');
var weContext = require('web_editor.context');
var websiteNavbarData = require('website.navbar');
-var QWeb = core.qweb;
+var _t = core._t;
var templateDef = null;
-var ThemeCustomizeDialog = Widget.extend({
+var ThemeCustomizeDialog = Dialog.extend({
template: 'website.theme_customize',
events: {
- 'change input[data-xmlid],input[data-enable],input[data-disable]': 'change_selection',
- 'mousedown label:has(input[data-xmlid],input[data-enable],input[data-disable])': function (event) {
- var self = this;
- this.time_select = _.defer(function () {
- var input = $(event.target).find('input').length ? $(event.target).find('input') : $(event.target).parent().find('input');
- self.on_select(input, event);
- });
- },
- 'click .close': 'close',
- 'click': 'click',
+ 'change [data-xmlid], [data-enable], [data-disable]': '_onChange',
+ },
+
+ /**
+ * @constructor
+ */
+ init: function (parent, options) {
+ this._super(parent, _.extend({
+ title: _t("Customize this theme"),
+ }, options || {}));
},
+ /**
+ * @override
+ */
willStart: function () {
if (templateDef === null) {
templateDef = this._rpc({
@@ -33,246 +35,209 @@ var ThemeCustomizeDialog = Widget.extend({
method: 'read_template',
args: ['website.theme_customize', weContext.get()],
}).then(function (data) {
- return QWeb.add_template(data);
+ return core.qweb.add_template(data);
});
}
return $.when(this._super.apply(this, arguments), templateDef);
},
+ /**
+ * @override
+ */
start: function () {
var self = this;
- this.timer = null;
- this.reload = false;
- this.flag = false;
- this.active_select_tags();
- this.$inputs = this.$('input[data-xmlid],input[data-enable],input[data-disable]');
- setTimeout(function () {self.$el.addClass('in');}, 0);
- this.keydown_escape = function (event) {
- if (event.keyCode === 27) {
- self.close();
- }
- };
- $(document).on('keydown', this.keydown_escape);
- return this.load_xml_data().then(function () {
- self.flag = true;
- });
- },
- active_select_tags: function () {
- var uniqueID = 0;
- var self = this;
- var $selects = this.$('select:has(option[data-xmlid],option[data-enable],option[data-disable])');
- $selects.each(function () {
- uniqueID++;
- var $select = $(this);
- var $options = $select.find('option[data-xmlid], option[data-enable], option[data-disable]');
- $options.each(function () {
- var $option = $(this);
- var $input = $('<input style="display: none;" type="radio" name="theme_customize_modal-select-'+uniqueID+'"/>');
- $input.attr('id', $option.attr('id'));
- $input.attr('data-xmlid', $option.data('xmlid'));
- $input.attr('data-enable', $option.data('enable'));
- $input.attr('data-disable', $option.data('disable'));
- $option.removeAttr('id');
- $option.data('input', $input);
- $input.on('update', function () {
- $option.attr('selected', $(this).prop('checked'));
- });
- self.$el.append($input);
- });
- $select.data('value', $options.first());
- $options.first().attr('selected', true);
- });
- $selects.change(function () {
- var $option = $(this).find('option:selected');
- $(this).data('value').data('input').prop('checked', true).change();
- $(this).data('value', $option);
- $option.data('input').change();
- });
+
+ this.$modal.addClass('o_theme_customize_modal');
+
+ this.$inputs = this.$('[data-xmlid], [data-enable], [data-disable]');
+
+ return $.when(
+ this._super.apply(this, arguments),
+ this._loadViews()
+ );
},
- load_xml_data: function () {
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ _loadViews: function () {
var self = this;
- $('#theme_error').remove();
return this._rpc({
route: '/website/theme_customize_get',
params: {
- xml_ids: this.get_xml_ids(this.$inputs),
+ xml_ids: this._getXMLIDs(this.$inputs),
},
- }).done(function (data) {
- self.$inputs.filter('[data-xmlid=""]').prop('checked', true).change();
- self.$inputs.filter('[data-xmlid]:not([data-xmlid=""])').each(function () {
- if (!_.difference(self.get_xml_ids($(this)), data[1]).length) {
- $(this).prop('checked', false).trigger('change', true);
+ }).done(function (data) {
+ self.$inputs.prop('checked', false);
+ _.each(self.$inputs.filter('[data-xmlid]:not([data-xmlid=""])'), function (input) {
+ var $input = $(input);
+ if (!_.difference(self._getXMLIDs($input), data[0]).length) {
+ $input.prop('checked', true);
}
- if (!_.difference(self.get_xml_ids($(this)), data[0]).length) {
- $(this).prop('checked', true).trigger('change', true);
+ });
+ _.each(self.$inputs.filter('[data-xmlid=""]'), function (input) {
+ var $input = $(input);
+ if (!self.$inputs.filter('[name="' + $input.attr('name') + '"]:checked').length) {
+ $input.prop('checked', true);
}
});
+ self._setActive();
}).fail(function (d, error) {
- $('body').prepend($('<div id="theme_error"/>').text(error.data.message));
+ Dialog.alert(this, error.data.message)
});
},
- get_inputs: function (string) {
- return this.$inputs.filter('#'+string.split(/\s*,\s*/).join(', #'));
+ /**
+ * @private
+ */
+ _getInputs: function (string) {
+ if (!string) {
+ return $();
+ }
+ return this.$inputs.filter('#' + string.replace(/\s*,\s*/g, ', #'));
},
- get_xml_ids: function ($inputs) {
- var xml_ids = [];
- $inputs.each(function () {
- if ($(this).data('xmlid') && $(this).data('xmlid').length) {
- xml_ids = xml_ids.concat($(this).data('xmlid').split(/\s*,\s*/));
+ /**
+ * @private
+ */
+ _getXMLIDs: function ($inputs) {
+ var xmlIDs = [];
+ _.each($inputs, function (input) {
+ var $input = $(input);
+ var xmlID = $input.data('xmlid');
+ if (xmlID) {
+ xmlIDs = xmlIDs.concat(xmlID.split(/\s*,\s*/));
}
});
- return xml_ids;
+ return xmlIDs;
},
- update_style: function (enable, disable, reload) {
- if (this.$el.hasClass('loading')) {
- return;
- }
- this.$el.addClass('loading');
+ /**
+ * @abstract
+ * @private
+ */
+ _processChange: function ($inputs, event) {},
+ /**
+ * @private
+ */
+ _setActive: function () {
+ var self = this;
- if (!reload && session.debug !== 'assets') {
- var self = this;
- return this._rpc({
- route: '/website/theme_customize',
- params: {
- enable: enable,
- disable: disable,
- get_bundle: true,
- },
- }).then(function (bundleHTML) {
- var $links = $('link[href*=".assets_frontend"]');
- var $newLinks = $(bundleHTML).filter('link');
+ // Look at all options to see if they are enabled or disabled
+ var $enable = this.$inputs.filter('[data-xmlid]:checked');
+ var $disable = this.$inputs.filter('[data-xmlid]:not(:checked)');
+
+ // Mark the labels as checked accordingly
+ this.$('label').removeClass('checked');
+ $enable.closest('label').addClass('checked');
- var linksLoaded = $.Deferred();
- var nbLoaded = 0;
- $newLinks.on('load', function (e) {
- if (++nbLoaded >= $newLinks.length) {
- linksLoaded.resolve();
- }
- });
- $newLinks.on('error', function (e) {
- linksLoaded.reject();
- window.location.hash = 'theme=true';
- window.location.reload();
- });
+ // Mark the option sets as checked if all their option are checked/unchecked
+ var $sets = this.$inputs.filter('[data-enable], [data-disable]').not('[data-xmlid]');
+ _.each($sets, function (set) {
+ var $set = $(set);
+ var checked = true;
+ if (self._getInputs($set.data('enable')).not(':checked').length) {
+ checked = false;
+ }
+ if (self._getInputs($set.data('disable')).filter(':checked').length) {
+ checked = false;
+ }
+ $set.prop('checked', checked).closest('label').toggleClass('checked', checked);
+ });
+ },
+ /**
+ * @private
+ */
+ _updateStyle: function (enable, disable, reload) {
+ this.$modal.addClass('loading');
- $links.last().after($newLinks);
- return linksLoaded.then(function () {
- $links.remove();
- self.$el.removeClass('loading');
- });
+ if (reload || config.debug === 'assets') {
+ window.location.href = $.param.querystring('/website/theme_customize_reload', {
+ href: window.location.href,
+ enable: enable.join(','),
+ disable: disable.join(','),
});
- } else {
- var href = '/website/theme_customize_reload'+
- '?href='+encodeURIComponent(window.location.href)+
- '&enable='+encodeURIComponent(enable.join(','))+
- '&disable='+encodeURIComponent(disable.join(','));
- window.location.href = href;
return $.Deferred();
}
- },
- enable_disable: function ($inputs, enable) {
- $inputs.each(function () {
- var check = $(this).prop('checked');
- var $label = $(this).closest('label');
- $(this).prop('checked', enable);
- if (enable) $label.addClass('checked');
- else $label.removeClass('checked');
- if (check !== enable) {
- $(this).change();
- }
+
+ var self = this;
+ return this._rpc({
+ route: '/website/theme_customize',
+ params: {
+ enable: enable,
+ disable: disable,
+ get_bundle: true,
+ },
+ }).then(function (bundleHTML) {
+ var frontendLinkSelector = 'link[href*=".assets_frontend"]';
+ var $links = $(frontendLinkSelector);
+ var $newLinks = $(bundleHTML).filter(frontendLinkSelector);
+
+ var linksLoaded = $.Deferred();
+ var nbLoaded = 0;
+ $newLinks.on('load', function (e) {
+ if (++nbLoaded >= $newLinks.length) {
+ linksLoaded.resolve();
+ }
+ });
+ $newLinks.on('error', function (e) {
+ linksLoaded.reject();
+ window.location.hash = 'theme=true';
+ window.location.reload();
+ });
+
+ $links.last().after($newLinks);
+ return linksLoaded.then(function () {
+ $links.remove();
+ self.$modal.removeClass('loading');
+ });
});
},
- change_selection: function (event, init_mode) {
- var self = this;
- clearTimeout(this.time_select);
- if (this.$el.hasClass('loading')) return; // prevent to change selection when css is loading
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
- var $option = $(event.target).is('input') ? $(event.target) : $('input', event.target),
- $options = $option,
- checked = $option.prop('checked');
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onChange: function (ev) {
+ var self = this;
+
+ // Checkout the option that changed
+ var $option = $(ev.target).find('input').addBack('input');
+ var $options = $option;
+ var checked = $option.is(':checked');
+ // If it was enabled, enable/disable the related input (see data-enable, data-disable)
+ // and retain the ones that actually changed
if (checked) {
var $inputs;
- if ($option.data('enable')) {
- $inputs = this.get_inputs($option.data('enable'));
- $options = $options.add($inputs.filter(':not(:checked)'));
- this.enable_disable($inputs, true);
- }
- if ($option.data('disable')) {
- $inputs = this.get_inputs($option.data('disable'));
- $options = $options.add($inputs.filter(':checked'));
- this.enable_disable($inputs, false);
- }
- $option.closest('label').addClass('checked');
- } else {
- $option.closest('label').removeClass('checked');
+ // Input to enable
+ $inputs = this._getInputs($option.data('enable'));
+ $options = $options.add($inputs.filter(':not(:checked)'));
+ $inputs.prop('checked', true);
+ // Input to disable
+ $inputs = this._getInputs($option.data('disable'));
+ $options = $options.add($inputs.filter(':checked'));
+ $inputs.prop('checked', false);
}
+ // Look at all options to see if they are enabled or disabled
var $enable = this.$inputs.filter('[data-xmlid]:checked');
- $enable.closest('label').addClass('checked');
var $disable = this.$inputs.filter('[data-xmlid]:not(:checked)');
- $disable.closest('label').removeClass('checked');
- var $sets = this.$inputs.filter('input[data-enable]:not([data-xmlid]), input[data-disable]:not([data-xmlid])');
- $sets.each(function () {
- var $set = $(this);
- var checked = true;
- if ($set.data('enable')) {
- self.get_inputs($(this).data('enable')).each(function () {
- if (!$(this).prop('checked')) checked = false;
- });
- }
- if ($set.data('disable')) {
- self.get_inputs($(this).data('disable')).each(function () {
- if ($(this).prop('checked')) checked = false;
- });
- }
- if (checked) {
- $set.prop('checked', true).closest('label').addClass('checked');
- } else {
- $set.prop('checked', false).closest('label').removeClass('checked');
- }
- $set.trigger('update');
- });
-
- if (this.flag && $option.data('reload') && document.location.href.match(new RegExp( $option.data('reload') ))) {
- this.reload = true;
- }
+ this._setActive();
- clearTimeout(this.timer);
- if (this.flag) {
- this.timer = _.defer(function () {
- if (!init_mode) self.on_select($options, event);
- self.update_style(self.get_xml_ids($enable), self.get_xml_ids($disable), self.reload);
- self.reload = false;
- });
- } else {
- this.timer = _.defer(function () {
- if (!init_mode) self.on_select($options, event);
- self.reload = false;
- });
- }
+ // Update the style according to the whole set of options
+ self._processChange($options, ev);
+ self._updateStyle(
+ self._getXMLIDs($enable),
+ self._getXMLIDs($disable),
+ $option.data('reload') && window.location.href.match(new RegExp($option.data('reload')))
+ );
},
- /* Method call when the user change the selection or click on an input
- * @values: all changed inputs
- */
- on_select: function ($inputs, event) {
- clearTimeout(this.time_select);
- },
- click: function (event) {
- if (!$(event.target).closest('#theme_customize_modal > *').length) {
- this.close();
- }
- },
- close: function () {
- var self = this;
- $(document).off('keydown', this.keydown_escape);
- $('#theme_error').remove();
- $('link[href*=".assets_"]').removeAttr('data-loading');
- this.$el.removeClass('in');
- this.$el.addClass('out');
- setTimeout(function () {self.destroy();}, 500);
- }
});
var ThemeCustomizeMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
@@ -306,11 +271,11 @@ var ThemeCustomizeMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
* @returns {Deferred}
*/
_openThemeCustomizeDialog: function () {
- return new ThemeCustomizeDialog(this).appendTo(document.body);
+ return new ThemeCustomizeDialog(this).open();
},
});
websiteNavbarData.websiteNavbarRegistry.add(ThemeCustomizeMenu, '#theme_customize');
return ThemeCustomizeDialog;
-});
+}); \ No newline at end of file