diff --git a/addons/website/static/src/js/website.ace.js b/addons/website/static/src/js/website.ace.js
index fd26c50aefd..840e3317d56 100644
--- a/addons/website/static/src/js/website.ace.js
+++ b/addons/website/static/src/js/website.ace.js
@@ -55,82 +55,119 @@
website.ace.ViewEditor = openerp.Widget.extend({
template: 'website.ace_view_editor',
events: {
- 'change #ace-view-list': 'displayView',
- 'click button[data-action=save]': 'saveView',
+ 'change #ace-view-list': 'displaySelectedView',
+ 'click button[data-action=save]': 'saveViews',
'click button[data-action=format]': 'formatXml',
'click button[data-action=close]': 'close',
},
+ init: function (parent) {
+ this.buffers = {};
+ this._super(parent);
+ },
start: function () {
var self = this;
+ self.aceEditor = ace.edit(self.$('#ace-view-editor')[0]);
+ self.aceEditor.setTheme("ace/theme/monokai");
var viewId = $(document.documentElement).data('view-xmlid');
openerp.jsonRpc('/website/customize_template_get', 'call', {
'xml_id': viewId,
'optional': false,
}).then(function (views) {
- self.loadViewList.call(self, views);
+ self.loadViews.call(self, views);
+ self.open.call(self);
+ });
+ },
+ loadViews: function (views) {
+ var self = this;
+ var activeViews = _.filter(views, function (view) {
+ return view.active;
+ });
+ var $viewList = self.$('#ace-view-list');
+ _.each(activeViews, function (view) {
+ if (view.id) {
+ new website.ace.ViewOption(self, view).appendTo($viewList);
+ self.loadView(view.id);
+ }
+ });
+ },
+ loadView: function (id) {
+ var viewId = parseInt(id, 10);
+ var self = this;
+ openerp.jsonRpc('/web/dataset/call', 'call', {
+ model: 'ir.ui.view',
+ method: 'read',
+ args: [[viewId], ['arch'], website.get_context()],
+ }).then(function(result) {
+ var editingSession = self.buffers[viewId] = new ace.EditSession(result[0].arch);;
+ editingSession.setMode("ace/mode/xml");
+ editingSession.setUndoManager(new ace.UndoManager());
+ editingSession.on("change", function () {
+ setTimeout(function () {
+ var $option = self.$('#ace-view-list').find('[value='+viewId+']');
+ var bufferName = $option.text();
+ var dirtyMarker = " (unsaved changes)";
+ var isDirty = editingSession.getUndoManager().hasUndo();
+ if (isDirty && bufferName.indexOf(dirtyMarker) < 0) {
+ $option.text(bufferName + dirtyMarker);
+ } else if (!isDirty && bufferName.indexOf(dirtyMarker) > 0) {
+ $option.text(bufferName.substring(0, bufferName.indexOf(dirtyMarker)));
+ }
+ }, 1);
+ });
+ if (viewId === self.selectedViewId()) {
+ self.displayView.call(self, viewId);
+ }
});
- this.$el.hover();
},
selectedViewId: function () {
return parseInt(this.$('#ace-view-list').val(), 10);
},
- loadViewList: function (views) {
- var activeViews = _.filter(views, function (view) {
- return view.active;
- });
- var $viewList = this.$('#ace-view-list');
- _.each(activeViews, function (view) {
- if (view.id) {
- new website.ace.ViewOption(this, view).appendTo($viewList);
- }
- });
- var editor = ace.edit(this.$('#ace-view-editor')[0]);
- editor.setTheme("ace/theme/monokai");
- this.aceEditor = editor;
- this.open();
+ displayView: function (id) {
+ var viewId = parseInt(id, 10);
+ var editingSession = this.buffers[viewId];
+ if (editingSession) {
+ this.aceEditor.setSession(editingSession);
+ }
},
- displayView: function () {
- var editor = this.aceEditor;
- openerp.jsonRpc('/web/dataset/call', 'call', {
- model: 'ir.ui.view',
- method: 'read',
- args: [[this.selectedViewId()], ['arch'], website.get_context()],
- }).then(function(result) {
- var xml = new website.ace.XmlDocument(result[0].arch);
- var editingSession = new ace.EditSession(xml.xml);
- editingSession.setMode("ace/mode/xml");
- editingSession.setUndoManager(new ace.UndoManager());
- editor.setSession(editingSession);
- });
+ displaySelectedView: function () {
+ this.displayView(this.selectedViewId());
},
formatXml: function () {
var xml = new website.ace.XmlDocument(this.aceEditor.getValue());
this.aceEditor.setValue(xml.format());
},
- saveView: function () {
+ saveViews: function () {
var self = this;
- var xml = new website.ace.XmlDocument(this.aceEditor.getValue());
+ var toSave = _.filter(_.map(self.buffers, function (editingSession, viewId) {
+ return {
+ id: parseInt(viewId, 10),
+ isDirty: editingSession.getUndoManager().hasUndo(),
+ text: editingSession.getValue(),
+ };
+ }), function (session) {
+ return session.isDirty;
+ });
+ var requests = _.map(toSave, self.saveView);
+ $.when.apply($, requests).then(self.reloadPage).fail(self.displayError);
+ },
+ saveView: function (session) {
+ var xml = new website.ace.XmlDocument(session.text);
if (xml.isWellFormed()) {
- openerp.jsonRpc('/web/dataset/call', 'call', {
+ return openerp.jsonRpc('/web/dataset/call', 'call', {
model: 'ir.ui.view',
method: 'write',
- args: [[this.selectedViewId()], { 'arch': xml.xml }, website.get_context()],
- }).then(function(result) {
- self.reloadPage();
- }).fail(function (error) {
- self.displayError(error);
+ args: [[session.id], { 'arch': xml.xml }, website.get_context()],
});
} else {
- self.displayError();
+ return $.Deferred().fail("Malformed XML document");
}
},
reloadPage: function () {
- // TODO Reload { header + div#wrap + footer } only
window.location.reload();
},
displayError: function (error) {
// TODO Improve feedback (e.g. update 'Save' button + tooltip)
- alert("Malformed XML document");
+ alert(error);
},
open: function () {
this.$el.removeClass('oe_ace_closed').addClass('oe_ace_open');
diff --git a/addons/website/static/src/js/website.seo.js b/addons/website/static/src/js/website.seo.js
index e5741123ccb..49cc65e1b09 100644
--- a/addons/website/static/src/js/website.seo.js
+++ b/addons/website/static/src/js/website.seo.js
@@ -214,14 +214,14 @@
return hashIndex >= 0 ? url.substring(0, hashIndex) : url;
},
title: function () {
- return $('title').text();
+ return $('title').text().trim();
},
changeTitle: function (title) {
$('title').text(title);
this.trigger('title-changed', title);
},
description: function () {
- return $('meta[name=description]').attr('value');
+ return $('meta[name=description]').attr('value').trim();
},
changeDescription: function (description) {
$('meta[name=description]').attr('value', description);
diff --git a/addons/website/views/views.xml b/addons/website/views/views.xml
index 485c1b9f9f2..5a9f427641c 100644
--- a/addons/website/views/views.xml
+++ b/addons/website/views/views.xml
@@ -11,7 +11,7 @@
-
+
<!DOCTYPE html>
-
+