123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- 'use strict';
- /**
- * Licensed Materials - Property of IBM
- * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2015, 2020
- * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
- */
- define(['./SceneLayout', '../../navigation/NavigationController', '../../navigation/SceneLoader', '../../navigation/panandzoom/PanAndZoomTransitionController', 'baglass/core-client/js/core-client/utils/Deferred', 'jquery', 'underscore', 'impress'], function (SceneLayout, NavigationController, SceneLoader, TransitionController, Deferred, $, _, impress) {
- var BLACKLISTED_PROPERTIES = ['fitPage'];
- /**
- * Pan and zoom layout. Uses impress to navigate (pan or zoom) between scenes
- */
- var PanAndZoomLayout = SceneLayout.extend({
- // Following line is for testing :(
- _impressFactory: impress,
- // PanAndZoomLayout6 uses CSS to scale it's border so here we only capture the templates
- _dropZoneSelector: '.pagetemplateDropZone, .pagetemplateIndicator',
- _pageNavigationController: null,
- init: function init() {
- PanAndZoomLayout.inherited('init', this, arguments);
- this._trailingOverviewId = '_overview_' + this.model.id;
- // Add onto the sceneLayoutApi
- this.extendApi({
- 'getOverviews': this._getOverviews.bind(this)
- });
- this._overviews = [{
- id: 'start',
- $el: $('#start' + this._trailingOverviewId),
- isOverview: true
- }, {
- id: 'end',
- $el: $('#end' + this._trailingOverviewId),
- isOverview: true
- }];
- this._sceneLoader = new SceneLoader({
- logger: this.logger,
- dashboardApi: this.dashboardApi,
- layoutController: this.layoutController
- });
- this._layoutIsReady = new Deferred();
- this.changePageSize({ value: this.model.pageSize });
- this.model.on('change:pageSize', this._handlePageUpdate, this);
- },
- destroy: function destroy() {
- var _this = this;
- this._sceneLoader.stopBackgroundLoad();
- // we have to clear the modification we made to the scenes without telling them.
- // (in _updateSceneSize)
- (this._scenes || []).forEach(function (scene) {
- var view = scene.getLayoutView();
- if (view) {
- view.$el[0].style.height = null;
- view.$el[0].style.width = null;
- view.$el.find(_this._dropZoneSelector).each(function (index, element) {
- element.style.borderWidth = null;
- });
- }
- });
- clearInterval(this._viewPortSetIntervalId);
- this.$el[0].removeEventListener('impress:stepenter', this._impressStepEnterHandler);
- this.model.off('change:pageSize', this._handlePageUpdate, this);
- PanAndZoomLayout.inherited('destroy', this, arguments);
- },
- _handlePageUpdate: function _handlePageUpdate(options) {
- this.changePageSize(options);
- this.onResize();
- },
- changePageSize: function changePageSize() {
- //to be overwritten
- },
- getProperties: function getProperties() {
- var _this2 = this;
- return PanAndZoomLayout.inherited('getProperties', this, arguments).then(function (properties) {
- properties = properties.filter(function (property) {
- return BLACKLISTED_PROPERTIES.indexOf(property.id) === -1;
- });
- return properties.concat(_this2._getShowOverviewProperties());
- });
- },
- _getShowOverviewProperties: function _getShowOverviewProperties() {
- var _this3 = this;
- var overviewsModel = this.model.get('showOverviews');
- // the overview property name are very generic
- // to prevent clashing with other properties we add a prefix
- var propertyPrefix = 'overview_';
- var updateOverviewModel = function updateOverviewModel(propertyName, propertyValue) {
- var _showOverviews;
- //remove prefix
- propertyName = propertyName.substring(propertyPrefix.length);
- var updateOptions = {
- updateArray: [{
- id: _this3.model.id,
- showOverviews: (_showOverviews = {}, _showOverviews[propertyName] = propertyValue, _showOverviews)
- }]
- };
- _this3.model.updateModel(updateOptions, _this3, { undoRedoTransactionId: _.uniqueId('layoutShowOverview_') });
- };
- return [{
- 'name': propertyPrefix + 'showStart',
- 'sectionName': this.stringResources.get('scenesPropertiesSection'),
- 'type': 'CheckBox',
- 'label': this.stringResources.get('propShowStoryOverviewFirstSlide'),
- 'checked': overviewsModel.showStart,
- 'onChange': updateOverviewModel,
- 'tabName': this.stringResources.get('tabName_general')
- }, {
- 'name': propertyPrefix + 'showEnd',
- 'sectionName': this.stringResources.get('scenesPropertiesSection'),
- 'type': 'CheckBox',
- 'label': this.stringResources.get('propShowStoryOverviewLastSlide'),
- 'checked': overviewsModel.showEnd,
- 'onChange': updateOverviewModel,
- 'tabName': this.stringResources.get('tabName_general')
- }];
- },
- _setupNavigationEvents: function _setupNavigationEvents() {
- this.$el.on('keydown', this._onKeyDown.bind(this));
- this.$el.on('swiperight', this._onPlaybackPrevious.bind(this)).on('swipeleft', this._onPlaybackNext.bind(this)).on('clicktap', this._onOverviewSceneClick.bind(this));
- // This event was introduced to ensure the navigation state recovers in the case where
- // a transition was caused by the hashchange listener inside impress (e.g back browser button).
- this._impressStepEnterHandler = function () {
- // this is because impress doesn't remove its internal hashchange listener
- window.location.hash = '';
- var sceneId = this.$el.find('.step.active')[0].dataset.modelId;
- // Only do work if we are out of sync.
- if (sceneId && this.sceneId !== sceneId) {
- this.layoutController.eventRouter.trigger('scene:jump', { modelId: sceneId });
- }
- }.bind(this);
- this.$el[0].addEventListener('impress:stepenter', this._impressStepEnterHandler);
- },
- _getViewPort: function _getViewPort() {
- var viewport = void 0;
- var currentSceneIndex = this._getSceneIndexById(this.sceneId);
- if (currentSceneIndex < 0) {
- // momentarily enable filter-dock if on overviews while getting the viewport size
- this.layoutController.eventRouter.trigger('filterDock:enable');
- viewport = this.$el[0].getBoundingClientRect();
- this.layoutController.eventRouter.trigger('filterDock:disable');
- } else {
- viewport = this.$el[0].getBoundingClientRect();
- }
- // If the viewport hasn't rendered yet, we will attempt to resize the layout on show.
- if (viewport.height === 0 && viewport.width === 0) {
- this.resizeOnShow();
- }
- return viewport;
- },
- _onResize: function _onResize() {
- var _this4 = this,
- _arguments = arguments;
- return this._layoutIsReady.promise.then(function () {
- var viewport = _this4._getViewPort();
- var currentSceneIndex = _this4._getSceneIndexById(_this4.sceneId);
- _.each(_this4._scenes, function (scene, index) {
- _this4._updateSceneSize(scene, viewport);
- if (currentSceneIndex === index) {
- _this4._impress.goto(scene.$el[0].id, 0);
- }
- });
- var info = _this4._getOverviewLocation(viewport);
- _.each(_this4._overviews, function (item, index) {
- _this4._updateElementData(item.$el, info);
- if ((index + 1) * -1 === currentSceneIndex) {
- _this4._impress.goto(item.$el[0].id, 0);
- }
- });
- _this4.$el.removeClass('scenesHidden');
- PanAndZoomLayout.inherited('_onResize', _this4, _arguments);
- });
- },
- onLayoutReady: function onLayoutReady() {
- var _this5 = this;
- PanAndZoomLayout.inherited('onLayoutReady', this, arguments);
- this._updateEndpoints();
- this._impress = this._impressFactory('impress_' + this.model.id);
- this._impress.init();
- this._didImpressInit = true;
- var scene = void 0;
- if (this.sceneId) {
- // the indices -1 and -2 are used as scene IDs for start overview and end overview
- var index = parseInt(this.sceneId, 10);
- scene = index < 0 ? this._getSceneByIndex(index) : this._getSceneById(this.sceneId);
- } else if (this.isAuthoringMode || !this.model.showOverviews.showStart) {
- // goto the first scene in authoring mode even if overviews are enabled
- scene = this._scenes[0];
- } else {
- scene = this._overviews[0];
- }
- // We don't care about what the sceneId was before. We update it here based on the scene that was retrieved
- this.sceneId = scene.id;
- this._pageNavigationController = new NavigationController({
- sceneLayoutApi: this.getSceneLayoutApi(),
- transitionController: new TransitionController({ impress: this._impress }),
- logger: this.logger,
- sceneLoader: this._sceneLoader
- });
- this._setupNavigationEvents();
- this.currentSceneChanged();
- // hide the filter dock if rendering an overview scene
- if (this._isOverview()) {
- this.layoutController.eventRouter.trigger('filterDock:collapse');
- }
- _.each(this.model.items, function (model) {
- this._updateSceneLabel({ model: model });
- }.bind(this));
- // +1 because the overview is 0 to impress but -1 to us
- var sceneIndex = this._getCurrentSceneIndex();
- this._impress.goto(sceneIndex + 1, 0);
- return this.onJumpScene({
- modelId: this.sceneId,
- play: false
- }).then(function () {
- _this5._onResize();
- return _this5._layoutIsReady.resolve();
- });
- },
- /**
- * @override
- * @see SceneLayout._getSceneById
- */
- _getSceneById: function _getSceneById(sceneId) {
- if (sceneId === 'start') {
- return this._overviews[0];
- } else if (sceneId === 'end') {
- return this._overviews[1];
- }
- return PanAndZoomLayout.inherited('_getSceneById', this, arguments);
- },
- /**
- * @override
- * @see SceneLayout._getSceneByIndex
- */
- _getSceneByIndex: function _getSceneByIndex(index) {
- if (index === -1) {
- return this._overviews[0];
- } else if (index === -2) {
- return this._overviews[1];
- }
- return PanAndZoomLayout.inherited('_getSceneByIndex', this, arguments);
- },
- /**
- * @override
- * @see SceneLayout._getSceneIndexById
- */
- _getSceneIndexById: function _getSceneIndexById(sceneId) {
- var sceneIndex = PanAndZoomLayout.inherited('_getSceneIndexById', this, arguments);
- if (sceneIndex === -1) {
- _.each(this._overviews, function (overview) {
- if (overview.id === sceneId && overview.id === 'end') {
- sceneIndex = -2;
- }
- });
- }
- return sceneIndex;
- },
- /**
- * @override
- * @see SceneLayout._getNextScene
- */
- _getNextScene: function _getNextScene(scene) {
- var sceneIndex = this._getCurrentSceneIndex();
- if (scene && scene.id !== this.sceneId) {
- sceneIndex = this._getSceneIndex(scene);
- }
- if (sceneIndex >= -2 && sceneIndex < this._scenes.length - 1) {
- return this._getSceneByIndex(sceneIndex + 1);
- } else if (sceneIndex === this._scenes.length - 1) {
- return this._getSceneByIndex(-2);
- }
- return null;
- },
- /**
- * @override
- * @see SceneLayout._getPreviousScene
- */
- _getPreviousScene: function _getPreviousScene(scene) {
- var sceneIndex = this._getCurrentSceneIndex();
- if (scene && scene.id !== this.sceneId) {
- sceneIndex = this._getSceneIndex(scene);
- }
- if (sceneIndex >= 0) {
- return this._getSceneByIndex(sceneIndex - 1);
- } else if (sceneIndex === -2) {
- return this._getSceneByIndex(this._scenes.length - 1);
- }
- return null;
- },
- onKeyDown: function onKeyDown(event) {
- var keyCode = event.keyCode || event.charCode;
- switch (keyCode) {
- case 13: // enter
- case 32:
- // space
- this._jumpToScene(event);
- break;
- default:
- break;
- }
- },
- /**
- * @returns {Promise}
- */
- didRemovePage: function didRemovePage() {
- var _this6 = this;
- return PanAndZoomLayout.inherited('didRemovePage', this, arguments).then(function () {
- _this6._updateEndpoints();
- });
- },
- _getOverviews: function _getOverviews() {
- return this._overviews;
- },
- _isOverview: function _isOverview() {
- return this.sceneId === 'start' || this.sceneId === 'end';
- },
- /**
- * @override
- */
- _addScene: function _addScene(model) {
- PanAndZoomLayout.inherited('_addScene', this, arguments);
- var scene = this._getSceneById(model.id);
- this._updateSceneSize(scene, this._getViewPort());
- // add index to scene in overview
- var sceneIndex = this._getSceneIndex(model);
- var sceneOrder = scene.$el.find('.sceneOrder');
- sceneOrder.attr('data-index', sceneIndex + 1);
- },
- /**
- * @override
- */
- currentSceneChanged: function currentSceneChanged() {
- PanAndZoomLayout.inherited('currentSceneChanged', this, arguments);
- this.$el.find('.swapSelected').removeClass('swapSelected');
- this.$el.toggleClass('overview', this._isOverview());
- },
- _onOverviewSceneClick: function _onOverviewSceneClick(event) {
- this._jumpToScene(event);
- },
- _jumpToScene: function _jumpToScene(event) {
- var $scene = $(event.target).closest('.overview .step.pageTabContent');
- if ($scene.length === 1) {
- var sceneId = $scene[0].dataset.modelId;
- this.layoutController.eventRouter.trigger('scene:jump', { modelId: sceneId });
- event.stopPropagation();
- }
- },
- /**
- * Updates the DOM if an existing scene and makes impress notices it's changed.
- *
- * @param $el element to update
- * @param data data to use to update $el. should contain the 3 needed data items
- * @param insertBefore id of the next element in the dom.
- */
- _updateElementData: function _updateElementData($el, data) {
- //TODO add to impress
- var impress_updateStep = function (id) {
- // impress version would just call: initStep(node);
- var node = document.getElementById(id);
- var nextNode = node.nextElementSibling;
- var insertBefore = nextNode ? nextNode.id : undefined;
- this._impress.removeStep(id);
- this._impress.addStep('#' + id, insertBefore);
- }.bind(this);
- $el.attr({
- 'data-scale': data.scale,
- 'data-x': data.x,
- 'data-y': data.y
- });
- if (this._didImpressInit) {
- // all steps have an id, impress ensures that.
- impress_updateStep($el.attr('id'));
- }
- },
- _updateSceneSize: function _updateSceneSize(scene, viewport) {
- var view = scene.getLayoutView();
- var overviewBlockerCell = scene.$el.find('.overviewBlockerCell');
- if (view) {
- var info = this._getSceneLocation(view.model.data.positionIndex, viewport);
- this._updateElementData(scene.$el, info);
- if (info.stepHeight && info.stepWidth) {
- var sceneCss = {
- height: info.stepHeight + 'px',
- width: info.stepWidth + 'px'
- };
- var viewCss = {
- height: info.sceneHeight + 'px',
- width: info.sceneWidth + 'px'
- };
- scene.$el.css(sceneCss);
- view.$el.css(viewCss);
- overviewBlockerCell.css(viewCss);
- } else {
- var css = {
- height: info.height + 'px',
- width: info.width + 'px'
- };
- scene.$el.css(css);
- view.$el.css(css);
- overviewBlockerCell.css(css);
- }
- }
- },
- _updateSceneLabel: function _updateSceneLabel(payload) {
- this.$el.find('#' + payload.model.id + '_sceneLabel').text(payload.model.get('title') || '');
- },
- _updateEndpoints: function _updateEndpoints() {
- this.$el.find('.sequenceEndpoint').removeClass('sequenceEndpoint sequenceEnd sequenceStart');
- var minScenePosition = 0;
- var maxScenePosition = this.model.items.length - 1;
- var firstSceneItem = this.model.items.find(function (item) {
- return item.data.positionIndex === minScenePosition;
- });
- var firstScene = this._getSceneById(firstSceneItem.id);
- firstScene.$el.addClass('sequenceEndpoint sequenceStart');
- var lastSceneItem = this.model.items.find(function (item) {
- return item.data.positionIndex === maxScenePosition;
- });
- var lastScene = this._getSceneById(lastSceneItem.id);
- lastScene.$el.addClass('sequenceEndpoint sequenceEnd');
- },
- /**
- * Called to get the correct scene scale value from this.sceneLocations
- * Note: this function takes care of wrapping sceneIndex based on how many scenes are in this.sceneLocations
- *
- * @param {number} sceneIndex the index of the scene we want to find the location of
- * @returns {number} the scale of the scene corresponding to its value in this.sceneLocations
- *
- */
- getSceneScale: function getSceneScale(sceneIndex) {
- var numSceneLocations = this.sceneLocations.length;
- return this.sceneLocations[sceneIndex % numSceneLocations].scale;
- },
- // temporary home for the next 2 methods.
- // they are common code used by the template implementation -> derived classes (PnZ 1-6)
- //
- // These method don't really belong here,
- // we need an intermediate base for them, or move to composition and have the base class contain them
- _computeViewportScale: function _computeViewportScale(viewport, sceneHeight, sceneWidth) {
- var viewportUsage = 0.95;
- // viewport should subtrct handle height (svg: 24 + padding: 5), the height will split by top and bottom so times 2
- var doubleStoryHandleHeight = 58;
- var scale = 1;
- if (viewport) {
- var vScale = (viewport.height - doubleStoryHandleHeight) / sceneHeight * viewportUsage;
- var hScale = viewport.width / sceneWidth * viewportUsage;
- scale = Math.min(vScale, hScale);
- }
- return scale;
- },
- _computeTemplateScale: function _computeTemplateScale(width, height, padding, factor) {
- return Math.min((height * factor + padding) / height, (width * factor + padding) / width);
- }
- });
- return PanAndZoomLayout;
- });
- //# sourceMappingURL=PanAndZoomLayout.js.map
|