diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py index d553acf363a..ea982bbe563 100644 --- a/addons/website/models/ir_qweb.py +++ b/addons/website/models/ir_qweb.py @@ -25,6 +25,7 @@ import openerp from openerp.osv import orm, fields from openerp.tools import ustr, DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT from openerp.addons.web.http import request +from openerp.addons.base.ir import ir_qweb REMOTE_CONNECTION_TIMEOUT = 2.5 @@ -198,7 +199,6 @@ class ManyToOne(orm.AbstractModel): matches = self.pool[column._obj].name_search( cr, uid, name=element.text_content().strip(), context=context) # FIXME: no match? More than 1 match? - print element.text_content().strip() assert len(matches) == 1 return matches[0][0] @@ -239,10 +239,10 @@ class Image(orm.AbstractModel): if options is None: options = {} classes = ['img', 'img-responsive'] + options.get('class', '').split() - return '' % ( + return ir_qweb.HTMLSafe('' % ( ' '.join(itertools.imap(werkzeug.utils.escape, classes)), record._model._name, - field_name, record.id) + field_name, record.id)) local_url_re = re.compile(r'^/(?P[^]]+)/static/(?P.+)$') def from_html(self, cr, uid, model, column, element, context=None): @@ -390,4 +390,4 @@ class Contact(orm.AbstractModel): 'options': options }, engine='website.qweb', context=context) - return html + return ir_qweb.HTMLSafe(html) diff --git a/addons/website/static/src/css/website.css b/addons/website/static/src/css/website.css index 3c57d1bf69f..4d75ef6ef51 100644 --- a/addons/website/static/src/css/website.css +++ b/addons/website/static/src/css/website.css @@ -203,7 +203,7 @@ html, body, #wrapwrap { width: 100%; } -header, #wrap, footer { +header, main, footer { display: table-row; } diff --git a/addons/website/static/src/css/website.sass b/addons/website/static/src/css/website.sass index eeac3ce2eb5..babeee577a7 100644 --- a/addons/website/static/src/css/website.sass +++ b/addons/website/static/src/css/website.sass @@ -127,7 +127,7 @@ html,body, #wrapwrap display: table width: 100% -header, #wrap, footer +header, main, footer display: table-row footer diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 40b7820e89a..1e3ef0da66a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -32,6 +32,27 @@ }); }); + /** + * An editing host is an HTML element with @contenteditable=true, or the + * child of a document in designMode=on (but that one's not supported) + * + * https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#editing-host + */ + function is_editing_host(element) { + return element.getAttribute('contentEditable') === 'true'; + } + /** + * Checks that both the element's content *and the element itself* are + * editable: an editing host is considered non-editable because its content + * is editable but its attributes should not be considered editable + */ + function is_editable_node(element) { + return !(element.data('oe-model') === 'ir.ui.view' + || element.data('cke-realelement') + || is_editing_host(element) + || element.isReadOnly()); + } + function link_dialog(editor) { return new website.editor.RTELinkDialog(editor).appendTo(document.body); } @@ -54,18 +75,13 @@ init: function (editor) { editor.on('doubleclick', function (evt) { var element = evt.data.element; - if (element.is('img') - && !element.data('cke-realelement') - && !element.isReadOnly() - && (element.data('oe-model') !== 'ir.ui.view')) { + if (element.is('img') && is_editable_node(element)) { image_dialog(editor, element); return; } element = get_selected_link(editor) || evt.data.element; - if (element.isReadOnly() - || !element.is('a') - || element.data('oe-model')) { + if (!(element.is('a') && is_editable_node(element))) { return; } @@ -360,7 +376,8 @@ }); $body.css('padding-top', '50px'); // Not working properly: editor.$el.outerHeight()); }; - /* ----- TOP EDITOR BAR FOR ADMIN ---- */ + + /* ----- TOP EDITOR BAR FOR ADMIN ---- */ website.EditorBar = openerp.Widget.extend({ template: 'website.editorbar', events: { @@ -597,9 +614,7 @@ if (previous && previous === this) { return; } var selected = new CKEDITOR.dom.element(this); - if (selected.data('oe-model') === 'ir.ui.view' - || selected.data('cke-realelement') - || selected.isReadOnly()) { + if (!is_editable_node(selected)) { return; } diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js index c2f3b09911a..fb869119352 100644 --- a/addons/website/static/src/js/website.tour.js +++ b/addons/website/static/src/js/website.tour.js @@ -69,7 +69,7 @@ $doc.one('shown.bs.modal', function () { $('.modal button.btn-primary').one('click', function () { $doc.off('hide.bs.modal', onStop); - self.moveToStep(step.trigger.modal.afterSubmit); + (callback || self.moveToNextStep).apply(self, [step.trigger.modal.afterSubmit]); }); (callback || self.moveToNextStep).apply(self); }); @@ -290,6 +290,7 @@ return this._super(); }, registerTour: function (tour) { + var self = this; var testId = 'test_'+tour.id+'_tour'; this.tours.push(tour); var test = { @@ -343,9 +344,17 @@ currentStep = actionSteps.shift(); } } - setTimeout(function () { - executeStep(currentStep); - }, 0); + if (currentStep.snippet && $(currentStep.element).length === 0) { + self.on('rte:ready', this, function () { + executeStep(currentStep); + }); + } else { + setTimeout(function () { + setTimeout(function () { + executeStep(currentStep); + }, 0); + }, 0); + } } }, reset: function () { diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 257e3bb4562..be7d4c65a85 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -114,7 +114,9 @@ - +
+ +