5 openerp.website = website;
7 website.translatable = !!$('html').data('translatable');
9 /* ----------------------------------------------------
11 ---------------------------------------------------- */
12 website.get_context = function (dict) {
13 var html = document.documentElement;
15 lang: html.getAttribute('lang').replace('-', '_'),
16 website_id: html.getAttribute('data-website-id')|0
20 website.parseQS = function (qs) {
23 pl = /\+/g, // Regex for replacing addition symbol with a space
24 search = /([^&=]+)=?([^&]*)/g;
26 while ((match = search.exec(qs))) {
27 var name = decodeURIComponent(match[1].replace(pl, " "));
28 var value = decodeURIComponent(match[2].replace(pl, " "));
35 website.parseSearch = function () {
37 parsedSearch = website.parseQS(window.location.search.substring(1));
42 website.parseHash = function () {
43 return website.parseQS(window.location.hash.substring(1));
46 website.reload = function () {
47 location.hash = "scrollTop=" + window.document.body.scrollTop;
48 if (location.search.indexOf("enable_editor") > -1) {
49 window.location.href = window.location.href.replace(/enable_editor(=[^&]*)?/g, '');
51 window.location.reload();
55 /* ----------------------------------------------------
57 ---------------------------------------------------- */
59 website.prompt = function (options) {
61 * A bootstrapped version of prompt() albeit asynchronous
62 * This was built to quickly prompt the user with a single field.
63 * For anything more complex, please use editor.Dialog class
67 * website.prompt("What... is your quest ?").then(function (answer) {
68 * arthur.reply(answer || "To seek the Holy Grail.");
72 * select: "Please choose your destiny",
74 * return [ [0, "Sub-Zero"], [1, "Robo-Ky"] ];
76 * }).then(function (answer) {
77 * mame_station.loadCharacter(answer);
80 * @param {Object|String} options A set of options used to configure the prompt or the text field name if string
81 * @param {String} [options.window_title=''] title of the prompt modal
82 * @param {String} [options.input] tell the modal to use an input text field, the given value will be the field title
83 * @param {String} [options.textarea] tell the modal to use a textarea field, the given value will be the field title
84 * @param {String} [options.select] tell the modal to use a select box, the given value will be the field title
85 * @param {Object} [options.default=''] default value of the field
86 * @param {Function} [options.init] optional function that takes the `field` (enhanced with a fillWith() method) and the `dialog` as parameters [can return a deferred]
88 if (typeof options === 'string') {
96 'default': '', // dict notation for IE<9
100 var type = _.intersection(Object.keys(options), ['input', 'textarea', 'select']);
101 type = type.length ? type[0] : 'text';
102 options.field_type = type;
103 options.field_name = options.field_name || options[type];
105 var def = $.Deferred();
106 var dialog = $(openerp.qweb.render('website.prompt', options)).appendTo("body");
107 options.$dialog = dialog;
108 var field = dialog.find(options.field_type).first();
109 field.val(options['default']); // dict notation for IE<9
110 field.fillWith = function (data) {
111 if (field.is('select')) {
112 var select = field[0];
113 data.forEach(function (item) {
114 select.options[select.options.length] = new Option(item[1], item[0]);
120 var init = options.init(field, dialog);
121 $.when(init).then(function (fill) {
123 field.fillWith(fill);
125 dialog.modal('show');
127 dialog.on('click', '.btn-primary', function () {
128 def.resolve(field.val(), field, dialog);
130 $('.modal-backdrop').remove();
133 dialog.on('hidden.bs.modal', function () {
136 $('.modal-backdrop').remove();
138 if (field.is('input[type="text"], select')) {
139 field.keypress(function (e) {
142 dialog.find('.btn-primary').trigger('click');
149 website.error = function(data, url) {
150 var $error = $(openerp.qweb.render('website.error_dialog', {
151 'title': data.data ? data.data.arguments[0] : "",
152 'message': data.data ? data.data.arguments[1] : data.statusText,
155 $error.appendTo("body");
156 $error.modal('show');
159 website.form = function (url, method, params) {
160 var form = document.createElement('form');
161 form.setAttribute('action', url);
162 form.setAttribute('method', method);
163 _.each(params, function (v, k) {
164 var param = document.createElement('input');
165 param.setAttribute('type', 'hidden');
166 param.setAttribute('name', k);
167 param.setAttribute('value', v);
168 form.appendChild(param);
170 document.body.appendChild(form);
174 website.init_kanban = function ($kanban) {
175 $('.js_kanban_col', $kanban).each(function () {
177 var $pagination = $('.pagination', $col);
178 if(!$pagination.size()) {
182 var page_count = $col.data('page_count');
183 var scope = $pagination.last().find("li").size()-2;
184 var kanban_url_col = $pagination.find("li a:first").attr("href").replace(/[0-9]+$/, '');
187 'domain': $col.data('domain'),
188 'model': $col.data('model'),
189 'template': $col.data('template'),
190 'step': $col.data('step'),
191 'orderby': $col.data('orderby')
194 $pagination.on('click', 'a', function (ev) {
196 var $a = $(ev.target);
197 if($a.parent().hasClass('active')) {
201 var page = +$a.attr("href").split(",").pop().split('-')[1];
204 $.post('/website/kanban', data, function (col) {
205 $col.find("> .thumbnail").remove();
206 $pagination.last().before(col);
209 var page_start = page - parseInt(Math.floor((scope-1)/2), 10);
210 if (page_start < 1 ) page_start = 1;
211 var page_end = page_start + (scope-1);
212 if (page_end > page_count ) page_end = page_count;
214 if (page_end - page_start < scope) {
215 page_start = page_end - scope > 0 ? page_end - scope : 1;
218 $pagination.find('li.prev a').attr("href", kanban_url_col+(page-1 > 0 ? page-1 : 1));
219 $pagination.find('li.next a').attr("href", kanban_url_col+(page < page_end ? page+1 : page_end));
220 for(var i=0; i < scope; i++) {
221 $pagination.find('li:not(.prev):not(.next):eq('+i+') a').attr("href", kanban_url_col+(page_start+i)).html(page_start+i);
223 $pagination.find('li.active').removeClass('active');
224 $pagination.find('li:has(a[href="'+kanban_url_col+page+'"])').addClass('active');
231 /* ----------------------------------------------------
232 Async Ready and Template loading
233 ---------------------------------------------------- */
234 var templates_def = $.Deferred().resolve();
235 website.add_template_file = function(template) {
236 templates_def = templates_def.then(function() {
237 var def = $.Deferred();
238 openerp.qweb.add_template(template, function(err) {
249 website.add_template_file('/website/static/src/xml/website.xml');
251 website.dom_ready = $.Deferred();
252 $(document).ready(function () {
253 website.dom_ready.resolve();
255 if($.fn.placeholder) $('input, textarea').placeholder();
259 * Execute a function if the dom contains at least one element matched
260 * through the given jQuery selector. Will first wait for the dom to be ready.
262 * @param {String} selector A jQuery selector used to match the element(s)
263 * @param {Function} fn Callback to execute if at least one element has been matched
265 website.if_dom_contains = function(selector, fn) {
266 website.dom_ready.then(function () {
267 var elems = $(selector);
274 var all_ready = null;
276 * Returns a deferred resolved when the templates are loaded
277 * and the Widgets can be instanciated.
279 website.ready = function() {
281 all_ready = website.dom_ready.then(function () {
282 return templates_def;
283 }).then(function () {
284 // display button if they are at least one editable zone in the page (check the branding)
285 if (!!$('[data-oe-model]').size()) {
286 $("#oe_editzone").show();
288 //backwards compatibility with 8.0RC1 templates - Drop next line in master!
289 $("#oe_editzone button").show();
292 if ($('html').data('website-id')) {
293 website.id = $('html').data('website-id');
294 website.session = new openerp.Session();
295 var modules = ['website'];
296 return openerp._t.database.load_translations(website.session, modules, website.get_context().lang);
303 website.inject_tour = function() {
304 // if a tour is active inject tour js
307 website.dom_ready.then(function () {
308 /* ----- PUBLISHING STUFF ---- */
309 $(document).on('click', '.js_publish_management .js_publish_btn', function () {
310 var $data = $(this).parents(".js_publish_management:first");
312 openerp.jsonRpc($data.data('controller') || '/website/publish', 'call', {'id': +$data.data('id'), 'object': $data.data('object')})
313 .then(function (result) {
314 $data.toggleClass("css_unpublished css_published");
315 $data.parents("[data-publish]").attr("data-publish", +result ? 'on' : 'off');
316 }).fail(function (err, data) {
317 website.error(data, '/web#return_label=Website&model='+$data.data('object')+'&id='+$data.data('id'));
321 /* ----- KANBAN WEBSITE ---- */
322 $('.js_kanban').each(function () {
323 website.init_kanban(this);
326 setTimeout(function () {
327 if (window.location.hash.indexOf("scrollTop=") > -1) {
328 window.document.body.scrollTop = +location.hash.match(/scrollTop=([0-9]+)/)[1];
332 /* ----- WEBSITE TOP BAR ---- */
333 var $collapse = $('#oe_applications ul.dropdown-menu').clone()
334 .attr("id", "oe_applications_collapse")
335 .attr("class", "nav navbar-nav navbar-left navbar-collapse collapse");
336 $('#oe_applications').before($collapse);
337 $collapse.wrap('<div class="visible-xs"/>');
338 $('[data-target="#oe_applications"]').attr("data-target", "#oe_applications_collapse");