4 openerp.website.add_template_file('/website/static/src/xml/website.theme.xml');
6 openerp.website.Theme = openerp.Widget.extend({
7 template: 'website.theme_customize',
9 'change input[data-xmlid],input[data-enable],input[data-disable]': 'change_selection',
10 'click .close': 'close',
17 this.$el.addClass("theme_customize_modal");
18 this.active_select_tags();
19 this.$inputs = $("input[data-xmlid],input[data-enable],input[data-disable]");
20 setTimeout(function () {self.$el.addClass('in');}, 0);
21 return this.load_xml_data().then(function () {
25 active_select_tags: function () {
28 var $selects = this.$('select:has(option[data-xmlid],option[data-enable],option[data-disable])');
29 $selects.each(function () {
31 var $select = $(this);
32 var $options = $select.find('option[data-xmlid], option[data-enable], option[data-disable]');
33 $options.each(function () {
34 var $option = $(this);
35 var $input = $('<input style="display: none;" type="radio" name="theme_customize_modal-select-'+uniqueID+'"/>');
36 $input.attr('id', $option.attr('id'));
37 $input.attr('data-xmlid', $option.data('xmlid'));
38 $input.attr('data-enable', $option.data('enable'));
39 $input.attr('data-disable', $option.data('disable'));
40 $option.removeAttr('id');
41 $option.data('input', $input);
42 $input.on('update', function () {
43 $option.attr('selected', $(this).prop("checked"));
45 self.$el.append($input);
47 $select.data("value", $options.first());
48 $options.first().attr("selected", true);
50 $selects.change(function () {
51 var $option = $(this).find('option:selected');
52 $(this).data("value").data("input").prop("checked", true).change();
53 $(this).data("value", $option);
54 $option.data("input").change();
57 load_xml_data: function (xml_ids) {
59 $('#theme_error').remove();
60 return openerp.jsonRpc('/website/theme_customize_get', 'call', {
61 'xml_ids': this.get_xml_ids(this.$inputs)
62 }).done(function (data) {
63 self.$inputs.filter('[data-xmlid]').each(function () {
64 if (!_.difference(self.get_xml_ids($(this)), data[1]).length) {
65 $(this).prop("checked", false).change();
67 if (!_.difference(self.get_xml_ids($(this)), data[0]).length) {
68 $(this).prop("checked", true).change();
71 }).fail(function (d, error) {
72 $('body').prepend($('<div id="theme_error"/>').text(error.data.message));
75 get_inputs: function (string) {
76 return this.$inputs.filter('#'+string.split(",").join(", #"));
78 get_xml_ids: function ($inputs) {
80 $inputs.each(function () {
81 if ($(this).data('xmlid') && $(this).data('xmlid').length) {
82 xml_ids = xml_ids.concat($(this).data('xmlid').split(","));
87 compute_stylesheets: function () {
89 self.has_error = false;
90 $('link[href*=".assets_"]').attr('data-loading', true);
91 function theme_customize_css_onload() {
92 if ($('link[data-loading]').size()) {
93 $('body').toggleClass('theme_customize_css_loading');
94 setTimeout(theme_customize_css_onload, 50);
96 $('body').removeClass('theme_customize_css_loading');
97 self.$el.removeClass("loading");
99 if (window.getComputedStyle($('button[data-toggle="collapse"]:first')[0]).getPropertyValue('position') === 'static' ||
100 window.getComputedStyle($('#theme_customize_modal')[0]).getPropertyValue('display') === 'none') {
101 if (self.has_error) {
102 window.location.hash = "theme=true";
103 window.location.reload();
105 self.has_error = true;
106 $('link[href*=".assets_"][data-error]').removeAttr('data-error').attr('data-loading', true);
107 self.update_stylesheets();
108 setTimeout(theme_customize_css_onload, 50);
113 theme_customize_css_onload();
115 update_stylesheets: function () {
116 $('link[href*=".assets_"]').each(function update () {
117 var $style = $(this);
118 var href = $style.attr("href").replace(/[^\/]+$/, new Date().getTime());
119 var $asset = $('<link rel="stylesheet" href="'+href+'"/>');
120 $asset.attr("onload", "$(this).prev().attr('disable', true).remove(); $(this).removeAttr('onload').removeAttr('onerror');");
121 $asset.attr("onerror", "$(this).prev().removeAttr('data-loading').attr('data-error','loading'); $(this).attr('disable', true).remove();");
122 $style.after($asset);
125 update_style: function (enable, disable, reload) {
127 if (this.$el.hasClass("loading")) return;
128 this.$el.addClass("loading");
130 if (!reload && $('link[href*=".assets_"]').size()) {
131 this.compute_stylesheets();
132 return openerp.jsonRpc('/website/theme_customize', 'call', {
135 }).then(function () {
136 self.update_stylesheets();
139 var href = '/website/theme_customize_reload'+
140 '?href='+encodeURIComponent(window.location.href)+
141 '&enable='+encodeURIComponent(enable.join(","))+
142 '&disable='+encodeURIComponent(disable.join(","));
143 window.location.href = href;
147 enable_disable: function (data, enable) {
149 this.$('#'+data.split(",").join(", #")).each(function () {
150 var check = $(this).prop("checked");
151 var $label = $(this).closest("label");
152 $(this).attr("checked", enable);
153 if (enable) $label.addClass("checked");
154 else $label.removeClass("checked");
155 if (check != enable) {
160 change_selection: function (event) {
162 if (this.$el.hasClass("loading")) return;
164 var $option = $(event.target),
165 checked = $option.prop("checked");
168 this.enable_disable($option.data('enable'), true);
169 this.enable_disable($option.data('disable'), false);
170 $option.closest("label").addClass("checked");
172 $option.closest("label").removeClass("checked");
174 $option.prop("checked", checked);
176 var $enable = this.$inputs.filter('[data-xmlid]:checked');
177 $enable.closest("label").addClass("checked");
178 var $disable = this.$inputs.filter('[data-xmlid]:not(:checked)');
179 $disable.closest("label").removeClass("checked");
181 var $sets = this.$inputs.filter('input[data-enable]:not([data-xmlid]), input[data-disable]:not([data-xmlid])');
182 $sets.each(function () {
185 if ($set.data("enable")) {
186 self.get_inputs($(this).data("enable")).each(function () {
187 if (!$(this).prop("checked")) checked = false;
190 if ($set.data("disable")) {
191 self.get_inputs($(this).data("disable")).each(function () {
192 if ($(this).prop("checked")) checked = false;
196 $set.prop("checked", true).closest("label").addClass("checked");
198 $set.prop("checked", false).closest("label").removeClass("checked");
200 $set.trigger('update');
203 if (this.flag && $option.data('reload') && document.location.href.match(new RegExp( $option.data('reload') ))) {
207 clearTimeout(this.timer);
209 this.timer = setTimeout(function () {
210 self.update_style(self.get_xml_ids($enable), self.get_xml_ids($disable), self.reload);
214 this.timer = setTimeout(function () { self.reload = false; },0);
219 $('#theme_error').remove();
220 $('link[href*=".assets_"]').removeAttr('data-loading');
221 this.$el.removeClass('in');
222 this.$el.addClass('out');
223 setTimeout(function () {self.destroy();}, 500);
227 function themeError(message) {
230 if (message.indexOf('lessc')) {
231 message = '<span class="text-muted">' + message + "</span><br/><br/>" + _t("Please install or update node-less");
234 var $error = $( openerp.qweb.render('website.error_dialog', {
235 title: _t("Theme Error"),
238 $error.appendTo("body").modal();
239 $error.on('hidden.bs.modal', function () {
245 openerp.website.ready().done(function() {
246 function theme_customize() {
247 var error = window.getComputedStyle(document.body, ':before').getPropertyValue('content');
248 if (error && error !== 'none') {
249 return themeError(eval(error));
251 var Theme = openerp.website.Theme;
252 if (Theme.open && !Theme.open.isDestroyed()) return;
253 Theme.open = new Theme();
254 Theme.open.appendTo("body");
256 $(document).on('click', "#theme_customize a",theme_customize);
257 if ((window.location.hash || "").indexOf("theme=true") !== -1) {
259 window.location.hash = "";