123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 |
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- /**
- * @deprecated since version 2.2.0
- */
- (function (root, factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- define([
- 'jquery',
- 'mage/template',
- 'jquery/ui',
- 'mage/translate-inline',
- 'mage/translate'
- ], factory);
- } else {
- factory(root.jQuery, root.mageTemplate);
- }
- }(this, function ($, mageTemplate) {
- 'use strict';
- /**
- * Widget for a dialog to edit translations.
- */
- $.widget('mage.translateInlineDialogVde', $.mage.translateInline, {
- options: {
- translateForm: {
- template: '#translate-inline-dialog-form-template',
- data: {
- selector: '#translate-inline-dialog-form'
- }
- },
- dialogClass: 'translate-dialog',
- draggable: false,
- modal: false,
- resizable: false,
- height: 'auto',
- minHeight: 0,
- buttons: [{
- text: $.mage.__('Cancel'),
- 'class': 'translate-dialog-cancel',
- /**
- * Click.
- */
- click: function () {
- $(this).translateInlineDialogVde('close');
- }
- },
- {
- text: $.mage.__('Save'),
- 'class': 'translate-dialog-save',
- /**
- * Click.
- */
- click: function () {
- $(this).translateInlineDialogVde('submit');
- }
- }],
- area: 'vde',
- ajaxUrl: null,
- textTranslations: null,
- imageTranslations: null,
- scriptTranslations: null,
- translateMode: null,
- translateModes: ['text', 'script', 'alt']
- },
- /**
- * Identifies if the form is already being submitted.
- *
- * @type {Boolean}
- */
- isSubmitting: false,
- /**
- * Identifies if inline text is being editied. Only one element can be edited at a time.
- *
- * @type {Boolean}
- */
- isBeingEdited: false,
- /**
- * Creates the translation dialog widget. Fulfills jQuery WidgetFactory _create hook.
- */
- _create: function () {
- this._super();
- // Unbind previously bound events that may be present from previous loads of vde container.
- if (parent && parent.jQuery) {
- parent.jQuery('[data-frame="editor"]')
- .off('modeChange')
- .on('modeChange', $.proxy(this._checkTranslateEditing, this));
- }
- },
- /**
- * @param {jQuery.Event} e
- * @param {Object} widget
- * @param {Function} callback
- */
- openWithWidget: function (e, widget, callback) {
- if (widget && callback) {
- this.callback = callback;
- this.element.html(this._prepareContent($(widget.element).data('translate')));
- this.triggerElement = widget.element;
- $(window).on('resize.translateInlineDialogVde', $.proxy(this._positionNearTarget, this));
- this._positionNearTarget();
- }
- this.open(arguments);
- },
- /**
- * @private
- */
- _positionNearTarget: function () {
- this.option('position', {
- of: this.triggerElement,
- my: 'left top',
- at: 'left-3 top-9'
- });
- this.option('width', $(this.triggerElement).width());
- },
- /**
- * Close.
- */
- close: function () {
- this._super();
- this._onCancel();
- this.isBeingEdited = false;
- $(window).off('resize.translateInlineVdeDialog');
- },
- /**
- * Shows translate mode applicable css styles.
- */
- toggleStyle: function (mode) {
- // TODO: need to remove eventually
- this._toggleOutline(mode);
- this.options.textTranslations.translateInlineVde('toggleIcon', mode);
- this.options.imageTranslations.translateInlineImageVde('toggleIcon', mode);
- this.options.scriptTranslations.translateInlineScriptVde('toggleIcon', mode);
- },
- /**
- * Determine if user has modified inline translation text, but has not saved it.
- */
- _checkTranslateEditing: function (event, data) {
- var url, dataDisable;
- if (this.isBeingEdited) {
- alert(data['alert_message']); //eslint-disable-line no-alert
- data['is_being_edited'] = true;
- } else {
- // Disable inline translation.
- url = parent.jQuery('[data-frame="editor"]').attr('src');
- dataDisable = {
- frameUrl: url.substring(0, url.indexOf('translation_mode')),
- mode: this.options.translateMode
- };
- parent.jQuery('[vde-translate]').trigger('disableInlineTranslation', dataDisable);
- // Inline translation text is not being edited. Continue on.
- parent.jQuery('[data-frame="editor"]').trigger(data['next_action'], data);
- }
- },
- /**
- * @return {*}
- * @private
- */
- _prepareContent: function () {
- var content = this._superApply(arguments);
- this._on(content.find('textarea[data-translate-input-index]'), {
- /**
- * @param {jQuery.Event} e
- */
- keydown: function (e) {
- var keyCode = $.ui.keyCode;
- switch (e.keyCode) {
- case keyCode.ESCAPE:
- e.preventDefault();
- this.close();
- break;
- case keyCode.ENTER:
- e.preventDefault();
- this._formSubmit();
- break;
- default:
- // keep track of the fact that translate text has been changed
- this.isBeingEdited = true;
- }
- }
- });
- this._on(content.find(this.options.translateForm.data.selector), {
- /**
- * @param {jQuery.Event} e
- * @return {Boolean}
- */
- submit: function (e) {
- e.preventDefault();
- this._formSubmit();
- return true;
- }
- });
- return content;
- },
- /**
- * Submits the form.
- */
- _formSubmit: function () {
- this._superApply(arguments);
- this.isBeingEdited = false;
- },
- /**
- * Callback for when the AJAX call in _formSubmit is completed.
- */
- _formSubmitComplete: function () {
- // TODO: need to replace with merged version
- var self = this;
- this.element.find('[data-translate-input-index]').each($.proxy(function (count, elem) {
- var index = $(elem).data('translate-input-index'),
- value = $(elem).val() || '';
- self.callback(index, value);
- self = null;
- }, this));
- $(window).off('resize.translateInlineVdeDialog');
- this._onSubmitComplete();
- this._superApply(arguments);
- this.isSubmitting = false;
- },
- /**
- * @param {*} mode
- * @private
- */
- _toggleOutline: function (mode) {
- var that = this;
- // TODO: need to remove eventually
- if (mode == null) {
- mode = this.options.translateMode;
- } else {
- this.options.translateMode = mode;
- }
- this.element.closest('[data-container="body"]').addClass('trnslate-inline-' + mode + '-area');
- $.each(this.options.translateModes, function () {
- if (this != mode) { //eslint-disable-line eqeqeq
- that.element.closest('[data-container="body"]').removeClass('trnslate-inline-' + this + '-area');
- }
- });
- },
- /**
- * @private
- */
- _onCancel: function () {
- // TODO: need to remove eventually
- this._toggleOutline();
- this.options.textTranslations.translateInlineVde('show');
- this.options.imageTranslations.translateInlineImageVde('show');
- this.options.scriptTranslations.translateInlineScriptVde('show');
- },
- /**
- * @private
- */
- _onSubmitComplete: function () {
- // TODO: need to remove eventually
- this._toggleOutline();
- this.options.textTranslations.translateInlineVde('show');
- this.options.imageTranslations.translateInlineImageVde('show');
- this.options.scriptTranslations.translateInlineScriptVde('show');
- }
- });
- /**
- * Widget for an icon to be displayed indicating that text can be translated.
- */
- $.widget('mage.translateInlineVde', {
- options: {
- iconTemplateSelector: '[data-template="translate-inline-icon"]',
- img: null,
- imgHover: null,
- offsetLeft: -16,
- dataAttrName: 'translate',
- translateMode: null,
- /**
- * On click.
- */
- onClick: function () {}
- },
- /**
- * Elements to wrap instead of just inserting a child element. This is
- * to work around some different behavior in Firefox vs. WebKit.
- *
- * @type {Array}
- */
- elementsToWrap: ['button'],
- /**
- * Determines if the template is already appended to the element.
- *
- * @type {Boolean}
- */
- isTemplateAttached: false,
- iconTemplate: null,
- iconWrapperTemplate: null,
- elementWrapperTemplate: null,
- /**
- * Determines if the element is suppose to be wrapped or just attached.
- *
- * @type {Boolean}, null is unset, false/true is set
- */
- isElementWrapped: null,
- /**
- * Creates the icon widget to indicate text that can be translated.
- * Fulfills jQuery's WidgetFactory _create hook.
- */
- _create: function () {
- this.element.addClass('translate-edit-icon-container');
- this._initTemplates();
- this.show();
- },
- /**
- * Shows the widget.
- */
- show: function () {
- this._attachIcon();
- this.iconTemplate.removeClass('hidden');
- if (this.element.data('translateMode') != this.options.translateMode) { //eslint-disable-line eqeqeq
- this.iconTemplate.addClass('hidden');
- }
- this.element.on('dblclick', $.proxy(this._invokeAction, this));
- this._disableElementClicks();
- },
- /**
- * Show edit icon for given translate mode.
- */
- toggleIcon: function (mode) {
- if (mode == this.element.data('translateMode')) { //eslint-disable-line eqeqeq
- this.iconTemplate.removeClass('hidden');
- } else {
- this.iconTemplate.addClass('hidden');
- }
- this.options.translateMode = mode;
- },
- /**
- * Determines if the element should have an icon element wrapped around it or
- * if an icon element should be added as a child element.
- */
- _shouldWrap: function () {
- var c;
- if (this.isElementWrapped !== null) {
- return this.isElementWrapped;
- }
- this.isElementWrapped = false;
- for (c = 0; c < this.elementsToWrap.length; c++) {
- if (this.element.is(this.elementsToWrap[c])) {
- this.isElementWrapped = true;
- break;
- }
- }
- return this.isElementWrapped;
- },
- /**
- * Attaches an icon to the widget's element.
- */
- _attachIcon: function () {
- if (this._shouldWrap()) {
- if (!this.isTemplateAttached) {
- this.iconWrapperTemplate = this.iconTemplate.wrap('<div/>').parent();
- this.iconWrapperTemplate.addClass('translate-edit-icon-wrapper-text');
- this.elementWrapperTemplate = this.element.wrap('<div/>').parent();
- this.elementWrapperTemplate.addClass('translate-edit-icon-container');
- this.iconTemplate.appendTo(this.iconWrapperTemplate);
- this.iconWrapperTemplate.appendTo(this.elementWrapperTemplate);
- }
- } else {
- this.iconTemplate.appendTo(this.element);
- this.element.removeClass('invisible');
- }
- this.isTemplateAttached = true;
- },
- /**
- * Disables the element click from actually performing a click.
- */
- _disableElementClicks: function () {
- this.element.find('a').off('click');
- if (this.element.is('A')) {
- this.element.on('click', function () {
- return false;
- });
- }
- },
- /**
- * Hides the widget.
- */
- hide: function () {
- this.element.off('dblclick');
- this.iconTemplate.addClass('hidden');
- },
- /**
- * Replaces the translated text inside the widget with the new value.
- */
- replaceText: function (index, value) {
- var translateData = this.element.data(this.options.dataAttrName),
- innerHtmlStr = this.element.html();
- if (value === null || value === '') {
- value = ' ';
- }
- innerHtmlStr = innerHtmlStr.replace(translateData[index].shown, value);
- this.element.html(innerHtmlStr);
- translateData[index].shown = value;
- translateData[index].translated = value;
- this.element.data(this.options.dataAttrName, translateData);
- },
- /**
- * Initializes all the templates for the widget.
- */
- _initTemplates: function () {
- this._initIconTemplate();
- this.iconTemplate.addClass('translate-edit-icon-text');
- },
- /**
- * Changes depending on hover action.
- */
- _hoverIcon: function () {
- if (this.options.imgHover) {
- this.iconTemplate.prop('src', this.options.imgHover);
- }
- },
- /**
- * Changes depending on hover action.
- */
- _unhoverIcon: function () {
- if (this.options.imgHover) {
- this.iconTemplate.prop('src', this.options.img);
- }
- },
- /**
- * Initializes the icon template for the widget. Sets the widget up to
- * respond to events.
- */
- _initIconTemplate: function () {
- this.iconTemplate = $(mageTemplate(this.options.iconTemplateSelector, {
- data: this.options
- }));
- this.iconTemplate.on('click', $.proxy(this._invokeAction, this))
- .on('mouseover', $.proxy(this._hoverIcon, this))
- .on('mouseout', $.proxy(this._unhoverIcon, this));
- },
- /**
- * Invokes the action (e.g. activate the inline dialog)
- */
- _invokeAction: function (event) {
- this._detachIcon();
- this.options.onClick(event, this);
- },
- /**
- * Destroys the widget. Fulfills jQuery's WidgetFactory _destroy hook.
- */
- _destroy: function () {
- this.iconTemplate.remove();
- this._detachIcon();
- },
- /**
- * Detaches an icon from the widget's element.
- */
- _detachIcon: function () {
- this._unhoverIcon();
- $(this.iconTemplate).detach();
- if (this._shouldWrap()) {
- this.iconWrapperTemplate.remove();
- this.element.unwrap();
- this.elementWrapperTemplate.remove();
- } else {
- this.element.addClass('invisible');
- }
- this.isTemplateAttached = false;
- }
- });
- $.widget('mage.translateInlineImageVde', $.mage.translateInlineVde, {
- /**
- * @private
- */
- _attachIcon: function () {
- if (!this.isTemplateAttached) {
- this.iconWrapperTemplate = this.iconTemplate.wrap('<div/>').parent();
- this.iconWrapperTemplate.addClass('translate-edit-icon-wrapper-image');
- this.elementWrapperTemplate = this.element.wrap('<div/>').parent();
- this.elementWrapperTemplate.addClass('translate-edit-icon-container');
- this.iconTemplate.appendTo(this.iconWrapperTemplate);
- this.iconWrapperTemplate.appendTo(this.elementWrapperTemplate);
- this.isTemplateAttached = true;
- }
- },
- /**
- * @private
- */
- _initTemplates: function () {
- this._initIconTemplate();
- this.iconTemplate.addClass('translate-edit-icon-image');
- },
- /**
- * @private
- */
- _detachIcon: function () {
- $(this.iconTemplate).detach();
- this.iconWrapperTemplate.remove();
- this.element.unwrap();
- this.elementWrapperTemplate.remove();
- this.isTemplateAttached = false;
- }
- });
- $.widget('mage.translateInlineScriptVde', $.mage.translateInlineVde, {});
- /*
- * @TODO move the "escapeHTML" method into the file with global utility functions
- */
- $.extend(true, $, {
- mage: {
- /**
- * @param {String} str
- * @return {String}
- */
- escapeHTML: function (str) {
- return str ? str.replace(/"/g, '"') : '';
- }
- }
- });
- }));
|