/** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** * @deprecated use lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce4Adapter.js instead */ /* global varienGlobalEvents, tinyMceEditors, MediabrowserUtility, closeEditorPopup, Base64 */ /* eslint-disable strict */ define([ 'jquery', 'underscore', 'tinymceDeprecated', 'mage/adminhtml/wysiwyg/tiny_mce/html5-schema', 'mage/translate', 'prototype', 'mage/adminhtml/events' ], function (jQuery, _, tinyMCE3, html5Schema) { var tinyMce3Wysiwyg = Class.create(); tinyMce3Wysiwyg.prototype = { mediaBrowserOpener: null, mediaBrowserTargetElementId: null, /** * @param {*} htmlId * @param {Object} config */ initialize: function (htmlId, config) { if (config.baseStaticUrl && config.baseStaticDefaultUrl) { tinyMCE3.baseURL = tinyMCE3.baseURL.replace(config.baseStaticUrl, config.baseStaticDefaultUrl); } this.id = htmlId; this.config = config; this.schema = config.schema || html5Schema; _.bindAll( this, 'beforeSetContent', 'saveContent', 'onChangeContent', 'openFileBrowser', 'updateTextArea', 'removeEvents' ); varienGlobalEvents.attachEventHandler('tinymceChange', this.onChangeContent); varienGlobalEvents.attachEventHandler('tinymceBeforeSetContent', this.beforeSetContent); varienGlobalEvents.attachEventHandler('tinymceSetContent', this.updateTextArea); varienGlobalEvents.attachEventHandler('tinymceSaveContent', this.saveContent); if (typeof tinyMceEditors == 'undefined') { window.tinyMceEditors = $H({}); } tinyMceEditors.set(this.id, this); }, /** * @param {*} mode */ setup: function (mode) { if (this.config['widget_plugin_src']) { tinyMCE3.PluginManager.load('magentowidget', 'plugins/magentowidget/editor_plugin.js'); } if (this.config.plugins) { this.config.plugins.each(function (plugin) { tinyMCE3.PluginManager.load(plugin.name, plugin.src); }); } if (jQuery.isReady) { tinyMCE3.dom.Event.domLoaded = true; } tinyMCE3.init(this.getSettings(mode)); }, /** * Remove events from instance. * * @param {String} wysiwygId */ removeEvents: function (wysiwygId) { var editor = tinyMceEditors.get(wysiwygId); varienGlobalEvents.removeEventHandler('tinymceChange', editor.onChangeContent); }, /** * @param {*} mode * @return {Object} */ getSettings: function (mode) { var plugins = 'inlinepopups,safari,pagebreak,style,layer,table,advhr,advimage,emotions,iespell,media,searchreplace,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,noneditable', //eslint-disable-line self = this, magentoPluginsOptions, magentoPlugins, settings; if (this.config['widget_plugin_src']) { plugins = 'magentowidget,' + plugins; } magentoPluginsOptions = $H({}); magentoPlugins = ''; if (this.config.plugins) { this.config.plugins.each(function (plugin) { magentoPlugins = plugin.name + ',' + magentoPlugins; magentoPluginsOptions.set(plugin.name, plugin.options); }); if (magentoPlugins) { plugins = '-' + magentoPlugins + plugins; } } settings = { 'entity_encoding': 'raw', mode: mode != undefined ? mode : 'none', //eslint-disable-line eqeqeq elements: this.id, theme: 'advanced', plugins: plugins, 'theme_advanced_buttons1': magentoPlugins + 'magentowidget,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect', //eslint-disable-line max-len 'theme_advanced_buttons2': 'cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,forecolor,backcolor', //eslint-disable-line max-len 'theme_advanced_buttons3': 'tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,iespell,media,advhr,|,ltr,rtl,|,fullscreen', //eslint-disable-line max-len 'theme_advanced_buttons4': 'insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,pagebreak', //eslint-disable-line max-len 'theme_advanced_toolbar_location': 'top', 'theme_advanced_toolbar_align': 'left', 'theme_advanced_statusbar_location': 'bottom', 'valid_elements': this.schema.validElements.join(','), 'valid_children': this.schema.validChildren.join(','), 'theme_advanced_resizing': true, 'theme_advanced_resize_horizontal': false, 'convert_urls': false, 'relative_urls': false, 'content_css': this.config['content_css'], 'custom_popup_css': this.config['popup_css'], 'magentowidget_url': this.config['widget_window_url'], 'noneditable_leave_contenteditable': true, magentoPluginsOptions: magentoPluginsOptions, doctype: '', //eslint-disable-line max-len /** * @param {Object} ed */ setup: function (ed) { var onChange; ed.onPreInit.add(self.onEditorPreInit.bind(self)); ed.onInit.add(self.onEditorInit.bind(self)); ed.onInit.add(function (editor) { varienGlobalEvents.fireEvent('wysiwygEditorInitialized', editor); }); ed.onSubmit.add(function (edi, e) { varienGlobalEvents.fireEvent('tinymceSubmit', e); }); ed.onPaste.add(function (edi, e, o) { varienGlobalEvents.fireEvent('tinymcePaste', o); }); ed.onBeforeSetContent.add(function (edi, o) { varienGlobalEvents.fireEvent('tinymceBeforeSetContent', o); }); ed.onSetContent.add(function (edi, o) { varienGlobalEvents.fireEvent('tinymceSetContent', o); }); ed.onSaveContent.add(function (edi, o) { varienGlobalEvents.fireEvent('tinymceSaveContent', o); }); /** * @param {*} edi * @param {*} l */ onChange = function (edi, l) { varienGlobalEvents.fireEvent('tinymceChange', l); }; ed.onChange.add(onChange); ed.onKeyUp.add(onChange); ed.onExecCommand.add(function (edi, cmd) { varienGlobalEvents.fireEvent('tinymceExecCommand', cmd); }); } }; // jscs:disable requireDotNotation if (!settings['style_formats']) { settings['theme_advanced_buttons1'] = settings['theme_advanced_buttons1'].replace(',styleselect', ''); } // Set the document base URL if (this.config['document_base_url']) { settings['document_base_url'] = this.config['document_base_url']; } if (this.config['files_browser_window_url']) { /** * @param {*} fieldName * @param {*} url * @param {*} objectType * @param {*} w */ settings['file_browser_callback'] = function (fieldName, url, objectType, w) { varienGlobalEvents.fireEvent('open_browser_callback', { win: w, type: objectType, field: fieldName }); }; } // jscs:enable requireDotNotation if (this.config.width) { settings.width = this.config.width; } if (this.config.height) { settings.height = this.config.height; } if (this.config.settings) { Object.extend(settings, this.config.settings); } return settings; }, /** * @param {Object} editor */ applySchema: function (editor) { var schema = editor.schema, schemaData = this.schema, makeMap = tinyMCE3.makeMap; jQuery.extend(true, { nonEmpty: schema.getNonEmptyElements(), boolAttrs: schema.getBoolAttrs(), whiteSpace: schema.getWhiteSpaceElements(), shortEnded: schema.getShortEndedElements(), selfClosing: schema.getSelfClosingElements(), blockElements: schema.getBlockElements() }, { nonEmpty: makeMap(schemaData.nonEmpty), boolAttrs: makeMap(schemaData.boolAttrs), whiteSpace: makeMap(schemaData.whiteSpace), shortEnded: makeMap(schemaData.shortEnded), selfClosing: makeMap(schemaData.selfClosing), blockElements: makeMap(schemaData.blockElements) }); }, /** * @param {String} id */ get: function (id) { return tinyMCE3.get(id); }, /** * @return {String|null} */ getId: function () { return this.id || (this.activeEditor() ? this.activeEditor().id : null) || tinyMceEditors.values()[0].id; }, /** * @return {Object} */ activeEditor: function () { return tinyMCE3.activeEditor; }, /** * Insert content to active editor. * * @param {String} content * @param {Boolean} ui */ insertContent: function (content, ui) { this.activeEditor().execCommand('mceInsertContent', typeof ui !== 'undefined' ? ui : false, content); }, /** * Set the status of the toolbar to disabled or enabled (true for enabled, false for disabled) * @param {Boolean} enabled */ setToolbarStatus: function (enabled) { _.each(this.activeEditor().controlManager.controls, function (property, index, controls) { controls[property.id].setDisabled(!enabled); }); }, /** * Set the status of the editor and toolbar * * @param {Boolean} enabled */ setEnabledStatus: function (enabled) { if (this.activeEditor()) { this.activeEditor().getBody().setAttribute('contenteditable', enabled); this.activeEditor().readonly = !enabled; this.setToolbarStatus(enabled); } if (enabled) { this.getTextArea().removeProp('disabled'); } else { this.getTextArea().prop('disabled', 'disabled'); } }, /** * Set caret location in WYSIWYG editor. * * @param {Object} targetElement */ setCaretOnElement: function (targetElement) { this.activeEditor().selection.select(targetElement); this.activeEditor().selection.collapse(); }, /** * @param {Object} o */ openFileBrowser: function (o) { var typeTitle = this.translate('Select Images'), storeId = this.config['store_id'] !== null ? this.config['store_id'] : 0, frameDialog = jQuery(o.win.frameElement).parents('[role="dialog"]'), wUrl = this.config['files_browser_window_url'] + 'target_element_id/' + this.getId() + '/' + 'store/' + storeId + '/'; this.mediaBrowserOpener = o.win; this.mediaBrowserTargetElementId = o.field; if (typeof o.type != 'undefined' && o.type != '') { //eslint-disable-line eqeqeq wUrl = wUrl + 'type/' + o.type + '/'; } frameDialog.hide(); jQuery('#mceModalBlocker').hide(); require(['mage/adminhtml/browser'], function () { MediabrowserUtility.openDialog(wUrl, false, false, typeTitle, { /** * Closed. */ closed: function () { frameDialog.show(); jQuery('#mceModalBlocker').show(); } }); }); }, /** * @param {String} string * @return {String} */ translate: function (string) { return jQuery.mage.__ ? jQuery.mage.__(string) : string; }, /** * @return {null} */ getMediaBrowserOpener: function () { return this.mediaBrowserOpener; }, /** * @return {null} */ getMediaBrowserTargetElementId: function () { return this.mediaBrowserTargetElementId; }, /** * @return {jQuery|*|HTMLElement} */ getToggleButton: function () { return $('toggle' + this.getId()); }, /** * Get plugins button. */ getPluginButtons: function () { return jQuery('#buttons' + this.getId() + ' > button.plugin'); }, /** * @param {*} mode * @return {wysiwygSetup} */ turnOn: function (mode) { this.closePopups(); this.setup(mode); tinyMCE3.execCommand('mceAddControl', false, this.getId()); this.getPluginButtons().hide(); return this; }, /** * @return {wysiwygSetup} */ turnOff: function () { this.closePopups(); tinyMCE3.execCommand('mceRemoveControl', false, this.getId()); this.getPluginButtons().show(); return this; }, /** * Close popups. */ closePopups: function () { if (typeof closeEditorPopup == 'function') { // close all popups to avoid problems with updating parent content area closeEditorPopup('widget_window' + this.getId()); closeEditorPopup('browser_window' + this.getId()); } }, /** * @return {Boolean} */ toggle: function () { if (!tinyMCE3.get(this.getId())) { this.turnOn(); return true; } this.turnOff(); return false; }, /** * Editor pre-initialise event handler. */ onEditorPreInit: function (editor) { this.applySchema(editor); }, /** * @deprecated */ onEditorInit: function () {}, /** * On form validation. */ onFormValidation: function () { if (tinyMCE3.get(this.getId())) { $(this.getId()).value = tinyMCE3.get(this.getId()).getContent(); } }, /** * On change content. */ onChangeContent: function () { // Add "changed" to tab class if it exists var tab; this.updateTextArea(); if (this.config['tab_id']) { tab = $$('a[id$=' + this.config['tab_id'] + ']')[0]; if ($(tab) != undefined && $(tab).hasClassName('tab-item-link')) { //eslint-disable-line eqeqeq $(tab).addClassName('changed'); } } }, /** * Retrieve directives URL with substituted directive value. * * @param {String} directive */ makeDirectiveUrl: function (directive) { return this.config['directives_url'] .replace(/directive/, 'directive/___directive/' + directive) .replace(/\/$/, ''); }, /** * Convert {{directive}} style attributes syntax to absolute URLs * @param {Object} content * @return {*} */ encodeDirectives: function (content) { // collect all HTML tags with attributes that contain directives return content.gsub(/<([a-z0-9\-\_]+[^>]+?)([a-z0-9\-\_]+="[^"]*?\{\{.+?\}\}.*?".*?)>/i, function (match) { var attributesString = match[2], decodedDirectiveString; // process tag attributes string attributesString = attributesString.gsub(/([a-z0-9\-\_]+)="(.*?)(\{\{.+?\}\})(.*?)"/i, function (m) { decodedDirectiveString = encodeURIComponent(Base64.mageEncode(m[3].replace(/"/g, '"'))); return m[1] + '="' + m[2] + this.makeDirectiveUrl(decodedDirectiveString) + m[4] + '"'; }.bind(this)); return '<' + match[1] + attributesString + '>'; }.bind(this)); }, /** * @param {Object} content * @return {*} */ encodeWidgets: function (content) { return content.gsub(/\{\{widget(.*?)\}\}/i, function (match) { var attributes = this.parseAttributesString(match[1]), imageSrc, imageHtml; if (attributes.type) { attributes.type = attributes.type.replace(/\\\\/g, '\\'); imageSrc = this.config['widget_placeholders'][attributes.type]; imageHtml = ']+id=\"[^>]+)>/i, function (match) { var attributes = this.parseAttributesString(match[1]), widgetCode; if (attributes.id) { widgetCode = Base64.idDecode(attributes.id); if (widgetCode.indexOf('{{widget') !== -1) { return widgetCode; } } return match[0]; }.bind(this)); }, /** * @param {Object} attributes * @return {Object} */ parseAttributesString: function (attributes) { var result = {}; attributes.gsub( /(\w+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/, function (match) { result[match[1]] = match[2]; } ); return result; }, /** * Update text area. */ updateTextArea: function () { var editor = tinyMCE3.get(this.getId()), content; if (!editor) { return; } content = editor.getContent(); content = this.decodeContent(content); this.getTextArea().val(content).trigger('change'); }, /** * @return {Object} jQuery textarea element */ getTextArea: function () { return jQuery('#' + this.getId()); }, /** * @param {Object} content * @return {*} */ decodeContent: function (content) { var result = content; if (this.config['add_widgets']) { result = this.decodeWidgets(result); result = this.decodeDirectives(result); } else if (this.config['add_directives']) { result = this.decodeDirectives(result); } return result; }, /** * @param {Object} content * @return {*} */ encodeContent: function (content) { var result = content; if (this.config['add_widgets']) { result = this.encodeWidgets(this.decodeWidgets(result)); result = this.encodeDirectives(result); } else if (this.config['add_directives']) { result = this.encodeDirectives(result); } return result; }, /** * @param {Object} o */ beforeSetContent: function (o) { o.content = this.encodeContent(o.content); }, /** * @param {Object} o */ saveContent: function (o) { o.content = this.decodeContent(o.content); }, /** * @returns {Object} */ getAdapterPrototype: function () { return tinyMce3Wysiwyg; } }; return tinyMce3Wysiwyg.prototype; });