odoo.define('web_editor.field.html', function (require) { 'use strict'; var ajax = require('web.ajax'); var basic_fields = require('web.basic_fields'); var config = require('web.config'); var core = require('web.core'); var Wysiwyg = require('web_editor.wysiwyg.root'); var field_registry = require('web.field_registry'); // must wait for web/ to add the default html widget, otherwise it would override the web_editor one require('web._field_registry'); var _lt = core._lt; var TranslatableFieldMixin = basic_fields.TranslatableFieldMixin; var QWeb = core.qweb; var assetsLoaded; var jinjaRegex = /(^|\n)\s*%\s(end|set\s)/; /** * 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, { description: _lt("Html"), 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 () { var self = this; this.isRendered = false; this._onUpdateIframeId = 'onLoad_' + _.uniqueId('FieldHtml'); var defAsset; if (this.nodeOptions.cssReadonly) { defAsset = ajax.loadAsset(this.nodeOptions.cssReadonly); } if (!assetsLoaded) { // avoid flickering when begin to edit assetsLoaded = new Promise(function (resolve) { var wysiwyg = new Wysiwyg(self, {}); 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)); }); }, /** * Allows Enter keypress in a textarea (source mode) * * @private * @param {OdooEvent} ev */ _onKeydown: function (ev) { if (ev.which === $.ui.keyCode.ENTER) { ev.stopPropagation(); return; } this._super.apply(this, arguments); }, /** * Method called when wysiwyg triggers a change. * * @private * @param {OdooEvent} ev */ _onReadonlyClickChecklist: function (ev) { var self = this; if (ev.offsetX > 0) { return; } ev.stopPropagation(); ev.preventDefault(); 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', top: '+5px', }); this.$el.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; });