123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- '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 = $('<div class="widgetTitle" title="' + sTitle + '">' + titleHtml + '</div>');
- }
- this._nTitle = this.$el.find('.textArea');
- } else {
- this.$el = $('<div>', {
- 'class': 'widgetTitle',
- 'title': sTitle
- });
- this.$el.attr('aria-labelledby', this.titleId);
- this._nTitle = $('<div>', {
- '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
|