UNPKG

terriajs

Version:

Geospatial data visualization platform.

147 lines (130 loc) 5.51 kB
'use strict'; import React from 'react'; import createReactClass from 'create-react-class'; import PropTypes from 'prop-types'; import ObserveModelMixin from '../ObserveModelMixin'; import defined from 'terriajs-cesium/Source/Core/defined'; import HelpScreenWindow from './HelpScreenWindow.jsx'; import ObscureOverlay from './ObscureOverlay.jsx'; const HelpOverlay = createReactClass({ displayName: 'HelpOverlay', mixins: [ObserveModelMixin], propTypes: { helpViewState: PropTypes.object.isRequired, viewState: PropTypes.object.isRequired }, getInitialState() { return { screens: undefined, index: undefined, currentRectangle: undefined, previousRectangle: undefined }; }, cancel() { if (defined(this.setIntervalId)) { clearInterval(this.setIntervalId); } this.setState({ screens: undefined, index: undefined, currentRectangle: undefined, previousRectangle: undefined }); this.props.helpViewState.currentScreen = undefined; }, help(screens, i) { if (i === 0) { // If this is the first help screen in a sequence, locate the highlighted element and track the rectangle // to make sure the overlay and help screen move with the element. const that = this; this.setIntervalId = setInterval(function() { if (!defined(that.state.screens)) { return; } if (that.props.helpViewState.cancel) { // Has been cancelled from somewhere else. Abort! that.cancel(); } const i = that.state.index; const currentScreen = that.state && that.state.screens && that.state.screens[i]; if (currentScreen && typeof currentScreen.preDisplayHook === 'function') { currentScreen.preDisplayHook(that.props.viewState); } updateCurrentRectangle(that, currentScreen); if (!that.props.helpViewState.advance && defined(that.state) && defined(that.state.previousRectangle) && that.state.previousRectangle === that.state.currentRectangle) { return; } if (defined(that.state) && defined(that.state.currentRectangle)) { currentScreen.rectangle = that.state.currentRectangle; currentScreen.currentScreenNumber = i+1; currentScreen.totalNumberOfScreens = that.state.screens.length; currentScreen.onNext = function() { if (typeof currentScreen.postDisplayHook === 'function') { currentScreen.postDisplayHook(that.props.viewState); } if ((i+1) >= that.state.screens.length) { that.cancel(); } else { that.help(that.state.screens, i+1); } }; that.props.helpViewState.currentScreen = currentScreen; // Processed current rectangle, set as previous. that.setState({previousRectangle: that.state.currentRectangle}); } if (that.props.helpViewState.advance) { // Has been manually advanced from somewhere else. Next screen! that.props.helpViewState.advance = false; currentScreen.onNext(); } }, 10); } this.props.helpViewState.cancel = false; this.setState({ screens: screens, index: i, currentRectangle: undefined, previousRectangle: undefined }); }, executeSequence() { if (defined(this.props.helpViewState.currentSequence)) { if (defined(this.setIntervalId)) { clearInterval(this.setIntervalId); } this.help(this.props.helpViewState.currentSequence.screens, 0); // To prevent executeSequence from triggering again before we start a new sequence. this.props.helpViewState.currentSequence = undefined; } }, componentDidMount() { this.executeSequence(); }, componentDidUpdate() { this.executeSequence(); }, render() { return ( <div aria-hidden={ !this.props.helpViewState.currentSequence }> <ObscureOverlay helpViewState={this.props.helpViewState}/> <HelpScreenWindow helpViewState={this.props.helpViewState}/> </div> ); }, }); /** * Reset currentRectangle to the bounding rectangle of the highlighted element. * @private */ function updateCurrentRectangle(component, currentScreen) { if (!defined(currentScreen)) { return; } const highlightedElement = document.getElementsByClassName(currentScreen.highlightedComponentId); if (defined(highlightedElement[0])) { const screenRect = highlightedElement[0].getBoundingClientRect(); component.setState({currentRectangle: screenRect}); } } export default HelpOverlay;