diff --git a/addons/website/static/lib/ckeditor.sharedspace/plugin.js b/addons/website/static/lib/ckeditor.sharedspace/plugin.js
deleted file mode 100644
index ae8ddc79eb4..00000000000
--- a/addons/website/static/lib/ckeditor.sharedspace/plugin.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * @license Copyright (c) 2003-2012, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or http://ckeditor.com/license
- */
-
-(function() {
-
- 'use strict';
-
- var containerTpl = CKEDITOR.addTemplate( 'sharedcontainer', '
' );
-
- CKEDITOR.plugins.add( 'sharedspace', {
- afterInit: function( editor ) {
- var spaces = editor.config.sharedSpaces;
-
- if ( spaces ) {
- for ( var spaceName in spaces ) {
- create( editor, spaceName, spaces[ spaceName ] );
- }
- }
- }
- });
-
- function create( editor, spaceName, targetId ) {
- var target = CKEDITOR.document.getById( targetId ),
- innerHtml, space;
-
- if ( target ) {
- // Have other plugins filling the space.
- innerHtml = editor.fire( 'uiSpace', { space: spaceName, html: '' } ).html;
-
- if ( innerHtml ) {
- // Block the uiSpace handling by others (e.g. themed-ui).
- editor.on( 'uiSpace', function( ev ) {
- if ( ev.data.space == spaceName )
- ev.cancel();
- }, null, null, 1 ); // Hi-priority
-
- // Inject the space into the target.
- space = target.append( CKEDITOR.dom.element.createFromHtml( containerTpl.output({
- id: editor.id,
- name: editor.name,
- langDir: editor.lang.dir,
- langCode: editor.langCode,
- space: spaceName,
- spaceId: editor.ui.spaceId( spaceName ),
- content: innerHtml
- })));
-
- // Only the first container starts visible. Others get hidden.
- if ( target.getCustomData( 'cke_hasshared' ) )
- space.hide();
- else
- target.setCustomData( 'cke_hasshared', 1 );
-
- // There's no need for the space to be selectable.
- space.unselectable();
-
- // Prevent clicking on non-buttons area of the space from blurring editor.
- space.on( 'mousedown', function( evt ) {
- evt = evt.data;
- if ( !evt.getTarget().hasAscendant( 'a', 1 ) )
- evt.preventDefault();
- });
-
- // Register this UI space to the focus manager.
- editor.focusManager.add( space, 1 );
-
- // When the editor gets focus, show the space container, hiding others.
- editor.on( 'focus', function() {
- for ( var i = 0, sibling, children = target.getChildren(); ( sibling = children.getItem( i ) ); i++ ) {
- if ( sibling.type == CKEDITOR.NODE_ELEMENT &&
- !sibling.equals( space ) &&
- sibling.hasClass( 'cke_shared' ) ) {
- sibling.hide();
- }
- }
-
- space.show();
- });
-
- editor.on( 'destroy', function() {
- space.remove();
- });
- }
- }
- }
-})();
-
-/**
- * Makes it possible to place some of the editor UI blocks, like the toolbar
- * and the elements path, into any element in the page.
- *
- * The elements used to hold the UI blocks can be shared among several editor
- * instances. In that case, only the blocks of the active editor instance will
- * display.
- *
- * // Place the toolbar inside the element with ID "someElementId" and the
- * // elements path into the element with ID "anotherId".
- * config.sharedSpaces = {
- * top: 'someElementId',
- * bottom: 'anotherId'
- * };
- *
- * // Place the toolbar inside the element with ID "someElementId". The
- * // elements path will remain attached to the editor UI.
- * config.sharedSpaces = {
- * top: 'someElementId'
- * };
- *
- * @cfg {Object} [sharedSpaces]
- * @member CKEDITOR.config
- */
diff --git a/addons/website/static/src/js/website.js b/addons/website/static/src/js/website.js
index 84f0cc70767..5fb341d1f32 100644
--- a/addons/website/static/src/js/website.js
+++ b/addons/website/static/src/js/website.js
@@ -1,4 +1,5 @@
openerp.website = function(instance) {
+var _lt = instance.web._lt;
instance.website.EditorBar = instance.web.Widget.extend({
template: 'Website.EditorBar',
events: {
@@ -8,52 +9,39 @@ instance.website.EditorBar = instance.web.Widget.extend({
'click button[data-action=snippet]': 'snippet',
},
container: 'body',
+ init: function () {
+ this._super.apply(this, arguments);
+ this.saving_mutex = new $.Mutex();
+ },
start: function() {
var self = this;
- this.saving_mutex = new $.Mutex();
- self.$('button[data-action]').prop('disabled', true);
- self.$('button[data-action=edit], button[data-action=snippet]').prop('disabled', false);
+
+ this.$('button[data-action]').prop('disabled', true);
+ this.$buttons = {
+ edit: this.$('button[data-action=edit]'),
+ save: this.$('button[data-action=save]'),
+ cancel: this.$('button[data-action=cancel]'),
+ snippet: this.$('button[data-action=snippet]'),
+ };
+ this.$buttons.edit.add(this.$buttons.snippet).prop('disabled', false);
+
self.snippet_start();
- $('body').on("keypress", ".oe_editable", function(e) {
- var $e = $(e.currentTarget);
- if (!$e.is('.oe_dirty')) {
- $e.addClass('oe_dirty');
- self.$('button[data-action=save],button[data-action=cancel]').prop('disabled', false);
- // TODO: Are we going to use a meta-data flag in order to know if the field shall be text or html ?
- }
- if (e.which == 13) {
- $e.blur();
- e.preventDefault();
- }
- });
+ this.rte = new instance.website.RTE(this);
+ this.rte.on('change', this, this.proxy('rte_changed'));
- return this._super.apply(this, arguments);
+ return $.when(
+ this._super.apply(this, arguments),
+ this.rte.appendTo(this.$el)
+ );
},
edit: function () {
- this.$('button[data-action=edit]').prop('disabled', true);
- $('[data-oe-model]')
- .not('link, script, span')
- .prop('contentEditable', true)
- .addClass('oe_editable')
- .each(function () {
- CKEDITOR.inline(this, {
- // Don't load ckeditor's style rules
- stylesSet: [],
- toolbar: [
- ['Bold', 'Italic']
- ],
- uiColor: '',
- // Ensure no config file is loaded
- customConfig: '',
- // Disable ACF
- allowedContent: true,
- // Support for sharedSpaces in 4.x
- extraPlugins: 'sharedspace',
- // Place toolbar in controlled location
- sharedSpaces: { top: 'oe_rte_toolbar' },
- });
- });
+ this.$buttons.edit.prop('disabled', true);
+ this.$buttons.cancel.prop('disabled', false);
+ this.rte.start_edition($('[data-oe-model]').addClass('oe_editable'));
+ },
+ rte_changed: function () {
+ this.$buttons.save.prop('disabled', false);
},
save: function () {
var self = this;
@@ -85,7 +73,6 @@ instance.website.EditorBar = instance.web.Widget.extend({
$w.removeClass('oe_dirty');
_.each(['model', 'id', 'field', 'xpath'], function(d) {$w.removeAttr('data-oe-' + d);});
$w
- .each(function () { console.log(this); })
.removeClass('oe_editable')
.prop('contentEditable', false);
html = $w.wrap('').parent().html();
@@ -124,6 +111,79 @@ instance.website.EditorBar = instance.web.Widget.extend({
},
});
+instance.website.RTE = instance.web.Widget.extend({
+ tagName: 'li',
+ className: 'oe_right',
+ commands: [
+ {name: _lt('Bold'), command: 'bold'},
+ {name: _lt('Italic'), command: 'italic'},
+ {name: _lt('Underline'), command: 'underline'},
+ {name: _lt('Strikethrough'), command: 'strike'},
+ {name: _lt('H1'), style: { element: 'h1' }},
+ {name: _lt('H2'), style: { element: 'h2', }},
+ {name: _lt('H3'), style: { element: 'h3', }},
+ {name: _lt('H4'), style: { element: 'h4', }},
+ {name: _lt("Red"), style: { element: 'span', styles: { color: 'red' } }}
+ ],
+ // editor.ui.items -> possible commands &al
+ // editor.applyStyle(new CKEDITOR.style({element: "span",styles: {color: "#(color)"},overrides: [{element: "font",attributes: {color: null}}]}, {color: '#ff0000'}));
+ start: function () {
+ var self = this;
+ this.$el.hide();
+
+ _(this.commands).foldl(function (jq, command) {
+ return jq.add(self.button_for(command));
+ }, $()).appendTo(this.$el);
+ },
+ start_edition: function ($elements) {
+ var self = this;
+ $elements
+ .not('link, script, span')
+ .prop('contentEditable', true)
+ .each(function () {
+ var $this = $(this);
+ CKEDITOR.inline(this, self._config()).on('change', function () {
+ $this.addClass('oe_dirty');
+ self.trigger('change', this, null);
+ });
+ });
+ this.$el.show();
+ },
+
+ button_for: function (command) {
+ var self = this;
+ return $('