modules/ui/intro/navigation.js (432 lines of code) (raw):

import { dispatch as d3_dispatch } from 'd3-dispatch'; import { event as d3_event, select as d3_select } from 'd3-selection'; import { t } from '../../util/locale'; import { modeBrowse } from '../../modes/browse'; import { modeSelect } from '../../modes/select'; import { utilRebind } from '../../util/rebind'; import { icon, pointBox, transitionTime } from './helper'; export function uiIntroNavigation(context, reveal) { var dispatch = d3_dispatch('done'); var timeouts = []; var hallId = 'n2061'; var townHall = [-85.63591, 41.94285]; var springStreetId = 'w397'; var springStreetEndId = 'n1834'; var springStreet = [-85.63582, 41.94255]; var onewayField = context.presets().field('oneway'); var maxspeedField = context.presets().field('maxspeed'); var chapter = { title: 'intro.navigation.title' }; function timeout(f, t) { timeouts.push(window.setTimeout(f, t)); } function eventCancel() { d3_event.stopPropagation(); d3_event.preventDefault(); } function isTownHallSelected() { var ids = context.selectedIDs(); return ids.length === 1 && ids[0] === hallId; } function dragMap() { context.enter(modeBrowse(context)); context.history().reset('initial'); var msec = transitionTime(townHall, context.map().center()); if (msec) { reveal(null, null, { duration: 0 }); } context.map().centerZoomEase(townHall, 19, msec); timeout(function() { var centerStart = context.map().center(); reveal('#surface', t('intro.navigation.drag')); context.map().on('drawn.intro', function() { reveal('#surface', t('intro.navigation.drag'), { duration: 0 }); }); context.map().on('move.intro', function() { var centerNow = context.map().center(); if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) { context.map().on('move.intro', null); timeout(function() { continueTo(zoomMap); }, 3000); } }); }, msec + 100); function continueTo(nextStep) { context.map().on('move.intro drawn.intro', null); nextStep(); } } function zoomMap() { var zoomStart = context.map().zoom(); reveal('#surface', t('intro.navigation.zoom', { plus: icon('#iD-icon-plus', 'pre-text'), minus: icon('#iD-icon-minus', 'pre-text') }) ); context.map().on('drawn.intro', function() { reveal('#surface', t('intro.navigation.zoom', { plus: icon('#iD-icon-plus', 'pre-text'), minus: icon('#iD-icon-minus', 'pre-text') }), { duration: 0 } ); }); context.map().on('move.intro', function() { if (context.map().zoom() !== zoomStart) { context.map().on('move.intro', null); timeout(function() { continueTo(features); }, 3000); } }); function continueTo(nextStep) { context.map().on('move.intro drawn.intro', null); nextStep(); } } function features() { var onClick = function() { continueTo(pointsLinesAreas); }; reveal('#surface', t('intro.navigation.features'), { buttonText: t('intro.ok'), buttonCallback: onClick } ); context.map().on('drawn.intro', function() { reveal('#surface', t('intro.navigation.features'), { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } ); }); function continueTo(nextStep) { context.map().on('drawn.intro', null); nextStep(); } } function pointsLinesAreas() { var onClick = function() { continueTo(nodesWays); }; reveal('#surface', t('intro.navigation.points_lines_areas'), { buttonText: t('intro.ok'), buttonCallback: onClick } ); context.map().on('drawn.intro', function() { reveal('#surface', t('intro.navigation.points_lines_areas'), { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } ); }); function continueTo(nextStep) { context.map().on('drawn.intro', null); nextStep(); } } function nodesWays() { var onClick = function() { continueTo(clickTownHall); }; reveal('#surface', t('intro.navigation.nodes_ways'), { buttonText: t('intro.ok'), buttonCallback: onClick } ); context.map().on('drawn.intro', function() { reveal('#surface', t('intro.navigation.nodes_ways'), { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } ); }); function continueTo(nextStep) { context.map().on('drawn.intro', null); nextStep(); } } function clickTownHall() { context.enter(modeBrowse(context)); context.history().reset('initial'); var entity = context.hasEntity(hallId); if (!entity) return; reveal(null, null, { duration: 0 }); context.map().centerZoomEase(entity.loc, 19, 500); timeout(function() { var entity = context.hasEntity(hallId); if (!entity) return; var box = pointBox(entity.loc, context); reveal(box, t('intro.navigation.click_townhall')); context.map().on('move.intro drawn.intro', function() { var entity = context.hasEntity(hallId); if (!entity) return; var box = pointBox(entity.loc, context); reveal(box, t('intro.navigation.click_townhall'), { duration: 0 }); }); context.on('enter.intro', function() { if (isTownHallSelected()) continueTo(selectedTownHall); }); }, 550); // after centerZoomEase context.history().on('change.intro', function() { if (!context.hasEntity(hallId)) { continueTo(clickTownHall); } }); function continueTo(nextStep) { context.on('enter.intro', null); context.map().on('move.intro drawn.intro', null); context.history().on('change.intro', null); nextStep(); } } function selectedTownHall() { if (!isTownHallSelected()) return clickTownHall(); var entity = context.hasEntity(hallId); if (!entity) return clickTownHall(); var box = pointBox(entity.loc, context); var onClick = function() { continueTo(editorTownHall); }; reveal(box, t('intro.navigation.selected_townhall'), { buttonText: t('intro.ok'), buttonCallback: onClick } ); context.map().on('move.intro drawn.intro', function() { var entity = context.hasEntity(hallId); if (!entity) return; var box = pointBox(entity.loc, context); reveal(box, t('intro.navigation.selected_townhall'), { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } ); }); context.history().on('change.intro', function() { if (!context.hasEntity(hallId)) { continueTo(clickTownHall); } }); function continueTo(nextStep) { context.map().on('move.intro drawn.intro', null); context.history().on('change.intro', null); nextStep(); } } function editorTownHall() { if (!isTownHallSelected()) return clickTownHall(); // disallow scrolling d3_select('.inspector-wrap').on('wheel.intro', eventCancel); var onClick = function() { continueTo(presetTownHall); }; reveal('.entity-editor-pane', t('intro.navigation.editor_townhall'), { buttonText: t('intro.ok'), buttonCallback: onClick } ); context.on('exit.intro', function() { continueTo(clickTownHall); }); context.history().on('change.intro', function() { if (!context.hasEntity(hallId)) { continueTo(clickTownHall); } }); function continueTo(nextStep) { context.on('exit.intro', null); context.history().on('change.intro', null); d3_select('.inspector-wrap').on('wheel.intro', null); nextStep(); } } function presetTownHall() { if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it.. d3_select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling d3_select('.inspector-wrap').on('wheel.intro', eventCancel); // preset match, in case the user happened to change it. var entity = context.entity(context.selectedIDs()[0]); var preset = context.presets().match(entity, context.graph()); var onClick = function() { continueTo(fieldsTownHall); }; context.on('exit.intro', function() { continueTo(clickTownHall); }); context.history().on('change.intro', function() { if (!context.hasEntity(hallId)) { continueTo(clickTownHall); } }); reveal('.inspector-body .preset-list-item.inspector-inner', t('intro.navigation.preset_townhall', { preset: preset.name() }), { buttonText: t('intro.ok'), buttonCallback: onClick } ); function continueTo(nextStep) { context.on('exit.intro', null); context.history().on('change.intro', null); d3_select('.inspector-wrap').on('wheel.intro', null); nextStep(); } } function fieldsTownHall() { if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it.. d3_select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling d3_select('.inspector-wrap').on('wheel.intro', eventCancel); var onClick = function() { continueTo(closeTownHall); }; reveal('.inspector-body .preset-editor', t('intro.navigation.fields_townhall'), { buttonText: t('intro.ok'), buttonCallback: onClick } ); context.on('exit.intro', function() { continueTo(clickTownHall); }); context.history().on('change.intro', function() { if (!context.hasEntity(hallId)) { continueTo(clickTownHall); } }); function continueTo(nextStep) { context.on('exit.intro', null); context.history().on('change.intro', null); d3_select('.inspector-wrap').on('wheel.intro', null); nextStep(); } } function closeTownHall() { if (!isTownHallSelected()) return clickTownHall(); var selector = '.entity-editor-pane button.preset-close svg use'; var href = d3_select(selector).attr('href') || '#iD-icon-close'; reveal('.entity-editor-pane', t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }) ); context.on('exit.intro', function() { continueTo(searchStreet); }); context.history().on('change.intro', function() { // update the close icon in the tooltip if the user edits something. var selector = '.entity-editor-pane button.preset-close svg use'; var href = d3_select(selector).attr('href') || '#iD-icon-close'; reveal('.entity-editor-pane', t('intro.navigation.close_townhall', { button: icon(href, 'pre-text') }), { duration: 0 } ); }); function continueTo(nextStep) { context.on('exit.intro', null); context.history().on('change.intro', null); nextStep(); } } function searchStreet() { context.enter(modeBrowse(context)); context.history().reset('initial'); // ensure spring street exists var msec = transitionTime(springStreet, context.map().center()); if (msec) { reveal(null, null, { duration: 0 }); } context.map().centerZoomEase(springStreet, 19, msec); // ..and user can see it timeout(function() { reveal('.search-header input', t('intro.navigation.search_street', { name: t('intro.graph.name.spring-street') }) ); d3_select('.search-header input') .on('keyup.intro', checkSearchResult); }, msec + 100); } function checkSearchResult() { var first = d3_select('.feature-list-item:nth-child(0n+2)'); // skip "No Results" item var firstName = first.select('.entity-name'); var name = t('intro.graph.name.spring-street'); if (!firstName.empty() && firstName.text() === name) { reveal(first.node(), t('intro.navigation.choose_street', { name: name }), { duration: 300 } ); context.on('exit.intro', function() { continueTo(selectedStreet); }); d3_select('.search-header input') .on('keydown.intro', eventCancel, true) .on('keyup.intro', null); } function continueTo(nextStep) { context.on('exit.intro', null); d3_select('.search-header input') .on('keydown.intro', null) .on('keyup.intro', null); nextStep(); } } function selectedStreet() { if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) { return searchStreet(); } var onClick = function() { continueTo(editorStreet); }; var entity = context.entity(springStreetEndId); var box = pointBox(entity.loc, context); box.height = 500; reveal(box, t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }), { duration: 600, buttonText: t('intro.ok'), buttonCallback: onClick } ); timeout(function() { context.map().on('move.intro drawn.intro', function() { var entity = context.hasEntity(springStreetEndId); if (!entity) return; var box = pointBox(entity.loc, context); box.height = 500; reveal(box, t('intro.navigation.selected_street', { name: t('intro.graph.name.spring-street') }), { duration: 0, buttonText: t('intro.ok'), buttonCallback: onClick } ); }); }, 600); // after reveal. context.on('enter.intro', function(mode) { if (!context.hasEntity(springStreetId)) { return continueTo(searchStreet); } var ids = context.selectedIDs(); if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) { // keep Spring Street selected.. context.enter(modeSelect(context, [springStreetId])); } }); context.history().on('change.intro', function() { if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) { timeout(function() { continueTo(searchStreet); }, 300); // after any transition (e.g. if user deleted intersection) } }); function continueTo(nextStep) { context.map().on('move.intro drawn.intro', null); context.on('enter.intro', null); context.history().on('change.intro', null); nextStep(); } } function editorStreet() { var selector = '.entity-editor-pane button.preset-close svg use'; var href = d3_select(selector).attr('href') || '#iD-icon-close'; reveal('.entity-editor-pane', t('intro.navigation.editor_street', { button: icon(href, 'pre-text'), field1: onewayField.label(), field2: maxspeedField.label() }) ); context.on('exit.intro', function() { continueTo(play); }); context.history().on('change.intro', function() { // update the close icon in the tooltip if the user edits something. var selector = '.entity-editor-pane button.preset-close svg use'; var href = d3_select(selector).attr('href') || '#iD-icon-close'; reveal('.entity-editor-pane', t('intro.navigation.editor_street', { button: icon(href, 'pre-text'), field1: onewayField.label().toLowerCase(), field2: maxspeedField.label().toLowerCase() }), { duration: 0 } ); }); function continueTo(nextStep) { context.on('exit.intro', null); context.history().on('change.intro', null); nextStep(); } } function play() { dispatch.call('done'); reveal('#id-container', t('intro.navigation.play', { next: t('intro.points.title') }), { tooltipBox: '.intro-nav-wrap .chapter-point', buttonText: t('intro.ok'), buttonCallback: function() { reveal('#id-container'); } } ); } chapter.enter = function() { dragMap(); }; chapter.exit = function() { timeouts.forEach(window.clearTimeout); context.on('enter.intro exit.intro', null); context.map().on('move.intro drawn.intro', null); context.history().on('change.intro', null); d3_select('.inspector-wrap').on('wheel.intro', null); d3_select('.search-header input').on('keydown.intro keyup.intro', null); }; chapter.restart = function() { chapter.exit(); chapter.enter(); }; return utilRebind(chapter, dispatch, 'on'); }