'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 = $('
', {
'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