diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py index d7bd704b895..6e33742803d 100644 --- a/addons/website/models/ir_qweb.py +++ b/addons/website/models/ir_qweb.py @@ -21,6 +21,7 @@ from PIL import Image as I 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 REMOTE_CONNECTION_TIMEOUT = 2.5 @@ -32,6 +33,31 @@ class QWeb(orm.AbstractModel): _name = 'website.qweb' _inherit = 'ir.qweb' + URL_ATTRS = { + 'form': 'action', + 'a': 'href', + 'link': 'href', + 'frame': 'src', + 'iframe': 'src', + 'script': 'src', + } + + def add_template(self, into, name, node, context): + # preprocessing for multilang static urls + if request and 'url_for' in context: + router = request.httprequest.app.get_db_router(request.db).bind('') + for tag, attr in self.URL_ATTRS.items(): + for e in node.getElementsByTagName(tag): + url = e.getAttribute(attr) + if url: + try: + func = router.match(url)[0] + if func.multilang: + e.setAttribute(attr, context['url_for'](url)) + except Exception, e: + pass + super(QWeb, self).add_template(into, name, node, context) + def get_converter_for(self, field_type): return self.pool.get( 'website.qweb.field.' + field_type, diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 123557a625e..d502ef774fa 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -100,25 +100,6 @@ class view(osv.osv): return arch - URL_ATTRS = { - 'form': 'action', - 'a': 'href', - 'link': 'href', - 'frame': 'src', - 'iframe': 'src', - 'script': 'src', - } - def _normalize_urls(self, root): - for element in root.iter(): - attr = self.URL_ATTRS.get(element.tag) - if attr is None or attr not in element.attrib: - continue - - value = element.get(attr) - if not urlparse(value).scheme: - element.attrib.pop(attr) - element.set('t-' + attr, value) - def save(self, cr, uid, res_id, value, xpath=None, context=None): """ Update a view section. The view section may embed fields to write @@ -131,10 +112,6 @@ class view(osv.osv): arch_section = html.fromstring( value, parser=html.HTMLParser(encoding='utf-8')) - # TODO fme: Temporary desactivated because this breaks most of the snippets - # Need to find another way to normalize multilang urls (postprocessing) ? - # self._normalize_urls(arch_section) - if xpath is None: # value is an embedded field on its own, not a view section self.save_embedded_field(cr, uid, arch_section, context=context) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index 7648d4cdcf2..74a0351e2d4 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -37,7 +37,7 @@ def route(routes, *route_args, **route_kwargs): @http.route(new_routes, *route_args, **route_kwargs) @functools.wraps(f, assigned=functools.WRAPPER_ASSIGNMENTS + ('func_name',)) def wrap(*args, **kwargs): - request.route_lang = kwargs.get('lang_code', None) + request.route_lang = kwargs.pop('lang_code', None) if not hasattr(request, 'website'): request.multilang = f.multilang # TODO: Select website, currently hard coded @@ -332,11 +332,22 @@ class website(osv.osv): of the same. :rtype: list({name: str, url: str}) """ + # FIXME: possibility to add custom converters without editing server + # would allow the creation of a pages converter generating page + # urls on its own + View = self.pool['ir.ui.view'] + views = View.search_read(cr, uid, [['page', '=', True]], + fields=['name'], order='name', context=context) + xids = View.get_external_id(cr, uid, [view['id'] for view in views], context=context) + for view in views: + if xids[view['id']]: + yield { + 'name': view['name'], + 'url': '/page/' + xids[view['id']], + } router = request.httprequest.app.get_db_router(request.db) - for rule in router.iter_rules(): - endpoint = rule.endpoint if not self.rule_is_enumerable(rule): continue @@ -346,8 +357,7 @@ class website(osv.osv): ))) for values in generated: - # rule.build returns (domain_part, rel_url) - url = rule.build(values, append_unknown=False)[1] + domain_part, url = rule.build(values, append_unknown=False) yield {'name': url, 'url': url } def kanban(self, cr, uid, ids, model, domain, column, template, step=None, scope=None, orderby=None, context=None): diff --git a/addons/website/static/src/css/editor.css b/addons/website/static/src/css/editor.css index ea4d38a9e67..748d5bfad45 100644 --- a/addons/website/static/src/css/editor.css +++ b/addons/website/static/src/css/editor.css @@ -1,3 +1,4 @@ +@charset "utf-8"; /* ---- CKEditor Minimal Reset ---- */ .navbar.navbar-inverse .cke_chrome { border: none; diff --git a/addons/website/static/src/css/website.css b/addons/website/static/src/css/website.css index eb530b0036d..e0ca7104dc4 100644 --- a/addons/website/static/src/css/website.css +++ b/addons/website/static/src/css/website.css @@ -362,6 +362,7 @@ footer { .parallax { position: relative; + background-size: 100%; } .parallax.oe_small { height: 200px; diff --git a/addons/website/static/src/css/website.sass b/addons/website/static/src/css/website.sass index 9855b20c313..f0a9d9b8d3c 100644 --- a/addons/website/static/src/css/website.sass +++ b/addons/website/static/src/css/website.sass @@ -277,6 +277,7 @@ footer .parallax position: relative + background-size: 100% &.oe_small height: 200px &.oe_medium diff --git a/addons/website/static/src/js/website.menu.js b/addons/website/static/src/js/website.menu.js index 5ed3f5dcb7f..04da43cefa2 100644 --- a/addons/website/static/src/js/website.menu.js +++ b/addons/website/static/src/js/website.menu.js @@ -27,7 +27,7 @@ website.menu.EditMenuDialog = website.editor.Dialog.extend({ template: 'website.menu.dialog.edit', events: _.extend({}, website.editor.Dialog.prototype.events, { - 'click button.js_add_menu': 'add_menu', + 'click a.js_add_menu': 'add_menu', 'click button.js_edit_menu': 'edit_menu', 'click button.js_delete_menu': 'delete_menu', }), @@ -40,8 +40,6 @@ }, start: function () { var r = this._super.apply(this, arguments); - var button = openerp.qweb.render('website.menu.dialog.footer-button'); - this.$('.modal-footer').prepend(button); this.$('.oe_menu_editor').nestedSortable({ listType: 'ul', handle: 'div', diff --git a/addons/website/static/src/js/website.snippets.animation.js b/addons/website/static/src/js/website.snippets.animation.js new file mode 100644 index 00000000000..7277f80ba95 --- /dev/null +++ b/addons/website/static/src/js/website.snippets.animation.js @@ -0,0 +1,111 @@ +(function () { + 'use strict'; + + var website = openerp.website; + website.snippet = {}; + + website.snippet.start_animation = function () { + $("[data-snippet-id]").each(function() { + var $snipped_id = $(this); + if ( !$snipped_id.parents("#oe_snippets").length && + !$snipped_id.parent("body").length && + !$snipped_id.data("snippet-view") && + website.snippet.animationRegistry[$snipped_id.data("snippet-id")]) { + var snippet = new website.snippet.animationRegistry[$snipped_id.data("snippet-id")]($snipped_id); + $snipped_id.data("snippet-view", snippet); + } + }); + }; + website.snippet.stop_animation = function () { + $("[data-snippet-id]").each(function() { + var $snipped_id = $(this); + if ($snipped_id.data("snippet-view")) { + $snipped_id.data("snippet-view").stop(); + $snipped_id.data("snippet-view", false); + } + }); + }; + $(document).ready(website.snippet.start_animation); + + + website.snippet.animationRegistry = {}; + website.snippet.Animation = openerp.Class.extend({ + $: function () { + return this.$el.find.apply(this.$el, arguments); + }, + init: function (dom) { + this.$el = this.$target = $(dom); + this.start(); + }, + /* + * start + * This method is called after init + */ + start: function () { + }, + /* + * stop + * This method is called to stop the animation (e.g.: when rte is launch) + */ + stop: function () { + }, + }); + + website.snippet.animationRegistry.carousel = website.snippet.Animation.extend({ + start: function () { + this.$target.carousel({interval: false}); + }, + }); + + website.snippet.animationRegistry.parallax = website.snippet.Animation.extend({ + start: function () { + var self = this; + setTimeout(function () {self.set_values();}); + this.on_scroll = function () { + var speed = parseFloat(self.$target.attr("data-scroll-background-ratio") || 0); + if (speed == 1) return; + var offset = parseFloat(self.$target.attr("data-scroll-background-offset") || 0); + var top = offset + window.scrollY * speed; + self.$target.css("background-position", "0px " + top + "px"); + }; + this.on_resize = function () { + self.set_values(); + }; + $(window).on("scroll", this.on_scroll); + $(window).on("resize", this.on_resize); + }, + stop: function () { + $(window).off("scroll", this.on_scroll) + .off("resize", this.on_resize); + }, + set_values: function () { + var self = this; + var speed = parseFloat(self.$target.attr("data-scroll-background-ratio") || 0); + + if (speed == 1) { + this.$target.css("background-attachment", "fixed").css("background-position", "0px 0px"); + return; + } else { + this.$target.css("background-attachment", "scroll"); + } + + this.$target.attr("data-scroll-background-offset", 0); + var img = new Image(); + img.onload = function () { + var offset = 0; + var padding = parseInt($(document.body).css("padding-top")); + if (speed < 1) { + var inner_offset = self.$target.outerHeight() - this.height / this.width * document.body.clientWidth; + var outer_offset = self.$target.offset().top - (document.body.clientHeight - self.$target.outerHeight()) - padding; + offset = - outer_offset * speed + inner_offset; + } else { + offset = - self.$target.offset().top * speed; + } + self.$target.attr("data-scroll-background-offset", offset); + $(window).scroll(); + }; + img.src = this.$target.css("background-image").replace(/url\(['"]*|['"]*\)/g, ""); + } + }); + +})(); diff --git a/addons/website/static/src/js/website.snippets.js b/addons/website/static/src/js/website.snippets.editor.js similarity index 93% rename from addons/website/static/src/js/website.snippets.js rename to addons/website/static/src/js/website.snippets.editor.js index e25de37b524..edeafbc6986 100644 --- a/addons/website/static/src/js/website.snippets.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -1,21 +1,6 @@ (function () { 'use strict'; - - var start_snippet_animation = function () { - hack_to_add_snippet_id(); - $("[data-snippet-id]").each(function() { - var $snipped_id = $(this); - if ( !$snipped_id.parents("#oe_snippets").length && - typeof $snipped_id.data("snippet-view") === 'undefined' && - website.snippet.animationRegistry[$snipped_id.data("snippet-id")]) { - var snippet = new website.snippet.animationRegistry[$snipped_id.data("snippet-id")]($snipped_id); - $snipped_id.data("snippet-view", snippet); - } - }); - }; - $(document).ready(start_snippet_animation); - var website = openerp.website; website.add_template_file('/website/static/src/xml/website.snippets.xml'); @@ -39,7 +24,8 @@ this.on('rte:ready', this, function () { self.snippets.$button.removeClass("hidden"); - start_snippet_animation(); + website.snippet.stop_animation(); + website.snippet.start_animation(); self.trigger('rte:snippets_ready'); }); @@ -58,7 +44,6 @@ /* ----- SNIPPET SELECTOR ---- */ - website.snippet = {}; var observer = new website.Observer(function (mutations) { if (!_(mutations).find(function (m) { return m.type === 'childList' && m.addedNodes.length > 0; @@ -88,6 +73,10 @@ }); } + $(document).ready(function() { + hack_to_add_snippet_id(); + }); + website.snippet.selector = []; website.snippet.BuildingBlock = openerp.Widget.extend({ template: 'website.snippets', @@ -219,16 +208,10 @@ if ($snipped_id.data("snippet-editor")) { $snipped_id.data("snippet-editor").onBlur(); } - if ($snipped_id.data("snippet-view")) { - $snipped_id.data("snippet-view").onBlurEdit(); - } } }, snippet_focus: function ($snipped_id) { if ($snipped_id) { - if ($snipped_id.data("snippet-view")) { - $snipped_id.data("snippet-view").onFocusEdit(); - } if ($snipped_id.data("snippet-editor")) { $snipped_id.data("snippet-editor").onFocus(); } @@ -367,9 +350,7 @@ if(action === 'insert'){ $target = $toInsert; - if (website.snippet.animationRegistry[snipped_id]) { - new website.snippet.animationRegistry[snipped_id]($target); - } + website.snippet.start_animation(); self.create_overlay($target); $target.data("snippet-editor").drop_and_build_snippet($target); @@ -547,34 +528,6 @@ }); - website.snippet.animationRegistry = {}; - website.snippet.Animation = openerp.Class.extend({ - $: function () { - return this.$el.find.apply(this.$el, arguments); - }, - init: function (dom) { - this.$el = this.$target = $(dom); - this.start(); - }, - /* - * start - * This method is called after init - */ - start: function () { - }, - /* onFocusEdit - * if they are an editor for this data-snippet-id - * Called before onFocus of snippet editor - */ - onFocusEdit : function () {}, - - /* onBlurEdit - * if they are an editor for this data-snippet-id - * Called after onBlur of snippet editor - */ - onBlurEdit : function () {}, - }); - website.snippet.editorRegistry = {}; website.snippet.Editor = openerp.Class.extend({ init: function (parent, dom) { @@ -797,7 +750,7 @@ }, - change_background: function (bg, ul_options) { + change_background: function (bg, ul_options, callback) { var self = this; this.set_options_background(bg, ul_options); var $ul = this.$editor.find(ul_options); @@ -819,6 +772,9 @@ }); editor.appendTo($('body')); } + if (callback) { + callback(); + } }) .on('mouseover', function (event) { if ($(this).data("value")) { @@ -1033,11 +989,6 @@ }, }); - website.snippet.animationRegistry.carousel = website.snippet.Animation.extend({ - start: function () { - this.$target.carousel({interval: false}); - }, - }); website.snippet.editorRegistry.carousel = website.snippet.editorRegistry.resize.extend({ drop_and_build_snippet: function() { var id = 0; @@ -1211,8 +1162,11 @@ website.snippet.editorRegistry.parallax = website.snippet.editorRegistry.resize.extend({ start : function () { + var self = this; this._super(); - this.change_background(this.$target, 'ul[name="parallax-background"]'); + this.change_background(this.$target, 'ul[name="parallax-background"]', function () { + self.$target.data("snippet-view").set_values(); + }); this.scroll(); this.change_size(); }, @@ -1228,11 +1182,15 @@ var speed = $(this).data('value'); self.$target.attr('data-scroll-background-ratio', speed); self.$target.data("snippet-view").set_values(); + return false; }); + this.$target.data("snippet-view").set_values(); }, clean_for_save: function () { this._super(); - this.$target.find(".parallax").css("background-position", ''); + this.$target.find(".parallax") + .css("background-position", '') + .removeAttr("data-scroll-background-offset"); }, change_size: function () { var self = this; @@ -1251,6 +1209,7 @@ $li.removeClass("active"); $(this).addClass("active"); self.$target.data("snippet-view").set_values(); + return false; }) .on('mouseover', function (event) { self.$target.removeClass('oe_big oe_small oe_medium'); @@ -1262,39 +1221,6 @@ }); } }); - website.snippet.animationRegistry.parallax = website.snippet.Animation.extend({ - start: function () { - var self = this; - this.set_values(); - var on_scroll = function () { - var speed = parseFloat(self.$target.attr("data-scroll-background-ratio") || 0); - if (speed == 1) return; - var offset = parseFloat(self.$target.attr("data-scroll-background-offset") || 0); - var top = offset + window.scrollY * speed; - self.$target.css("background-position", "0px " + top + "px"); - }; - $(window).off("scroll").on("scroll", on_scroll); - }, - set_values: function () { - var self = this; - var speed = parseFloat(self.$target.attr("data-scroll-background-ratio") || 0); - - if (speed == 1) { - this.$target.css("background-attachment", "fixed").css("background-position", "0px 0px"); - return; - } else { - this.$target.css("background-attachment", "scroll"); - } - - this.$target.attr("data-scroll-background-offset", 0); - var img = new Image(); - img.onload = function () { - self.$target.attr("data-scroll-background-offset", self.$target.outerHeight() - this.height); - $(window).scroll(); - }; - img.src = this.$target.css("background-image").replace(/url\(['"]*|['"]*\)/g, ""); - } - }); /* * data-snippet-id automatically setted diff --git a/addons/website/static/src/xml/website.menu.xml b/addons/website/static/src/xml/website.menu.xml index c9c73c32ae7..6eea8b25466 100644 --- a/addons/website/static/src/xml/website.menu.xml +++ b/addons/website/static/src/xml/website.menu.xml @@ -21,19 +21,19 @@ - - - - Edit Structure + Edit Menu
+

