'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /** * Licensed Materials - Property of IBM * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2017, 2020 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['../../../lib/@waca/core-client/js/core-client/ui/core/View', '../../../lib/@waca/core-client/js/core-client/utils/BidiUtil', '../../../dashboard/util/TextEditor', '../../../app/util/LocaleUtil', '../../../app/nls/StringResources', 'jquery', 'underscore'], function (View, BidiUtil, TextEditor, LocaleUtil, resources, $, _) { var localizedProp = function localizedProp(str) { if ((typeof str === 'undefined' ? 'undefined' : _typeof(str)) === 'object') { var locale = document.getElementsByTagName('html')[0].getAttribute('lang'); return str[locale] || str.en || str[Object.keys(str)[0]]; } return str; }; var WidgetTitleView = View.extend({ init: function init(options) { this.titleId = options.id + 'Title'; this.canEditTitle = options.canEditTitle; this.widgetModel = options.widgetModel; this.widgetChromeEventRouter = options.widgetChromeEventRouter; this.header = options.header; this.dashboardApi = options.dashboardApi; this.registerEvents(); }, registerEvents: function registerEvents() { this.widgetChromeEventRouter.on('title:chromeSelected', this.onChromeSelected, this); this.widgetChromeEventRouter.on('title:chromeDeselected', this.onChromeDeselected, this); this.widgetChromeEventRouter.on('title:containerReady', this.onContainerReady, this); this.widgetChromeEventRouter.on('title:enterContainer', this.onEnterContainer, this); this.widgetChromeEventRouter.on('title:updateModel', this.updateModelContent, this); this.widgetChromeEventRouter.on('widget:clearWidgetArialabel', this.clearWidgetArialabel, this); this.widgetChromeEventRouter.on('widget:updateWidgetArialabel', this.updateWidgetArialabel, this); if (this._isSmartTitleEnabled()) { this.widgetModel.on('change:titleMode', this._showTitle, this); } else { this.widgetModel.on('change:showTitle', this._showTitle, this); } }, /** * Based on properties, generate the HTML for the static content */ getHtmlRender: function getHtmlRender() { return this.getStyleNode().get(0).outerHTML; }, _getTextProperties: function _getTextProperties(text) { return { style: 'responsive', text: text }; }, /** * Render widget title view * @param {boolean} [hidden=false] whether to render hidden or not */ render: function render() { var hidden = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var titleHtml = void 0; var title = ''; if (this.widgetModel && this.widgetModel.get) { titleHtml = TextEditor.cleanContentElements(this.widgetModel.get('titleHtml')); title = this.widgetModel.get('name'); } var sTitle = title ? localizedProp(title) : ''; if (titleHtml) { this.$el = $(titleHtml); if (!this.$el.length) { this.$el = $('
' + titleHtml + '
'); } this._nTitle = this.$el.find('.textArea'); } else { this.$el = $('
', { 'class': 'widgetTitle', 'title': sTitle }); this.$el.attr('aria-labelledby', this.titleId); this._nTitle = $('
', { 'class': 'textArea' }); this.$el.prepend(this._nTitle); } this.$el.attr('appcues-data-id', 'widgetTitle'); this.$el.toggleClass('titleShown', !!(sTitle && sTitle.length)); var shouldShowTitle = this._shouldShowTitle(); this._nTitle.toggleClass('hidden', hidden && !shouldShowTitle); }, remove: function remove() { this.widgetChromeEventRouter.off('title:chromeSelected', this.onChromeSelected, this); this.widgetChromeEventRouter.off('title:chromeDeselected', this.onChromeDeselected, this); this.widgetChromeEventRouter.off('title:containerReady', this.onContainerReady, this); this.widgetChromeEventRouter.off('title:enterContainer', this.onEnterContainer, this); this.widgetChromeEventRouter.off('title:updateModel', this.updateModelContent, this); this.widgetChromeEventRouter.off('widget:clearWidgetArialabel', this.clearWidgetArialabel, this); this.widgetChromeEventRouter.off('widget:updateWidgetArialabel', this.updateWidgetArialabel, this); if (this._isSmartTitleEnabled()) { this.widgetModel.off('change:titleMode', this._showTitle, this); } else { this.widgetModel.off('change:showTitle', this._showTitle, this); } this.widgetModel.off('change:titleHtml', this._onTitleHtmlChange, this); if (this.textEditor) { this.textEditor.destroy(); this.textEditor = null; } WidgetTitleView.inherited('remove', this, arguments); }, onContainerReady: function onContainerReady(widget) { var _this = this; var truncateFeature = widget && widget.content && widget.content.getFeature && widget.content.getFeature('WidgetTitleTruncate'); var extension = truncateFeature && truncateFeature.getExtensionHooks(); truncateFeature && truncateFeature.setUpdateModelContent(this.updateModelContent.bind(this)); truncateFeature && truncateFeature.setTitleHighlighter(this._highlightTitle.bind(this)); this._handleEditUpdateTruncation = extension && extension.onEditUpdate; // TODO: Revisit how this class is implemented. // There could be a chance that some of the functions in the class are called before onContainerReady, // causing a null exception when accessing 'this.textEditor'. (e.g. updateTitle()) // For now, we check for this.textEditor === null all over this class to make sure when don't blow up. this.widget = widget; this.textEditor = new TextEditor({ 'node': this._nTitle, 'container': this.header, 'widget': widget, 'fontSizes': TextEditor.INT_FONTSIZE_CHOICES, 'toolbarNode': widget.$widgetContainer, 'shouldResizeViz': true, 'initialState': { 'fontSize': '16', 'color': 'responsiveColor' }, 'extension': extension }); if (LocaleUtil.isLocaleRTL()) { BidiUtil.initElementForBidi(this._nTitle); } //Widget title is never responsive (Removed auto size) this.textEditor.isResponsive = false; this.widgetModel.on('change:titleHtml', this._onTitleHtmlChange, this); this.textEditor.initContentEditable('p'); this.textEditor.selectionBindNodeEvents(); this._applyTitle(); this._updateAriaInfo(); // register the textEditor as a properties provider for text format properties return this.dashboardApi.getCanvasWhenReady().then(function (canvas) { var content = canvas.getContent(widget.id); content.getFeature('Properties').registerProvider(_this.textEditor); content.getFeature('TextEditor').registerProvider({ 'widgetId': widget.id, 'textEditor': _this.textEditor, 'titleId': _this.titleId }); }); }, _updateAriaInfo: function _updateAriaInfo() { var titleNodeId = this.widgetModel.id + 'Title'; this.$el.find('.note-editable').attr('id', titleNodeId); }, _onTitleHtmlChange: function _onTitleHtmlChange(options) { options = options || {}; if (options && (options.value === null || options.value === '' || options.value === undefined)) { this._setTitleHtmlFromName(); } else { if (this.textEditor) { var appliedContentResult = this.textEditor.applyContent(options); var title = this.textEditor.getTitleFromHtml(this.getHtmlRender()); this.$el.prop('title', title); //update title, so tooltip is also synced return appliedContentResult; } } }, _applyTitle: function _applyTitle() { var _this2 = this; if (!this.textEditor) { return; } var translationService = this.dashboardApi.getFeature('TranslationService'); if (!this.widgetModel.get('name')) { //We only show placeholder text if smart title is disabled or //when the smart title feature is enabled and the user is in the custom title var titleMode = this.widget && this.widget.content && this.widget.content.getPropertyValue('titleMode'); var smartTitleEnabled = this._isSmartTitleEnabled(); var addPlaceHolderTitle = false; if (smartTitleEnabled) { addPlaceHolderTitle = titleMode && titleMode === 'customTitle'; } else { addPlaceHolderTitle = true; } if (this.canEditTitle && addPlaceHolderTitle) { var prop = this._getTextProperties(resources.get('titlePlaceHolder')); this.textEditor.setText(TextEditor.getTextHTML(prop)); smartTitleEnabled && this.textEditor.toggleEditing(true); } else { this.textEditor.setText(' '); } } else if (!this.widgetModel.get('titleHtml')) { //Special case for upgraded dashboard. if (this.widgetModel['name'] && this.widgetModel['name'].translationTable) { //update all the locales _.each(this.widgetModel['name'].translationTable, function (item, locale) { //update the locale _this2.widgetModel.set({ 'name': { locale: locale, value: item } }); _this2._setTitleHtmlFromName(locale); }); } //and ensure our html is reset to the default locale. this._setTitleHtmlFromName(); } else if (translationService.isInTranslationMode()) { this._updateTextEditor(); } }, /** * Set the HTML for a specific name properly using the provided locale (or Default if locale is null) * This is storing HTML directly in the spec. This is not ideal to say the least. */ _setTitleHtmlFromName: function _setTitleHtmlFromName(locale) { if (!this.textEditor) { return; } var prop = this._updateTextEditor(locale); //update the aria labels if (prop.text) { this.$el.prop('title', prop.text); this.$el.find('.ariaLabelNode').html(TextEditor.cleanContentElements(prop.text)); } var updatedHtml = TextEditor.cleanContentElements(this.getHtmlRender()); //Get the default language if ant var boardModel = this.dashboardApi.getFeature('internal').getBoardModel(); var titleOptions = boardModel.getLanguageModelOptions(); _.extend(titleOptions, { silent: true }); this.widgetModel.set({ titleHtml: { value: updatedHtml, locale: locale } }, titleOptions); }, _updateTextEditor: function _updateTextEditor(locale) { var _propValue = this.widgetModel.get('name'); //get the localized value of the name if (locale && this.widgetModel['name']) { _propValue = this.widgetModel['name'].getValue(locale); } var prop = this._getTextProperties(_propValue); var _textHTML = TextEditor.getTextHTML(prop); this.textEditor.setText(_textHTML); //update so smart title updates don't confuse text editor into thinking edit happened and it needs to save this.textEditor.updateLastSavedText(_textHTML); return prop; }, _showTitle: function _showTitle(options) { this.updateTitle(options); //only toggleEdit (highlights all title text) when needed - if smart title is disabled or when its enabled and we are changing //from noTitle to customTitle var showTitle = this.widgetModel.showTitle; var titleMode = this.widget.content.getPropertyValue('titleMode'); if (!showTitle && titleMode === 'customTitle') { if (options && options.prevValue === 'noTitle') { showTitle = true; } else { showTitle = false; } } if (this.canEditTitle && showTitle) { if (this.textEditor && this.widget && this.widget.chromeSelected && this.widget.isAuthoringMode) { this.textEditor.toggleEditing(!(options && options.data && options.data.edit === false), options); } } }, _hasHeader: function _hasHeader() { if (this.widget && this.widget.$el && this.widget.$el.parent() && this.widget.$el.parent().find) { return this.widget.$el.parent().find('.widgetHeader').length !== 0; } return false; }, _toggleEdit: function _toggleEdit(toggle) { if (!this.textEditor) { return; } var eventName = 'showTitle'; var eventValue = false; if (this._isSmartTitleEnabled()) { eventName = 'titleMode'; eventValue = 'noTitle'; } if (this.textEditor.isEditing() && this.textEditor.textIsEmpty() && toggle === false) { this.widget.content.setPropertyValue(eventName, eventValue); } this.textEditor.toggleEditing(toggle); }, checkAndRecreateHeader: function checkAndRecreateHeader() { if (!this.widget) { return; } if (this.widget.isWidgetMaximized && this.widget.isWidgetMaximized()) { return; } if (!this._hasHeader()) { this.widgetChromeEventRouter.trigger('title:resetTitle', { widgetTitleView: this }); } }, _shouldShowTitle: function _shouldShowTitle() { //ShowTitle-support old (showTitle) and new (titleMode) if (this.widgetModel.titleMode === undefined) { return !!this.widgetModel.showTitle; } var titleMode = this.widgetModel.titleMode || 'smartTitle'; return titleMode !== 'noTitle'; }, _isWidgetReady: function _isWidgetReady() { var widgetReady = true; var visualization = this.widget && this.widget.content && this.widget.content.getFeature('Visualization'); if (visualization && visualization.getSlots() && visualization.getSlots().isMappingComplete() === false) { widgetReady = false; } return widgetReady; }, updateTitle: function updateTitle(options) { var widgetReady = this._isWidgetReady(); var shouldShowTitle = this._shouldShowTitle() && widgetReady; var wasShowingTitle = !this._nTitle.hasClass('hidden'); if (shouldShowTitle) { this.checkAndRecreateHeader(); this._applyTitle(); this._nTitle.removeClass('hidden'); } else { this._nTitle.addClass('hidden'); if (this.textEditor) { this.textEditor.toggleEditing(false, options); } } if (shouldShowTitle !== wasShowingTitle) { this.widgetChromeEventRouter.trigger('title:resizeViz'); } }, onChromeSelected: function onChromeSelected() { WidgetTitleView.inherited('onChromeSelected', this, arguments); if (this.textEditor && this.canEditTitle) { this.textEditor.attachEnterEditEvents(); } }, onChromeDeselected: function onChromeDeselected() { WidgetTitleView.inherited('onChromeDeselected', this, arguments); this._toggleEdit(false); if (this.textEditor) { this.textEditor.detachEnterEditEvents(); } }, onChromeOffFocus: function onChromeOffFocus() { this._toggleEdit(false); }, getProperties: function getProperties(properties) { return this.textEditor.getProperties(properties); }, onEnterContainer: function onEnterContainer() { if (this.textEditor && this.canEditTitle) { this.textEditor.toggleEditing(true); } }, /** * Updates the model version of the markup of this widget * @param updatedHtml An optional parameter of the markup. * This is to avoid regenerating the markup if it is already known. */ updateModelContent: function updateModelContent(info) { if (!this.textEditor) { return; } // update the model to persist the changes. Use transactionId to combine undos var boardModel = this.dashboardApi.getFeature('internal').getBoardModel(); var data = boardModel.getLanguageModelOptions(); if (info.transactionId) { _.extend(data, { payloadData: { undoRedoTransactionId: info.transactionId, transactionToken: info.transactionToken } }); } else { _.extend(data, { silent: true }); } //SMEditTest var title = this.textEditor.getTitleFromHtml(this.getHtmlRender()); var existingTitle = null; if (this.widgetModel && this.widgetModel.get) { existingTitle = this.widgetModel.get('name'); } var sExistingTitle = existingTitle ? localizedProp(existingTitle) : ''; this.$el.prop('title', title); //update title, so tooltip is also synced var updatedHtml = TextEditor.cleanContentElements(this.getHtmlRender()); this._handleEditUpdateTruncation && this._handleEditUpdateTruncation(sExistingTitle, updatedHtml, title, info.transactionId); //SMEditTest this.widgetModel.set({ titleHtml: updatedHtml, name: title }, data); }, //only used in the context of edit Title action - in some cases, we just need to highlight the title _highlightTitle: function _highlightTitle() { this.textEditor.toggleEditing(true); }, updateWidgetArialabel: function updateWidgetArialabel(event) { if (this._nAriaLabel) { this._nAriaLabel.text(event.value); } }, clearWidgetArialabel: function clearWidgetArialabel() { if (this._nAriaLabel) { this._nAriaLabel.empty(); } }, getStyleNode: function getStyleNode() { return this.$el; }, _isSmartTitleEnabled: function _isSmartTitleEnabled() { var featureChecker = this.dashboardApi.getGlassCoreSvc('.FeatureChecker'); if (featureChecker) { return !(featureChecker.checkValue && featureChecker.checkValue('dashboard', 'SmartTitle', 'disabled')); } return false; } }); return WidgetTitleView; }); //# sourceMappingURL=WidgetTitleView.js.map