[FIX] website translation won't properly find inherited view's id
[odoo/odoo.git] / addons / website / static / src / js / website.js
1 (function() {
2     "use strict";
3
4     var website = {};
5     // The following line can be removed in 2017
6     openerp.website = website;
7
8     website.get_context = function (dict) {
9         var html = document.documentElement;
10         return _.extend({
11             lang: html.getAttribute('lang').replace('-', '_'),
12             website_id: html.getAttribute('data-website-id')|0
13         }, dict);
14     };
15
16     website.parseQS = function (qs) {
17         var match,
18             params = {},
19             pl     = /\+/g,  // Regex for replacing addition symbol with a space
20             search = /([^&=]+)=?([^&]*)/g;
21
22         while ((match = search.exec(qs))) {
23             var name = decodeURIComponent(match[1].replace(pl, " "));
24             var value = decodeURIComponent(match[2].replace(pl, " "));
25             params[name] = value;
26         }
27         return params;
28     };
29
30     var parsedSearch;
31     website.parseSearch = function () {
32         if (!parsedSearch) {
33             parsedSearch = website.parseQS(window.location.search.substring(1));
34         }
35         return parsedSearch;
36     };
37     website.parseHash = function () {
38         return website.parseQS(window.location.hash.substring(1));
39     };
40
41     /* ----- TEMPLATE LOADING ---- */
42     var templates_def = $.Deferred().resolve();
43     website.add_template_file = function(template) {
44         templates_def = templates_def.then(function() {
45             var def = $.Deferred();
46             openerp.qweb.add_template(template, function(err) {
47                 if (err) {
48                     def.reject(err);
49                 } else {
50                     def.resolve();
51                 }
52             });
53             return def;
54         });
55     };
56     website.add_template_file('/website/static/src/xml/website.xml');
57     website.reload = function () {
58         location.hash = "scrollTop=" + window.document.body.scrollTop;
59         if (location.search.indexOf("enable_editor") > -1) {
60             window.location.href = window.location.href.replace(/enable_editor(=[^&]*)?/g, '');
61         } else {
62             window.location.reload();
63         }
64     };
65
66     var all_ready = null;
67     var dom_ready = website.dom_ready = $.Deferred();
68     $(document).ready(function () {
69         website.is_editable = website.is_editable || $('html').data('editable');
70         website.is_editable_button= website.is_editable_button || $('html').data('editable');
71         dom_ready.resolve();
72         // fix for ie
73         if($.fn.placeholder) $('input, textarea').placeholder();
74     });
75
76     website.init_kanban = function ($kanban) {
77         $('.js_kanban_col', $kanban).each(function () {
78             var $col = $(this);
79             var $pagination = $('.pagination', $col);
80             if(!$pagination.size()) {
81                 return;
82             }
83
84             var page_count =  $col.data('page_count');
85             var scope = $pagination.last().find("li").size()-2;
86             var kanban_url_col = $pagination.find("li a:first").attr("href").replace(/[0-9]+$/, '');
87
88             var data = {
89                 'domain': $col.data('domain'),
90                 'model': $col.data('model'),
91                 'template': $col.data('template'),
92                 'step': $col.data('step'),
93                 'orderby': $col.data('orderby')
94             };
95
96             $pagination.on('click', 'a', function (ev) {
97                 ev.preventDefault();
98                 var $a = $(ev.target);
99                 if($a.parent().hasClass('active')) {
100                     return;
101                 }
102
103                 var page = +$a.attr("href").split(",").pop().split('-')[1];
104                 data['page'] = page;
105
106                 $.post('/website/kanban/', data, function (col) {
107                     $col.find("> .thumbnail").remove();
108                     $pagination.last().before(col);
109                 });
110
111                 var page_start = page - parseInt(Math.floor((scope-1)/2), 10);
112                 if (page_start < 1 ) page_start = 1;
113                 var page_end = page_start + (scope-1);
114                 if (page_end > page_count ) page_end = page_count;
115
116                 if (page_end - page_start < scope) {
117                     page_start = page_end - scope > 0 ? page_end - scope : 1;
118                 }
119
120                 $pagination.find('li.prev a').attr("href", kanban_url_col+(page-1 > 0 ? page-1 : 1));
121                 $pagination.find('li.next a').attr("href", kanban_url_col+(page < page_end ? page+1 : page_end));
122                 for(var i=0; i < scope; i++) {
123                     $pagination.find('li:not(.prev):not(.next):eq('+i+') a').attr("href", kanban_url_col+(page_start+i)).html(page_start+i);
124                 }
125                 $pagination.find('li.active').removeClass('active');
126                 $pagination.find('li:has(a[href="'+kanban_url_col+page+'"])').addClass('active');
127
128             });
129
130         });
131     };
132
133     /**
134      * Returns a deferred resolved when the templates are loaded
135      * and the Widgets can be instanciated.
136      */
137     website.ready = function() {
138         if (!all_ready) {
139             all_ready = dom_ready.then(function () {
140                 return templates_def;
141             }).then(function () {
142                 if (website.is_editable) {
143                     website.id = $('html').data('website-id');
144                     website.session = new openerp.Session();
145                     var modules = ['website'];
146                     return openerp._t.database.load_translations(website.session, modules, website.get_context().lang);
147                 }
148             }).promise();
149         }
150         return all_ready;
151     };
152
153     website.error = function(data, url) {
154         var $error = $(openerp.qweb.render('website.error_dialog', {
155             'title': data.data ? data.data.arguments[0] : "",
156             'message': data.data ? data.data.arguments[1] : data.statusText,
157             'backend_url': url
158         }));
159         $error.appendTo("body");
160         $error.modal('show');
161     };
162
163     website.prompt = function (options) {
164         /**
165          * A bootstrapped version of prompt() albeit asynchronous
166          * This was built to quickly prompt the user with a single field.
167          * For anything more complex, please use editor.Dialog class
168          *
169          * Usage Ex:
170          *
171          * website.prompt("What... is your quest ?").then(function (answer) {
172          *     arthur.reply(answer || "To seek the Holy Grail.");
173          * });
174          *
175          * website.prompt({
176          *     select: "Please choose your destiny",
177          *     init: function() {
178          *         return [ [0, "Sub-Zero"], [1, "Robo-Ky"] ];
179          *     }
180          * }).then(function (answer) {
181          *     mame_station.loadCharacter(answer);
182          * });
183          *
184          * @param {Object|String} options A set of options used to configure the prompt or the text field name if string
185          * @param {String} [options.window_title=''] title of the prompt modal
186          * @param {String} [options.input] tell the modal to use an input text field, the given value will be the field title
187          * @param {String} [options.textarea] tell the modal to use a textarea field, the given value will be the field title
188          * @param {String} [options.select] tell the modal to use a select box, the given value will be the field title
189          * @param {Object} [options.default=''] default value of the field
190          * @param {Function} [options.init] optional function that takes the `field` (enhanced with a fillWith() method) and the `dialog` as parameters [can return a deferred]
191          */
192         if (typeof options === 'string') {
193             options = {
194                 text: options
195             };
196         }
197         options = _.extend({
198             window_title: '',
199             field_name: '',
200             default: '',
201             init: function() {}
202         }, options || {});
203
204         var type = _.intersection(Object.keys(options), ['input', 'textarea', 'select']);
205         type = type.length ? type[0] : 'text';
206         options.field_type = type;
207         options.field_name = options.field_name || options[type];
208
209         var def = $.Deferred();
210         var dialog = $(openerp.qweb.render('website.prompt', options)).appendTo("body");
211         options.$dialog = dialog;
212         var field = dialog.find(options.field_type).first();
213         field.val(options.default);
214         field.fillWith = function (data) {
215             if (field.is('select')) {
216                 var select = field[0];
217                 data.forEach(function (item) {
218                     select.options[select.options.length] = new Option(item[1], item[0]);
219                 });
220             } else {
221                 field.val(data);
222             }
223         };
224         var init = options.init(field, dialog);
225         $.when(init).then(function (fill) {
226             if (fill) {
227                 field.fillWith(fill);
228             }
229             dialog.modal('show');
230             field.focus();
231             dialog.on('click', '.btn-primary', function () {
232                 def.resolve(field.val(), field, dialog);
233                 dialog.remove();
234             });
235         });
236         dialog.on('hidden.bs.modal', function () {
237             def.reject();
238             dialog.remove();
239         });
240         if (field.is('input[type="text"], select')) {
241             field.keypress(function (e) {
242                 if (e.which == 13) {
243                     e.preventDefault();
244                     dialog.find('.btn-primary').trigger('click');
245                 }
246             });
247         }
248         return def;
249     };
250
251     website.form = function (url, method, params) {
252         var form = document.createElement('form');
253         form.setAttribute('action', url);
254         form.setAttribute('method', method);
255         _.each(params, function (v, k) {
256             var param = document.createElement('input');
257             param.setAttribute('type', 'hidden');
258             param.setAttribute('name', k);
259             param.setAttribute('value', v);
260             form.appendChild(param);
261         });
262         document.body.appendChild(form);
263         form.submit();
264     };
265
266     dom_ready.then(function () {
267
268         /* ----- BOOTSTRAP  STUFF ---- */
269         // $('.js_tooltip').bstooltip();
270
271         /* ----- PUBLISHING STUFF ---- */
272         $(document).on('click', '.js_publish_management .js_publish_btn', function () {
273             var $data = $(this).parents(".js_publish_management:first");
274             var self=this;
275             openerp.jsonRpc($data.data('controller') || '/website/publish', 'call', {'id': +$data.data('id'), 'object': $data.data('object')})
276                 .then(function (result) {
277                     $data.toggleClass("css_unpublished css_published");
278                     $data.parents("[data-publish]").attr("data-publish", +result ? 'on' : 'off');
279                 }).fail(function (err, data) {
280                     website.error(data, '/web#return_label=Website&model='+$data.data('object')+'&id='+$data.data('id'));
281                 });
282         });
283
284         /* ----- KANBAN WEBSITE ---- */
285         $('.js_kanban').each(function () {
286             website.init_kanban(this);
287         });
288
289         setTimeout(function () {
290             if (window.location.hash.indexOf("scrollTop=") > -1) {
291                 window.document.body.scrollTop = +location.hash.match(/scrollTop=([0-9]+)/)[1];
292             }
293         },0);
294     });
295
296     return website;
297 })();