+ + Add Menu Entry + +

diff --git a/addons/website/static/src/xml/website.xml b/addons/website/static/src/xml/website.xml index d3232767714..8ce2b155d7a 100644 --- a/addons/website/static/src/xml/website.xml +++ b/addons/website/static/src/xml/website.xml @@ -61,9 +61,16 @@ diff --git a/addons/website/views/snippets.xml b/addons/website/views/snippets.xml index 1f800e090e2..2d33ff0355e 100644 --- a/addons/website/views/snippets.xml +++ b/addons/website/views/snippets.xml @@ -703,8 +703,8 @@
  • Very Slow
  • Slow
  • Fixed
  • -
  • Fast
  • -
  • Very Fast
  • +
  • Fast
  • +
  • Very Fast
  • + @@ -98,7 +99,7 @@ - + @@ -147,13 +148,13 @@

    Our products & Services

    Connect with us

    - Copyright &copy; Company name - Sitemap + Copyright &copy; Company name - Sitemap
    @@ -366,7 +367,7 @@

    This page does not exists, but you can create it as you are administrator of this site.

    Create Page - or Search a Page + or Search a Page
    Edit the content bellow this line to adapt the default "page not found" page.
    @@ -381,8 +382,8 @@

    Maybe you were looking for one of these popular pages ?

    @@ -420,8 +421,8 @@

                         
                     
                   
    @@ -505,64 +506,67 @@ Sitemap: sitemap.xml
     
             
    diff --git a/addons/website_blog/controllers/main.py b/addons/website_blog/controllers/main.py
    index d15c78eabb1..b351dbdb131 100644
    --- a/addons/website_blog/controllers/main.py
    +++ b/addons/website_blog/controllers/main.py
    @@ -177,7 +177,7 @@ class WebsiteBlog(http.Controller):
                 context=dict(context, mail_create_nosubcribe=True))
             return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
     
    -    @website.route(['/blog//new'], type='http', auth="public")
    +    @website.route(['/blog//new'], type='http', auth="public", multilang=True)
         def blog_post_create(self, category_id=None, **post):
             cr, uid, context = request.cr, request.uid, request.context
             create_context = dict(context, mail_create_nosubscribe=True)
    diff --git a/addons/website_blog/views/website_blog_templates.xml b/addons/website_blog/views/website_blog_templates.xml
    index 4e605907ed8..4c5f0243f40 100644
    --- a/addons/website_blog/views/website_blog_templates.xml
    +++ b/addons/website_blog/views/website_blog_templates.xml
    @@ -263,7 +263,7 @@
                     through your blog entries, referenced in Google.
                 

    diff --git a/addons/website_crm/views/website_crm.xml b/addons/website_crm/views/website_crm.xml index 0a4702e49c7..f97a3c20ea4 100644 --- a/addons/website_crm/views/website_crm.xml +++ b/addons/website_crm/views/website_crm.xml @@ -4,7 +4,7 @@