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 @@
- This page does not exists, but you can create it as you are administrator of this site.Mobile preview
Maybe you were looking for one of these popular pages ?
+ We are a team of passionated people whose goal is to improve everyone's + life through disruptive products. We build great products to solve your + business problems. +
++ Our products are designed for small to medium companies willing to optimize + their performance. +
+
+ ++Write here a quote from one of your customer. Quotes are are great way to give confidence in your products or services.
+ Author of this quote +
++OpenERP provides essential platform for our project management. Things are better organized and more visible with it.
+ John Doe, CEO +
- We are a team of passionated people whose goal is to improve everyone's - life through disruptive products. We build great products to solve your - business problems. -
-- Our products are designed for small to medium companies willing to optimize - their performance. -
-
- --Write here a quote from one of your customer. Quotes are are great way to give confidence in your products or services.
- Author of this quote -
--OpenERP provides essential platform for our project management. Things are better organized and more visible with it.
- John Doe, CEO -