123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- 'use strict';
- /**
- * Licensed Materials - Property of IBM
- * IBM Cognos Products: Storytelling
- * (C) Copyright IBM Corp. 2014, 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', 'underscore', 'gemini/app/util/ScreenReaderUtil', 'baglass/core-client/js/core-client/utils/ContentFormatter', 'text!./templates/TimelineSliderContentView.html', 'baglass/core-client/js/core-client/utils/dom-utils', 'baglass/core-client/js/core-client/utils/Utils', '../lib/@ba-ui-toolkit/ba-graphics/dist/icons-js/resize-panel_16'], function (View, $, _, ScreenReaderUtil, ContentFormatter, template, DomUtils, Utils, resizePanelIcon) {
- var TimelineSliderContentView = View.extend({
- templateString: template,
- //should match _endBufferTime in TimeQueue
- _endBufferTime: 200,
- dragValue: null,
- value: null,
- min: 0,
- max: 0,
- scale: 1,
- title: null,
- notifyChangedInterval: 200,
- draggingElement: null,
- events: {},
- init: function init(options) {
- TimelineSliderContentView.inherited('init', this, arguments);
- this.id = options.id;
- this.min = options.min || 0;
- this.max = options.max || 0;
- this.value = options.value;
- this.scale = options.scale || 1;
- this.title = options.title;
- this.dndManager = options.dndManager;
- this.cssClassSelector = options.cssClassSelector;
- this.stringResources = options.services.getSvcSync('.StringResources');
- this.timelineController = options.timelineController;
- // convert to seconds
- this._minimumDuration = this._endBufferTime / 1000;
- this._ScreenReader = new ScreenReaderUtil();
- },
- render: function render() {
- var leftHandleLabel = this.title ? this.stringResources.get('timelineLeftHandle', { name: this.title }) : this.stringResources.get('timelineLeftHandleNoTitle');
- var rightHandleLabel = this.title ? this.stringResources.get('timelineRightHandle', { name: this.title }) : this.stringResources.get('timelineRightHandleNoTitle');
- var sHtml = this.dotTemplate({
- id: this.id,
- leftHandleLabel: leftHandleLabel,
- rightHandleLabel: rightHandleLabel
- });
- this.$el.html(sHtml);
- this.$highlightsEl = this.$el.find('.highlights-container');
- this.$selection = this.$el.find('.slider-selection');
- this.$handles = this.$selection.find('.handle');
- this.$content = this.$selection.find('.content');
- this.$content = this.$el.find('.content');
- this.$title = this.$content.find('.title');
- Utils.setIcon(this.$el.find('.svgHandleIcon'), resizePanelIcon.default.id);
- var isTouch = this._isTouchMode();
- this._toggleDragEvents(!isTouch);
- if (isTouch) {
- this._addHoldEvents();
- } else {
- this._addKeyDownEvents();
- }
- this._addClickEvents();
- this._update();
- this._updateTitle();
- return this;
- },
- setTitle: function setTitle(title) {
- this.title = title;
- this._updateTitle();
- },
- /** Sets the title and middle-shortens it if the title is too long for the container. */
- middleShortenTitle: function middleShortenTitle(title) {
- this.setTitle(title);
- ContentFormatter.middleShortenString(this.$title[0]);
- },
- setScale: function setScale(scale) {
- this.scale = scale;
- this._update();
- },
- setValue: function setValue(value, preventNotify) {
- this.value = value;
- if (this.$content) {
- this._update();
- if (!preventNotify) {
- this._notifyValueChanged();
- }
- }
- },
- getValue: function getValue() {
- return this.value;
- },
- getDragValue: function getDragValue() {
- return this.dragValue;
- },
- setMax: function setMax(max) {
- this.max = max;
- },
- toggleSelected: function toggleSelected(toggle) {
- this.$el.toggleClass('selected', toggle);
- if (this._isTouchMode()) {
- this._toggleDragEvents(this.isSelected());
- }
- },
- isSelected: function isSelected() {
- return this.$el.hasClass('selected');
- },
- move: function move(value) {
- this._move(value[0], value[1] - value[0]);
- },
- /*
- * View events.
- */
- onHold: function onHold(event) {
- this._select(event);
- },
- onClick: function onClick(event) {
- this._select(event);
- },
- /*
- * Helpers.
- */
- _startArrowKeyMove: function _startArrowKeyMove() {
- this.dragValue = this.value;
- this._notifyValueChangeBegin();
- },
- _select: function _select(event) {
- this.toggleSelected(true);
- this.trigger('dragSlider:select', event);
- },
- _move: function _move(start, length, visualOnly) {
- // on playback we move forward by tick duration each time.
- // when play on click is enabled it shows in certain cases.
- // to resolve this display issue we round down to the nearest tick.
- // (We need the value in seconds)
- var tick = this.timelineController.getTickDuration() / 1000;
- var round = function round(value) {
- return Math.round(value / tick) * tick;
- };
- start = round(start);
- length = round(length);
- // Boundary check the values.
- if (start < 0) {
- start = 0;
- }
- if (length < this._minimumDuration) {
- length = this._minimumDuration;
- }
- var properties = {
- left: start * this.scale + 'px',
- width: length * this.scale + 'px'
- };
- this.$selection.css(properties);
- var value = [start, start + length];
- if (!visualOnly) {
- this.value = value;
- }
- var timelineMax = this._roundValueForScreenReader(this.$el.width() / this.scale);
- this.$handles.eq(0).attr('aria-valuenow', this._roundValueForScreenReader(value[0]));
- this.$handles.eq(0).attr('aria-valuemin', 0);
- this.$handles.eq(0).attr('aria-valuemax', this._roundValueForScreenReader(value[1] - this._minimumDuration));
- this.$handles.eq(1).attr('aria-valuenow', this._roundValueForScreenReader(value[1]));
- this.$handles.eq(1).attr('aria-valuemin', this._roundValueForScreenReader(value[0] + this._minimumDuration));
- this.$handles.eq(1).attr('aria-valuemax', timelineMax);
- this.$content.attr('aria-valuenow', this._roundValueForScreenReader((value[0] + value[1]) / 2));
- this.$content.attr('aria-valuemin', 0);
- this.$content.attr('aria-valuemax', timelineMax);
- return value;
- },
- _update: function _update() {
- this.move(this.value);
- },
- _updateTitle: function _updateTitle() {
- var leftHandleLabel = this.title ? this.stringResources.get('timelineLeftHandle', { name: this.title }) : this.stringResources.get('timelineLeftHandleNoTitle');
- var rightHandleLabel = this.title ? this.stringResources.get('timelineRightHandle', { name: this.title }) : this.stringResources.get('timelineRightHandleNoTitle');
- this.$title.text(this.title);
- this.$handles.eq(0).attr('aria-label', leftHandleLabel);
- this.$handles.eq(1).attr('aria-label', rightHandleLabel);
- },
- _notifyValueChangeBegin: function _notifyValueChangeBegin() {
- this.trigger('value:willChange');
- },
- _notifyValueChanged: function _notifyValueChanged(extraOptions) {
- this.trigger('value:changed', _.extend({
- value: this.value,
- min: this.min,
- max: this.max
- }, extraOptions));
- },
- _addHoldEvents: function _addHoldEvents() {
- var handler = this.onHold.bind(this);
- this.$handles.hammer().on('hold', handler);
- this.$content.hammer().on('hold', handler);
- },
- _addClickEvents: function _addClickEvents() {
- var mouseDownHandler = function () {
- this.isDragging = false;
- }.bind(this);
- var clickHandler = function (event) {
- if (!this.isDragging) {
- this.onClick(event);
- }
- }.bind(this);
- this.$handles.on('mousedown', mouseDownHandler);
- this.$content.on('mousedown', mouseDownHandler);
- this.$handles.on('click', clickHandler);
- this.$content.on('click', clickHandler);
- },
- _addKeyDownEvents: function _addKeyDownEvents() {
- this.$handles.on('keydown', this._onKeyPress.bind(this));
- this.$content.on('keydown', this._onKeyPress.bind(this));
- },
- _toggleDragEvents: function _toggleDragEvents(toggle) {
- this._toggleDragEvent(this.$handles.eq(0), toggle, this._leftHandleDragHandler);
- this._toggleDragEvent(this.$handles.eq(1), toggle, this._rightHandleDragHandler);
- this._toggleDragEvent(this.$content, toggle, this._contentDragHandler);
- },
- _toggleDragEvent: function _toggleDragEvent($node, enable, handler) {
- if (enable) {
- $node.hammer().on('dragstart', this._dragHandler.bind(this, handler));
- } else {
- $node.hammer().off('dragstart');
- }
- },
- _dragHandler: function _dragHandler(wrapped, event) {
- this.trigger('dragSlider:dragStarted');
- var extraOptions = {
- payloadData: {
- undoRedoTransactionId: _.uniqueId('dragSlider')
- }
- };
- var config = {
- type: 'timelineSlider',
- data: {
- slider: this
- },
- restrictToXAxis: true,
- avatar: null,
- event: event,
- callerCallbacks: {
- onDragStart: function (event, options) {
- $('body').addClass('overflowHidden');
- this.dragValue = this.value;
- if (wrapped.onDragStart) {
- wrapped.onDragStart.bind(this)(event, options);
- }
- this._notifyValueChangeBegin();
- }.bind(this),
- onMove: function (event, options) {
- if (wrapped.onMove) {
- wrapped.onMove.bind(this)(event, options);
- }
- }.bind(this),
- onDragDone: function (event, options) {
- if (wrapped.onDragDone) {
- wrapped.onDragDone.bind(this)(event, _.extend({}, options, extraOptions));
- }
- if (this.dragValue) {
- this._move(this.dragValue[0], this.dragValue[1] - this.dragValue[0]);
- this.dragValue = null;
- this._notifyValueChanged(extraOptions);
- }
- this.draggingElement = null;
- $('body').removeClass('overflowHidden');
- this._select(event);
- }.bind(this)
- }
- };
- if (wrapped.getConfig) {
- var wrapperConfig = wrapped.getConfig.bind(this)(event);
- _.extend(config, wrapperConfig);
- }
- this.dndManager.startDrag(config);
- },
- _leftHandleDragHandler: {
- onDragStart: function onDragStart() {
- this.draggingElement = 'leftHandle';
- this.isDragging = true;
- },
- onMove: function onMove(event, options) {
- var deltaX = options.dragObject.position.x - options.dragObject.startPosition.x;
- var x = deltaX / this.scale;
- var start = x + this.value[0];
- var length = this.value[1] - this.value[0] - x;
- if (start < 0) {
- length += start;
- } else if (start + this._minimumDuration > this.value[1]) {
- start = this.value[1] - this._minimumDuration;
- }
- this.dragValue = this._move(start, length, true);
- }
- },
- _rightHandleDragHandler: {
- onDragStart: function onDragStart() {
- this.draggingElement = 'rightHandle';
- this.isDragging = true;
- },
- onMove: function onMove(event, options) {
- var deltaX = options.dragObject.position.x - options.dragObject.startPosition.x;
- this.dragValue = this._move(this.value[0], deltaX / this.scale + (this.value[1] - this.value[0]), true);
- }
- },
- _contentDragHandler: {
- getConfig: function getConfig(event) {
- var $avatar = $('<div>').addClass('dragAvatar timelineContent bringToFront selected').hide();
- $('body').append($avatar);
- $avatar.append(this.$selection.clone());
- if (this.cssClassSelector) {
- $avatar.append(this.$el.find('.' + this.cssClassSelector).clone());
- }
- var offset = this.$selection.offset();
- var eventPos = DomUtils.getEventPos(event);
- var avatarYOffset = offset.top - eventPos.pageY;
- var avatarXOffset = offset.left - eventPos.pageX - this.value[0] * this.scale;
- return {
- type: 'dragSliderContent',
- dragLockToAxis: true,
- restrictToXAxis: false,
- restrictToYAxis: false,
- moveXThreshold: 20,
- moveYThreshold: 20,
- data: {
- slider: this,
- avatar: $avatar
- },
- avatar: $avatar[0],
- avatarXOffset: avatarXOffset,
- avatarYOffset: avatarYOffset
- };
- },
- onDragStart: function onDragStart(event, options) {
- this.draggingElement = 'content';
- // show the avatar and hide the real slider
- options.dragObject.data.avatar.show();
- if (this.cssClassSelector) {
- this.$cssClassSelector = this.$el.find('.' + this.cssClassSelector);
- this.$cssClassSelector.hide();
- }
- this.$selection.hide();
- this.isDragging = true;
- },
- onMove: function onMove(event, options) {
- var deltaX = options.dragObject.position.x - options.dragObject.startPosition.x;
- this.dragValue = this._move(deltaX / this.scale + this.value[0], this.value[1] - this.value[0], true);
- },
- onDragDone: function onDragDone(event, options) {
- // restore the slider and hide the avatar
- this.$selection.show();
- if (this.cssClassSelector) {
- this.$cssClassSelector.show();
- }
- options.dragObject.data.avatar.hide();
- this.trigger('dragSlider:isDropped', _.extend({ id: this.id }, options));
- }
- },
- _onKeyPress: function _onKeyPress(evt) {
- var $target = $(evt.currentTarget);
- var isLeftHandle = $target.hasClass('lefthandle');
- var isRightHandle = $target.hasClass('righthandle');
- // Select the selection with white space or return key
- if (evt.keyCode === 13 || evt.keyCode === 32) {
- this._select(evt);
- $target.toggleClass('active', isLeftHandle || isRightHandle);
- $target.focus();
- return;
- }
- var messageOptions = {
- title: this.title
- };
- // Set moveby amount and message for move
- var xMoveByDelta = 0;
- var yMoveByDelta = 0;
- var sMessage = '';
- switch (evt.keyCode) {
- case 9:
- // Tab
- $target.toggleClass('active', false);
- return;
- case 37:
- // Left arrow
- xMoveByDelta = -0.1;
- break;
- case 39:
- // Right arrow
- xMoveByDelta = 0.1;
- break;
- case 38:
- // up arrow
- if (isLeftHandle || isRightHandle) {
- //handles can't be moved up
- evt.stopPropagation();
- evt.preventDefault();
- return;
- }
- yMoveByDelta = -1;
- break;
- case 40:
- //down arrow
- if (isLeftHandle || isRightHandle) {
- //handles can't be moved down
- evt.stopPropagation();
- evt.preventDefault();
- return;
- }
- yMoveByDelta = 1;
- break;
- default:
- return;
- }
- evt.stopPropagation();
- evt.preventDefault();
- $target.toggleClass('active', isLeftHandle || isRightHandle);
- // Start arrow key move
- this._startArrowKeyMove();
- if (isLeftHandle) {
- var start = xMoveByDelta + this.value[0];
- var length = this.value[1] - this.value[0] - xMoveByDelta;
- if (start < 0) {
- length += start;
- } else if (start > this.value[1]) {
- start = this.value[1];
- }
- this.dragValue = this._move(start, length, true);
- } else if (isRightHandle) {
- this.dragValue = this._move(this.value[0], xMoveByDelta + (this.value[1] - this.value[0]), true);
- } else {
- if (xMoveByDelta != 0) {
- this.dragValue = this._move(xMoveByDelta + this.value[0], this.value[1] - this.value[0], true);
- } else {
- var options = {
- id: this.id,
- payloadData: {
- undoRedoTransactionId: _.uniqueId('dragSlider')
- }
- };
- var event = yMoveByDelta > 0 ? 'dragSlider:movingDown' : 'dragSlider:movingUp';
- this.trigger(event, options);
- this.trigger('dragSlider:isDropped', options);
- }
- }
- // End move update
- if (this.dragValue) {
- messageOptions.newStartTime = this._roundValueForScreenReader(this.dragValue[0]);
- messageOptions.newEndTime = this._roundValueForScreenReader(this.dragValue[1]);
- this._move(this.dragValue[0], this.dragValue[1] - this.dragValue[0]);
- this.dragValue = null;
- this._notifyValueChanged();
- }
- if (isLeftHandle) {
- messageOptions.resourceName = 'timelineMoveWidgetStartTime';
- } else if (isRightHandle) {
- messageOptions.resourceName = 'timelineMoveWidgetEndTime';
- } else if (yMoveByDelta < 0) {
- messageOptions.resourceName = 'timelineMoveWidgetUp';
- } else if (yMoveByDelta > 0) {
- messageOptions.resourceName = 'timelineMoveWidgetDown';
- } else {
- messageOptions.resourceName = 'timelineMoveWidget';
- }
- // update the move
- this._update();
- sMessage = this.stringResources.get(messageOptions.resourceName, messageOptions);
- // update screenreader input
- this._ScreenReader.callOut(sMessage);
- },
- _roundValueForScreenReader: function _roundValueForScreenReader(value) {
- return Math.round(value * 100) / 100;
- },
- _isTouchMode: function _isTouchMode() {
- return 'ontouchstart' in document.documentElement;
- }
- });
- return TimelineSliderContentView;
- });
- //# sourceMappingURL=TimelineSliderContentView.js.map
|