123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- 'use strict';
- /**
- * Licensed Materials - Property of IBM
- * IBM Cognos Products: Storytelling
- * (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(['baglass/core-client/js/core-client/ui/core/View', 'jquery', 'gemini/app/util/ScreenReaderUtil', 'storytelling-ui/storytelling-ui.min', 'text!./templates/TimelineHighlightIndicatorView.html', 'dashboard-analytics/visualizations/renderer/filter/FilterLabelHelper', './highlight/TimelineHighlightFlyoutController', 'react', 'react-dom', '../util/WidgetHelper'], function (View, $, ScreenReaderUtil, StorytellingUI, Template, FilterLabelHelper, TimelineHighlightFlyoutController, React, ReactDOM, WidgetHelper) {
- var Indicator = View.extend({
- templateString: Template,
- //@override
- /**
- * @param options.$el {object} - JQuery node to append the highlight HTML
- * @param options.widgetId {string} - the widget Id of the selected timeline widget
- * @param options.scaleManager {object} - scaleManager of the timeline
- * @param options.episodeModel {object} - episodeModel of the selected timeline widget
- * @param options.highlightAct {object} - optional, the existing highlightAct model
- */
- init: function init(options) {
- Indicator.inherited('init', this, arguments);
- this.controller = options.controller;
- this.widgetId = options.widgetId;
- this.scaleManager = options.scaleManager;
- this.episodeModel = options.episodeModel;
- this.highlightAct = options.highlightAct;
- this.id = options.highlightAct.id;
- this.services = options.services;
- this.dashboardApi = options.dashboardApi;
- this.widgetHelper = new WidgetHelper({ dashboardApi: this.dashboardApi });
- this.widget = this.widgetHelper.getWidget(this.widgetId);
- this.content = this.widgetHelper.getContent(this.widgetId);
- if (this.widget && this.content) {
- this.visualization = this.content.getFeature('Visualization');
- this.filterLabelHelper = new FilterLabelHelper({
- dataSource: this.visualization.getDataSource(),
- dashboardApi: this.dashboardApi
- });
- }
- this.pageContextAPI = this.controller.model.pageContext.getAPI();
- this.extraCssClass = options.extraCssClass || '';
- this._ScreenReader = new ScreenReaderUtil();
- this.stringResources = this.dashboardApi.getDashboardCoreSvc('.StringResources');
- this.flyoutHolder = document.createElement('div');
- this.flyoutHolder.classList.add('flyout-holder');
- },
- render: function render() {
- var label = this._getTooltipLabel();
- this.el.id = 'timelineHighlight_' + this.id;
- this.el.setAttribute('role', 'application');
- this.el.className = 'timelineHighlight ' + this.extraCssClass;
- this.el.setAttribute('tabindex', '0');
- this.el.dataset.selector = 'true';
- this.el.dataset.id = this.id;
- if (label) {
- this.el.setAttribute('aria-label', label);
- this.el.setAttribute('title', label);
- }
- var sHtml = this.dotTemplate({
- id: this.id
- });
- this.$el.html(sHtml);
- this._indicatorWidth = this.$el.outerWidth();
- this._handleWidth = this.$el.closest('.sliderContent').find('.handle').outerWidth();
- // here we assume that timer is inside the widget since it's the persisted value;
- this._updateHighlightPosition(this.highlightAct.timer, false);
- this._updateHighlightState();
- this._registerEvents();
- },
- remove: function remove() {
- this._unregisterEvents();
- Indicator.inherited('remove', this, arguments);
- },
- onSliderChange: function onSliderChange() {
- this._updateHighlightPosition(this.highlightAct.timer, false);
- },
- onScaleChange: function onScaleChange() {
- this._updateHighlightPosition(this.highlightAct.timer, false);
- },
- onPayloadChange: function onPayloadChange() {
- this._updateHighlightState();
- this._updateTooltipLabel();
- },
- _updateHighlightState: function _updateHighlightState() {
- if (this.highlightAct.get('payload').filter(function (item) {
- return item.operator;
- }).length) {
- this.$el.removeClass('empty');
- } else {
- this.$el.addClass('empty');
- }
- },
- _updateHighlightPosition: function _updateHighlightPosition(time, isDragging) {
- // round to the nearest tick for display
- var tick = this.controller.getTickDuration();
- time = Math.round(time / tick) * tick;
- var position = this.scaleManager.convertTimeToPosition(time);
- // the center of the icon on the time
- position -= this._indicatorWidth / 2;
- // if we are dragging we allow the indicator to be over the handles.
- if (!isDragging) {
- position = this._limitPositionToInsideHandles(position);
- }
- this.$el.css('left', position + 'px');
- return position;
- },
- launchHighlightSummaryDialog: function launchHighlightSummaryDialog() {
- this.flyoutView = new TimelineHighlightFlyoutController({
- dashboardApi: this.dashboardApi,
- content: this.content,
- visualization: this.visualization,
- pageContextAPI: this.pageContextAPI,
- services: this.services,
- highlightAct: this.highlightAct,
- launchView: this,
- show: this.launchHighlightSummaryDialog,
- launchPoint: this.$el.get(0)
- });
- this.$el.append(this.flyoutHolder);
- this._flyout = React.createElement(StorytellingUI.HighlightSummaryFlyout, {
- anchorElement: this.$el.get(0),
- closeFlyout: this.closeFlyout.bind(this),
- itemActions: this.flyoutView.getItemActions(),
- title: this.stringResources.get('timelineHighlightTitle')
- });
- ReactDOM.render(this._flyout, this.flyoutHolder);
- },
- getPlacement: function getPlacement() {
- return 'top';
- },
- _registerEvents: function _registerEvents() {
- this._dragStartCallback = this._onDragStart.bind(this);
- this._dragLeftRightCallback = this._onDragLeftRight.bind(this);
- this._dragEndCallback = this._onDragEnd.bind(this);
- this._clickCallback = this._onClick.bind(this);
- this._onKeyPressCallback = this._onKeyPress.bind(this);
- this.$el.hammer({ correct_for_drag_min_distance: false }).on('dragstart', this._dragStartCallback).on('dragleft', this._dragLeftRightCallback).on('dragright', this._dragLeftRightCallback).on('dragend', this._dragEndCallback);
- this.$el.find('.svgIcon').on('primaryaction', this._clickCallback);
- this.$el.on('keydown', this._onKeyPressCallback);
- },
- setTime: function setTime(value) {
- this._updateHighlightPosition(value, false);
- },
- _unregisterEvents: function _unregisterEvents() {
- if (this._flyout) {
- this.closeFlyout();
- }
- if (this.$el) {
- this.$el.off('dragstart', null, this._dragStartCallback).off('dragleft', null, this._dragLeftRightCallback).off('dragright', null, this._dragLeftRightCallback).off('dragend', null, this._dragEndCallback);
- this.$el.find('.svgIcon').off('primaryaction', this._clickCallback);
- this.$el.off('keydown', this._onKeyPressCallback);
- }
- },
- _onDragLeftRight: function _onDragLeftRight(event) {
- if (event.gesture) {
- event.gesture.preventDefault();
- event.gesture.stopPropagation();
- var position = this._positionFromLeft + event.gesture.deltaX;
- var time = this.scaleManager.convertPositionToTime(position);
- time = this._limitTimerToSlider(time);
- this._updateHighlightPosition(time, true);
- }
- },
- _onDragEnd: function _onDragEnd(event) {
- if (event.gesture) {
- event.gesture.stopPropagation();
- this.controller.trigger('timeline:highlightIndicatorDragEnded');
- var position = this._positionFromLeft + event.gesture.deltaX;
- var time = this.scaleManager.convertPositionToTime(position);
- time = this._limitTimerToSlider(time);
- this._updateHighlightPosition(time, false);
- this.controller.updateTimelineHighlight(this.widgetId, this.id, { timer: time });
- }
- this._dragEnd = true;
- },
- _onDragStart: function _onDragStart() {
- this.closeFlyout();
- this.controller.trigger('timeline:highlightIndicatorDragStarted', this.widgetId);
- var position = this.scaleManager.convertTimeToPosition(this.highlightAct.timer);
- // the user drags the icon around so we make sure the icon is over the mouse by clamping it to inside the handles
- // this means that if the timer value was zero and the user moves 1 pixel it could be something like 200 depending on the scale
- // but nothing stops the user from dragging it back to zero.
- this._positionFromLeft = this._limitPositionToInsideHandles(position);
- },
- _updateTooltipLabel: function _updateTooltipLabel() {
- var label = this._getTooltipLabel();
- if (label !== this.$el.attr('title')) {
- this.$el.attr('title', label);
- this.$el.attr('aria-label', label);
- }
- },
- _getTooltipLabel: function _getTooltipLabel() {
- var _this = this;
- var label = this.stringResources.get('timelineHighlightTitle');
- if (this.filterLabelHelper) {
- var filterItems = this.filterLabelHelper.generateFilterListItems(this.highlightAct.payload);
- filterItems.forEach(function (filter) {
- label += '\n';
- label += _this.stringResources.get('filter_tooltip', {
- title: filter.title,
- description: filter.description
- });
- });
- }
- return label;
- },
- _onClick: function _onClick(event) {
- if (event.type === 'click' && this._dragEnd) {
- // Hammer will trigger a ghostclick event after dragend in Firefox
- this._dragEnd = false;
- return;
- }
- event.stopPropagation();
- event.preventDefault();
- if (!this.visAPI) {
- // widget has not been loaded. return
- var widget = this.widgetHelper.getWidget(this.widgetId);
- var content = this.widgetHelper.getContent(this.widgetId);
- if (!widget || !content) {
- return;
- } else {
- this.visAPI = widget.getVisApi && widget.getVisApi();
- this.visualization = content.getFeature('Visualization');
- }
- }
- this.$el.append(this.flyoutHolder);
- var flyout = React.createElement(StorytellingUI.HighlightFlyout, {
- widgetId: this.widgetId,
- actId: this.id,
- controller: this.controller,
- anchorElement: this.$el.get(0),
- closeFlyout: this.closeFlyout.bind(this),
- openSummaryDialog: this.launchHighlightSummaryDialog.bind(this)
- });
- ReactDOM.render(flyout, this.flyoutHolder);
- },
- _onKeyPress: function _onKeyPress(event) {
- var $target = $(event.currentTarget);
- // Set as selected
- $target.focus();
- // Setup the number of pixels to move based on arrow key pressed
- var xMoveBy = 0;
- switch (event.keyCode) {
- case 13:
- case 32:
- //Return or Space launches Flyout ODT
- this._onClick(event);
- return;
- case 37:
- //Left
- xMoveBy = this.scaleManager.convertPositionToTime(-20);
- break;
- case 39:
- //Right
- xMoveBy = this.scaleManager.convertPositionToTime(20);
- break;
- case 38:
- case 40:
- event.stopPropagation();
- event.preventDefault();
- return;
- default:
- return;
- }
- event.stopPropagation();
- event.preventDefault();
- //Moving from the current position.
- var time = this._limitTimerToSlider(this.highlightAct.timer + xMoveBy);
- this._updateHighlightPosition(time, false);
- this.controller.updateTimelineHighlight(this.widgetId, this.id, { timer: time });
- var messageOptions = {
- id: this.id,
- time: time
- };
- var sMessage = this.stringResources.get('timeline_highlight_moved_to', messageOptions);
- this._ScreenReader.callOut(sMessage);
- },
- _limitTimerToSlider: function _limitTimerToSlider(timerValue) {
- timerValue = Math.max(timerValue, this.episodeModel.getEntranceAct().timer + 1);
- timerValue = Math.min(timerValue, this.episodeModel.getExitAct().timer - 1);
- return timerValue;
- },
- _limitPositionToInsideHandles: function _limitPositionToInsideHandles(position) {
- var entranceTime = this.episodeModel.getEntranceAct().timer;
- var min = this.scaleManager.convertTimeToPosition(entranceTime);
- min += this._handleWidth;
- var exitTime = this.episodeModel.getExitAct().timer;
- var max = this.scaleManager.convertTimeToPosition(exitTime);
- max -= this._handleWidth + this._indicatorWidth;
- position = Math.min(position, max);
- position = Math.max(position, min);
- // if there is not enough space between the handles we split the difference.
- var contentWidth = this.scaleManager.convertTimeToPosition(exitTime - entranceTime - this._handleWidth * 2);
- if (contentWidth < this._indicatorWidth) {
- position -= (this._indicatorWidth - contentWidth) / 2;
- }
- return position;
- },
- closeFlyout: function closeFlyout() {
- ReactDOM.unmountComponentAtNode(this.flyoutHolder);
- this.$el.find('.flyout-holder').remove();
- }
- });
- return Indicator;
- });
- //# sourceMappingURL=TimelineHighlightIndicatorView.js.map
|