diff --git a/web_ckeditor4/__manifest__.py b/web_ckeditor4/__manifest__.py index 28825be1..530c6f9e 100644 --- a/web_ckeditor4/__manifest__.py +++ b/web_ckeditor4/__manifest__.py @@ -13,7 +13,7 @@ 'web', ], 'data': [ - 'views/qweb.xml', + 'templates/assets.xml', ], 'css': [ 'static/src/css/web_ckeditor4.css', diff --git a/web_ckeditor4/static/src/js/web_ckeditor4.js b/web_ckeditor4/static/src/js/web_ckeditor4.js index db327286..a976b349 100644 --- a/web_ckeditor4/static/src/js/web_ckeditor4.js +++ b/web_ckeditor4/static/src/js/web_ckeditor4.js @@ -25,114 +25,55 @@ odoo.define('web_ckeditor4', function(require){ var core = require('web.core'); var session = require('web.session'); var formats = require('web.formats'); + var ckconfig = require('web_ckeditor4.config'); - var ckeditor_addFunction_org = CKEDITOR.tools.addFunction; - //this is a quite complicated way to kind of monkey patch the private - //method onDomReady of ckeditor's plugin wysiwigarea, which causes problems - //when the editor is about to be destroyed but because of OpenERP's - //architecture updated one last time with its current value - CKEDITOR.tools.addFunction = function(fn, scope) - { - if(scope && scope._ && scope._.attrChanges && scope._.detach) - { - var scope_reference = scope; - return ckeditor_addFunction_org(function() - { - var self = this, - self_arguments=arguments; - setTimeout(function() - { - if(self.editor) - { - fn.apply(self, self_arguments); - } - }, 0); - }, scope); - } - return ckeditor_addFunction_org(fn, scope); - }; - - CKEDITOR.on('dialogDefinition', function(e) - { - _.each(e.data.definition.contents, function(element) - { - if(!element || element.filebrowser!='uploadButton') - { - return - } - _.each(element.elements, function(element) - { - if(!element.onClick || element.type!='fileButton') - { - return - } - var onClick_org = element.onClick; - element.onClick = function(e1) - { - onClick_org.apply(this, arguments); - _.each(jQuery('#'+this.domId).closest('table') - .find('iframe').contents().find(':file') - .get(0).files, - function(file) - { - var reader = new FileReader(); - reader.onload = function(load_event) - { - CKEDITOR.tools.callFunction( - e.editor._.filebrowserFn, - load_event.target.result, - ''); - } - reader.readAsDataURL(file); - }); - return false; - } - }); - }); - }); - function filter_html(value, ckeditor_filter, ckeditor_writer) - { - var fragment = CKEDITOR.htmlParser.fragment.fromHtml(value); - ckeditor_filter.applyTo(fragment); - ckeditor_writer.reset(); - fragment.writeHtml(ckeditor_writer); - return ckeditor_writer.getHtml(); - }; - - var default_ckeditor_filter = new CKEDITOR.filter( - { - '*': - { - attributes: 'href,src,style,alt,width,height,dir', - styles: '*', - classes: '*', - }, - 'html head title meta style body p div span a h1 h2 h3 h4 h5 img br hr table tr th td ul ol li dd dt strong pre b i': true, - }); - var default_ckeditor_writer = new CKEDITOR.htmlParser.basicWriter(); var FieldCKEditor4 = core.form_widget_registry.get('text').extend({ ckeditor_config: function () { - return { - removePlugins: this._getRemovePlugins(), - removeButtons: this._getRemoveButtons(), - filebrowserImageUploadUrl: 'dummy', - extraPlugins: 'filebrowser', - // this is '#39' per default which screws up single quoted text in ${} - entities_additional: '' - }; + return { + removePlugins: this._getRemovePlugins(), + removeButtons: this._getRemoveButtons(), + filebrowserImageUploadUrl: 'dummy', + extraPlugins: 'filebrowser', + // this is '#39' per default which screws up single quoted text in ${} + entities_additional: '' + }; }, - ckeditor_filter: default_ckeditor_filter, - ckeditor_writer: default_ckeditor_writer, + ckeditor_filter: ckconfig.default_ckeditor_filter, + ckeditor_writer: ckconfig.default_ckeditor_writer, _getRemovePlugins: function () { return 'iframe,flash,forms,smiley,pagebreak,stylescombo'; }, _getRemoveButtons: function () { return ''; }, + init: function () { + this._super.apply(this, arguments); + this.editor_lang = session.user_context.lang.split('_')[0]; + this.view.on("load_record", this, this._on_load_record); + }, start: function() { this._super.apply(this, arguments); - CKEDITOR.lang.load(session.user_context.lang.split('_')[0], 'en', function() {}); + CKEDITOR.lang.load(this.editor_lang, 'en', function() {}); + }, + _on_load_record: function() { + /* Fix widget not re-initialized on form discard. + + When you hit "cancel" button or when you navigate away + from the form, for instance by clicking on the breadcrumb + or on "edit translations", we have to remove the CKEditor widget. + + BUT then if you hit "create" Odoo's form machinery is not initializing + the widget anymore (which really sounds inconsistent). + If the widget is not initialized again it means that if CKEditor + got destroyed there's no way to re-init again. + + Here we make sure that on create (no id on datarecord) + if the editor is not initialized yet we force it. + */ + if (!this.view.datarecord.id && !this.editor) { + this.initialize_content(); + } }, initialize_content: function() { @@ -141,12 +82,11 @@ odoo.define('web_ckeditor4', function(require){ if(!this.$el) { return; - } else if (!this.get('effective_readonly')) { - + } else if (!this.get('effective_readonly') && !this.editor) { this.editor = CKEDITOR.replace(this.$el.get(0), _.extend( { - language: session.user_context.lang.split('_')[0], + language: this.editor_lang, on: { 'change': function() @@ -166,7 +106,7 @@ odoo.define('web_ckeditor4', function(require){ }, filter_html: function(value) { - return filter_html(value, this.ckeditor_filter, this.ckeditor_writer); + return ckconfig.filter_html(value, this.ckeditor_filter, this.ckeditor_writer); }, render_value: function() { @@ -195,6 +135,9 @@ odoo.define('web_ckeditor4', function(require){ } } }, + destroy_content: function () { + this._cleanup_editor(); + }, undelegateEvents: function() { this._cleanup_editor(); @@ -202,35 +145,35 @@ odoo.define('web_ckeditor4', function(require){ }, _cleanup_editor: function() { - if(this.editor && this.editor.status != 'unloaded') + if(this.editor && this.editor.status == 'ready') { - var id = this.editor.id + CKEDITOR.remove(this.editor.name); + $('#cke_' + this.editor.name).remove(); this.editor.removeAllListeners(); this.editor.destroy(); this.editor = null; - $('.' + id).remove(); } }, destroy: function() { - this._cleanup_editor(); - this._super(); - }, - destroy_content: function() - { + this.view.off("load_record", this, this._on_load_record); this._cleanup_editor(); + this._super(); } }); + var FieldCKEditor4Raw = FieldCKEditor4.extend({ filter_html: function(value) { return value; } }); + core.form_widget_registry.add('text_ckeditor4', FieldCKEditor4); core.form_widget_registry.add('text_ckeditor4_raw', FieldCKEditor4Raw); core.form_widget_registry.add('text_html', FieldCKEditor4); core.form_widget_registry.add('html', FieldCKEditor4); + return { 'FieldCKEditor4': FieldCKEditor4, 'FieldCKEditor4Raw': FieldCKEditor4Raw diff --git a/web_ckeditor4/static/src/js/web_ckeditor4_config.js b/web_ckeditor4/static/src/js/web_ckeditor4_config.js new file mode 100644 index 00000000..8f02cfb4 --- /dev/null +++ b/web_ckeditor4/static/src/js/web_ckeditor4_config.js @@ -0,0 +1,99 @@ +/* -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2013 Therp BV () +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################*/ + +odoo.define('web_ckeditor4.config', function (require) { + "use strict"; + + var ckeditor_addFunction_org = CKEDITOR.tools.addFunction; + // this is a quite complicated way to kind of monkey patch the private + // method onDomReady of ckeditor's plugin wysiwigarea, which causes problems + // when the editor is about to be destroyed but because of OpenERP's + // architecture updated one last time with its current value + CKEDITOR.tools.addFunction = function (fn, scope) { + if (scope && scope._ && scope._.attrChanges && scope._.detach) { + return ckeditor_addFunction_org(function () { + var self = this, + self_arguments = arguments; + setTimeout(function () { + if (self.editor) { + fn.apply(self, self_arguments); + } + }, 0); + }, scope); + } + return ckeditor_addFunction_org(fn, scope); + }; + + CKEDITOR.on('dialogDefinition', function (e) { + _.each(e.data.definition.contents, function (element) { + if (!element || element.filebrowser != 'uploadButton') { + return + } + _.each(element.elements, function (element) { + if (!element.onClick || element.type != 'fileButton') { + return + } + var onClick_org = element.onClick; + element.onClick = function (e1) { + onClick_org.apply(this, arguments); + _.each($('#' + this.domId).closest('table') + .find('iframe').contents().find(':file') + .get(0).files, + function (file) { + var reader = new FileReader(); + reader.onload = function (load_event) { + CKEDITOR.tools.callFunction( + e.editor._.filebrowserFn, + load_event.target.result, + ''); + } + reader.readAsDataURL(file); + }); + return false; + } + }); + }); + }); + var filter_html = function filter_html(value, ckeditor_filter, ckeditor_writer) { + var fragment = CKEDITOR.htmlParser.fragment.fromHtml(value); + ckeditor_filter.applyTo(fragment); + ckeditor_writer.reset(); + fragment.writeHtml(ckeditor_writer); + return ckeditor_writer.getHtml(); + }; + + var default_ckeditor_filter = new CKEDITOR.filter({ + '*': + { + attributes: 'href,src,style,alt,width,height,dir', + styles: '*', + classes: '*', + }, + 'html head title meta style body p div span a h1 h2 h3 h4 h5 img br hr table tr th td ul ol li dd dt strong pre b i': true, + }); + var default_ckeditor_writer = new CKEDITOR.htmlParser.basicWriter(); + return { + 'filter_html': filter_html, + 'default_ckeditor_filter': default_ckeditor_filter, + 'default_ckeditor_writer': default_ckeditor_writer + } +}); diff --git a/web_ckeditor4/templates/assets.xml b/web_ckeditor4/templates/assets.xml new file mode 100644 index 00000000..d3882fee --- /dev/null +++ b/web_ckeditor4/templates/assets.xml @@ -0,0 +1,20 @@ + + + - -