'use strict'; /** * Licensed Materials - Property of IBM * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2017, 2018 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ define(['jquery', 'baglass/core-client/js/core-client/ui/core/View', './TimelineRulerView', './TimelineTimeIndicatorView', '../NoScaleManager', 'text!./templates/PlayerViewProgressBar.html', 'underscore'], function ($, View, TimelineRulerView, TimelineTimeIndicatorView, NoScaleManager, ProgressBarTemplate, _) { var PlayerViewProgressBar = View.extend({ templateString: ProgressBarTemplate, events: { 'primaryaction div.marker': 'onMarkerClick', 'primaryaction': 'onProgressBarClick' }, init: function init(options) { PlayerViewProgressBar.inherited('init', this, arguments); this.controller = options.controller; this.timelineController = options.timelineController; this.glassContext = options.glassContext; this.services = options.services; this.stringResources = this.services.getSvcSync('.StringResources'); this.noScaleManager = new NoScaleManager(); this._refreshTimer = null; /* * This Event Listener helps with when the user changes the length of a scene * in the timeline view. Changing the length triggers a resize event which causes * the progress bar to resize down to 5px (the size of the element with the slash) * so when we close the timeline and the progress bar comes back we need to * recalculate size for the progress bar. */ this._progressBarTransition = function (event) { if (event.target === this.$el[0] && event.propertyName.indexOf('flex-grow') > -1) { this._recalculateProgressBar(); } }.bind(this); this.$el[0].addEventListener('transitionend', this._progressBarTransition); /* * Grab the navbar home button as it will be visible in all perspectives all the time. * We need it because it gets animated when switching between authoring/consumption modes or * when a browser window is resized to collapse the navbar. */ var homeBtn = this.glassContext.appController.findPlugin('com.ibm.bi.glass.common.home'); if (homeBtn && homeBtn.$el && homeBtn.$el.length === 1) { this._navbarItem = homeBtn.$el[0]; this._navbarTransitionCheck = function (event) { if (event.propertyName === 'width') { this._recalculateProgressBar(); } }.bind(this); this._navbarItem.addEventListener('transitionend', this._navbarTransitionCheck); } /* * We ALSO listen for window resize to recalculate the progress bar size */ this._resizeHandler = this._recalculateProgressBar.bind(this); $(window).on('resize', this._resizeHandler); this.timelineController.eventRouter.on('navigation:complete', this.refreshMarkers.bind(this)); this.markers = []; }, /** * Renders the ProgressBar. * * @returns */ render: function render() { var sHtml = this.dotTemplate({}); this.$el.html(sHtml); this._scaleToFit(); this.timeRulerView = new TimelineRulerView({ el: this.$el.find('.progressBarControl'), controller: this.timelineController, scaleManager: this.noScaleManager, useDiv: true }); this.timeRulerView.render(); this.timeIndicatorView = new TimelineTimeIndicatorView({ el: this.$el.find('.progressBarPosition'), controller: this.timelineController, scaleManager: this.noScaleManager, indicatorOnly: true, services: this.services, progressBarCallback: this._completionBarUpdate.bind(this) }); this.timeIndicatorView.render(); this._completionBarUpdate(); }, remove: function remove() { clearTimeout(this._refreshTimer); // Adding this removeEventListener line first to make sure that this.$el is still a valid object this.$el[0].removeEventListener('transitionend', this._progressBarTransition); this._removeMarkers(); PlayerViewProgressBar.inherited('remove', this, arguments); $(window).off('resize', this._resizeHandler); if (this._navBarItem) { this._navbarItem.removeEventListener('transitionend', this._navbarTransitionCheck); } if (this.timeIndicatorView) { this.timeIndicatorView.remove(); this.timeIndicatorView = null; } if (this.timeRulerView) { this.timeRulerView.remove(); this.timeRulerView = null; } }, refreshMarkers: function refreshMarkers() { if (this.timelineController.isNavigateMarkers() && !this.controller.isOverview()) { if (this.markers.length === 0) { this._renderMarkers(); } else { var updatedMarkers = this.timelineController.getMarkers(); var existingMarker; _.each(updatedMarkers, function (timer, index) { existingMarker = this.markers[index]; if (existingMarker) { // re-use existing pause points to avoid creating new elements this._updateMarkerTimer(existingMarker, timer); } else { this._renderMarker(timer); } }.bind(this)); // remove any unused pause points this._removeMarkers(updatedMarkers.length); } } else { this._removeMarkers(); } }, refresh: function refresh() { if (this.timeRulerView.$el.is(':visible')) { this._scaleToFit(); this.refreshMarkers(); this.timeRulerView.refresh(); this.timeIndicatorView.refresh(); } }, onMarkerClick: function onMarkerClick(event) { var marker = this._getMarker(event.currentTarget); if (marker) { this.timelineController.setCurrentTime(marker.timer); this.timeIndicatorView.setFocus(); } }, onProgressBarClick: function onProgressBarClick() { this.timeIndicatorView.setFocus(); }, _removeMarkers: function _removeMarkers(startIndex) { if (startIndex) { for (var i = startIndex; i < this.markers.length; i++) { this.markers[i].$el.remove(); this.markers[i] = null; } this.markers = _.compact(this.markers); } else if (this.markers.length > 0) { this.$el.find('.marker').remove(); this.markers = []; } }, _renderMarkers: function _renderMarkers() { var markers = this.timelineController.getMarkers(); _.each(markers, this._renderMarker.bind(this)); }, _renderMarker: function _renderMarker(timer) { var $marker = $("
"); $marker.attr('aria-label', this.stringResources.get('navigationMarker')); var marker = { $el: $marker, timer: timer }; this.$el.find('.markersContainer').append($marker); this.markers.push(marker); this._positionMarker(marker); return $marker; }, _updateMarkerTimer: function _updateMarkerTimer(marker, newTimer) { marker.timer = newTimer; this._positionMarker(marker); }, _positionMarker: function _positionMarker(marker) { var percent = marker.timer / this.timelineController.getDuration() * 100; var leftVal = percent + '%'; var halfIconWidth = marker.$el.outerWidth() / 2; marker.$el.css('left', 'calc(' + leftVal + ' - ' + halfIconWidth + 'px)'); }, _getMarker: function _getMarker(el) { var marker = _.find(this.markers, function (marker) { return marker.$el.is(el); }); return marker; }, _recalculateProgressBar: function _recalculateProgressBar() { if (this.timeRulerView && this.timeIndicatorView) { /* * !! WARNING!! setTimeout * There are two reasons for this setTimeout. * 1) When switching between authoring and consumption modes the width of the timeline player change * because the navbar shrinks/expands. When it changes it is animated so we need to wait longer than 200ms. * 200ms comes from the toolbars.css file in the glass-foundations component under the '.navbar button' style. * 2) We need to wait for a length of time when transition from the timeline view to film strip view. * The animation here takes a while and through trial and error 1000ms (1 second) worked consistently. * This is also for switching to fullscreen mode and also effects when switching from it. */ clearTimeout(this._refreshTimer); this._refreshTimer = setTimeout(function () { this.refresh(); }.bind(this), 1000); } }, _completionBarUpdate: function _completionBarUpdate(percent) { if (this.timeIndicatorView) { if (!percent) { percent = 0; } this.$el.find('.completedBar').css('width', percent + '%'); } }, _scaleToFit: function _scaleToFit() { var duration = this.timelineController.getDuration(); this.noScaleManager.updateDuration(duration, this.$el.outerWidth(false)); this.noScaleManager.scaleToFit(); } }); return PlayerViewProgressBar; }); //# sourceMappingURL=PlayerViewProgressBar.js.map