odoo.define('web_editor.field.html', function (require) { 'use strict'; var ajax = require('web.ajax'); var basic_fields = require('web.basic_fields'); var core = require('web.core'); var Wysiwyg = require('web_editor.wysiwyg.root'); var field_registry = require('web.field_registry'); var TranslatableFieldMixin = basic_fields.TranslatableFieldMixin; var QWeb = core.qweb; var assetsLoaded = false; /** * FieldHtml Widget * Intended to display HTML content. This widget uses the wysiwyg editor * improved by odoo. * * nodeOptions: * - style-inline => convert class to inline style (no re-edition) => for sending by email * - no-attachment * - cssEdit * - cssReadonly * - snippets * - wrapper */ var FieldHtml = basic_fields.DebouncedField.extend(TranslatableFieldMixin, { className: 'oe_form_field oe_form_field_html', supportedFieldTypes: ['html'], custom_events: { wysiwyg_focus: '_onWysiwygFocus', wysiwyg_blur: '_onWysiwygBlur', wysiwyg_change: '_onChange', wysiwyg_attachment: '_onAttachmentChange', }, /** * @override */ willStart: function () { this._onUpdateIframeId = 'onLoad_' + _.uniqueId('FieldHtml'); var defAsset = null; if (this.nodeOptions.cssReadonly) { defAsset = ajax.loadAsset(this.nodeOptions.cssReadonly); } if (!assetsLoaded) { // avoid flickering when begin to edit assetsLoaded = $.Deferred(); var wysiwyg = new Wysiwyg(this, {}); wysiwyg.attachTo($('
'); } } return value; }, /** * Move HTML contents out of their wrapper. * * @private * @param {string} html content * @returns {string} html content */ _unWrap: function (html) { var $wrapper = $(html).find('#wrapper'); return $wrapper.length ? $wrapper.html() : html; }, /** * Wrap HTML in order to create a custom display. * * The wrapper (this.nodeOptions.wrapper) must be a static * XML template with content id="wrapper". * * @private * @param {string} html content * @returns {string} html content */ _wrap: function (html) { return $(QWeb.render(this.nodeOptions.wrapper)) .find('#wrapper').html(html) .end().prop('outerHTML'); }, //-------------------------------------------------------------------------- // Handler //-------------------------------------------------------------------------- /** * Method called when wysiwyg triggers a change. * * @private * @param {OdooEvent} ev */ _onChange: function (ev) { this._doDebouncedAction.apply(this, arguments); var $lis = this.$content.find('.note-editable ul.o_checklist > li:not(:has(> ul.o_checklist))'); if (!$lis.length) { return; } var max = 0; var ids = []; $lis.map(function () { var checklistId = parseInt(($(this).attr('id') || '0').replace(/^checklist-id-/, '')); if (ids.indexOf(checklistId) === -1) { if (checklistId > max) { max = checklistId; } ids.push(checklistId); } else { $(this).removeAttr('id'); } }); $lis.not('[id]').each(function () { $(this).attr('id', 'checklist-id-' + (++max)); }); }, /** * Method called when wysiwyg triggers a change. * * @private * @param {OdooEvent} ev */ _onReadonlyClickChecklist: function (ev) { var self = this; if (ev.offsetX > 0) { return; } var checked = $(ev.target).hasClass('o_checked'); var checklistId = parseInt(($(ev.target).attr('id') || '0').replace(/^checklist-id-/, '')); this._rpc({ route: '/web_editor/checklist', params: { res_model: this.model, res_id: this.res_id, filename: this.name, checklistId: checklistId, checked: !checked, }, }).then(function (value) { self._setValue(value); }); }, /** * Method called when the wysiwyg instance is loaded. * * @private */ _onLoadWysiwyg: function () { var $button = this._renderTranslateButton(); $button.css({ 'font-size': '15px', position: 'absolute', right: '+5px', }); var $toolbar = this.$content.find('.note-toolbar'); $toolbar.css('position', 'relative'); $toolbar.append($button); }, /** * @private * @param {OdooEvent} ev */ _onWysiwygBlur: function (ev) { ev.stopPropagation(); this._doAction(); if (ev.data.key === 'TAB') { this.trigger_up('navigation_move', { direction: ev.data.shiftKey ? 'left' : 'right', }); } }, /** * @private * @param {OdooEvent} ev */ _onWysiwygFocus: function (ev) {}, }); field_registry.add('html', FieldHtml); return FieldHtml; });