diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/website/static/src/js/menu/edit.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/website/static/src/js/menu/edit.js')
| -rw-r--r-- | addons/website/static/src/js/menu/edit.js | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/addons/website/static/src/js/menu/edit.js b/addons/website/static/src/js/menu/edit.js new file mode 100644 index 00000000..d448b15d --- /dev/null +++ b/addons/website/static/src/js/menu/edit.js @@ -0,0 +1,256 @@ +odoo.define('website.editMenu', function (require) { +'use strict'; + +var core = require('web.core'); +var EditorMenu = require('website.editor.menu'); +var websiteNavbarData = require('website.navbar'); + +var _t = core._t; + +/** + * Adds the behavior when clicking on the 'edit' button (+ editor interaction) + */ +var EditPageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({ + assetLibs: ['web_editor.compiled_assets_wysiwyg', 'website.compiled_assets_wysiwyg'], + + xmlDependencies: ['/website/static/src/xml/website.editor.xml'], + actions: _.extend({}, websiteNavbarData.WebsiteNavbarActionWidget.prototype.actions, { + edit: '_startEditMode', + on_save: '_onSave', + }), + custom_events: _.extend({}, websiteNavbarData.WebsiteNavbarActionWidget.custom_events || {}, { + content_will_be_destroyed: '_onContentWillBeDestroyed', + content_was_recreated: '_onContentWasRecreated', + snippet_will_be_cloned: '_onSnippetWillBeCloned', + snippet_cloned: '_onSnippetCloned', + snippet_dropped: '_onSnippetDropped', + edition_will_stopped: '_onEditionWillStop', + edition_was_stopped: '_onEditionWasStopped', + }), + + /** + * @constructor + */ + init: function () { + this._super.apply(this, arguments); + var context; + this.trigger_up('context_get', { + extra: true, + callback: function (ctx) { + context = ctx; + }, + }); + this._editorAutoStart = (context.editable && window.location.search.indexOf('enable_editor') >= 0); + var url = window.location.href.replace(/([?&])&*enable_editor[^&#]*&?/, '\$1'); + window.history.replaceState({}, null, url); + }, + /** + * Auto-starts the editor if necessary or add the welcome message otherwise. + * + * @override + */ + start: function () { + var def = this._super.apply(this, arguments); + + // If we auto start the editor, do not show a welcome message + if (this._editorAutoStart) { + return Promise.all([def, this._startEditMode()]); + } + + // Check that the page is empty + var $wrap = this._targetForEdition().filter('#wrapwrap.homepage').find('#wrap'); + + if ($wrap.length && $wrap.html().trim() === '') { + // If readonly empty page, show the welcome message + this.$welcomeMessage = $(core.qweb.render('website.homepage_editor_welcome_message')); + this.$welcomeMessage.addClass('o_homepage_editor_welcome_message'); + this.$welcomeMessage.css('min-height', $wrap.parent('main').height() - ($wrap.outerHeight(true) - $wrap.height())); + $wrap.empty().append(this.$welcomeMessage); + } + + return def; + }, + + //-------------------------------------------------------------------------- + // Actions + //-------------------------------------------------------------------------- + + /** + * Creates an editor instance and appends it to the DOM. Also remove the + * welcome message if necessary. + * + * @private + * @returns {Promise} + */ + _startEditMode: async function () { + var self = this; + if (this.editModeEnable) { + return; + } + this.trigger_up('widgets_stop_request', { + $target: this._targetForEdition(), + }); + if (this.$welcomeMessage) { + this.$welcomeMessage.detach(); // detach from the readonly rendering before the clone by summernote + } + this.editModeEnable = true; + await new EditorMenu(this).prependTo(document.body); + this._addEditorMessages(); + var res = await new Promise(function (resolve, reject) { + self.trigger_up('widgets_start_request', { + editableMode: true, + onSuccess: resolve, + onFailure: reject, + }); + }); + // Trigger a mousedown on the main edition area to focus it, + // which is required for Summernote to activate. + this.$editorMessageElements.mousedown(); + return res; + }, + /** + * On save, the editor will ask to parent widgets if something needs to be + * done first. The website navbar will receive that demand and asks to its + * action-capable components to do something. For example, the content menu + * handles page-related options saving. However, some users with limited + * access rights do not have the content menu... but the website navbar + * expects that the save action is performed. So, this empty action is + * defined here so that all users have an 'on_save' related action. + * + * @private + * @todo improve the system to somehow declare required/optional actions + */ + _onSave: function () {}, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Adds automatic editor messages on drag&drop zone elements. + * + * @private + */ + _addEditorMessages: function () { + const $target = this._targetForEdition(); + const $skeleton = $target.find('.oe_structure.oe_empty, [data-oe-type="html"]'); + this.$editorMessageElements = $skeleton.not('[data-editor-message]').attr('data-editor-message', _t('DRAG BUILDING BLOCKS HERE')); + $skeleton.attr('contenteditable', function () { return !$(this).is(':empty'); }); + }, + /** + * Returns the target for edition. + * + * @private + * @returns {JQuery} + */ + _targetForEdition: function () { + return $('#wrapwrap'); // TODO should know about this element another way + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Called when content will be destroyed in the page. Notifies the + * WebsiteRoot that is should stop the public widgets. + * + * @private + * @param {OdooEvent} ev + */ + _onContentWillBeDestroyed: function (ev) { + this.trigger_up('widgets_stop_request', { + $target: ev.data.$target, + }); + }, + /** + * Called when content was recreated in the page. Notifies the + * WebsiteRoot that is should start the public widgets. + * + * @private + * @param {OdooEvent} ev + */ + _onContentWasRecreated: function (ev) { + this.trigger_up('widgets_start_request', { + editableMode: true, + $target: ev.data.$target, + }); + }, + /** + * Called when edition will stop. Notifies the + * WebsiteRoot that is should stop the public widgets. + * + * @private + * @param {OdooEvent} ev + */ + _onEditionWillStop: function (ev) { + this.$editorMessageElements && this.$editorMessageElements.removeAttr('data-editor-message'); + this.trigger_up('widgets_stop_request', { + $target: this._targetForEdition(), + }); + }, + /** + * Called when edition was stopped. Notifies the + * WebsiteRoot that is should start the public widgets. + * + * @private + * @param {OdooEvent} ev + */ + _onEditionWasStopped: function (ev) { + this.trigger_up('widgets_start_request', { + $target: this._targetForEdition(), + }); + this.editModeEnable = false; + }, + /** + * Called when a snippet is about to be cloned in the page. Notifies the + * WebsiteRoot that is should destroy the animations for this snippet. + * + * @private + * @param {OdooEvent} ev + */ + _onSnippetWillBeCloned: function (ev) { + this.trigger_up('widgets_stop_request', { + $target: ev.data.$target, + }); + }, + /** + * Called when a snippet is cloned in the page. Notifies the WebsiteRoot + * that is should start the public widgets for this snippet and the snippet it + * was cloned from. + * + * @private + * @param {OdooEvent} ev + */ + _onSnippetCloned: function (ev) { + this.trigger_up('widgets_start_request', { + editableMode: true, + $target: ev.data.$target, + }); + // TODO: remove in saas-12.5, undefined $origin will restart #wrapwrap + if (ev.data.$origin) { + this.trigger_up('widgets_start_request', { + editableMode: true, + $target: ev.data.$origin, + }); + } + }, + /** + * Called when a snippet is dropped in the page. Notifies the WebsiteRoot + * that is should start the public widgets for this snippet. Also add the + * editor messages. + * + * @private + * @param {OdooEvent} ev + */ + _onSnippetDropped: function (ev) { + this.trigger_up('widgets_start_request', { + editableMode: true, + $target: ev.data.$target, + }); + this._addEditorMessages(); + }, +}); + +websiteNavbarData.websiteNavbarRegistry.add(EditPageMenu, '#edit-page-menu'); +}); |
