modules/ui/intro/welcome.js (216 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 { utilRebind } from '../../util/rebind'; export function uiIntroWelcome(context, reveal) { var dispatch = d3_dispatch('done'); var listener = clickListener(); var chapter = { title: 'intro.welcome.title' }; function welcome() { context.map().centerZoom([-85.63591, 41.94285], 19); reveal('.intro-nav-wrap .chapter-welcome', t('intro.welcome.welcome'), { buttonText: t('intro.ok'), buttonCallback: practice } ); } function practice() { reveal('.intro-nav-wrap .chapter-welcome', t('intro.welcome.practice'), { buttonText: t('intro.ok'), buttonCallback: words } ); } function words() { reveal('.intro-nav-wrap .chapter-welcome', t('intro.welcome.words'), { buttonText: t('intro.ok'), buttonCallback: mouse } ); } function mouse() { reveal('.intro-nav-wrap .chapter-welcome', t('intro.welcome.mouse'), { buttonText: t('intro.ok'), buttonCallback: leftClick } ); } function leftClick() { var counter = 0; var times = 5; var tooltip = reveal('.intro-nav-wrap .chapter-welcome', t('intro.welcome.leftclick', { num: times }), { tooltipClass: 'intro-mouse' } ); tooltip.selectAll('.tooltip-inner') .insert('svg', 'span') .attr('class', 'tooltip-illustration') .append('use') .attr('xlink:href', '#iD-walkthrough-mouse'); tooltip .append('div') .attr('class', 'counter'); tooltip.call(listener); listener.on('click', function(which) { if (which === 'left') { d3_select('.curtain-tooltip.intro-mouse .counter') .text(String(++counter)); if (counter === times) { window.setTimeout(function() { continueTo(rightClick); }, 1000); } } }); function continueTo(nextStep) { listener.on('click', null); tooltip.call(listener.off); tooltip.select('.counter').remove(); nextStep(); } } function rightClick() { var counter = 0; var times = 5; var tooltip = reveal('.intro-nav-wrap .chapter-welcome', t('intro.welcome.rightclick', { num: times }), { tooltipClass: 'intro-mouse' } ); tooltip.selectAll('.tooltip-inner') .insert('svg', 'span') .attr('class', 'tooltip-illustration') .append('use') .attr('xlink:href', '#iD-walkthrough-mouse'); tooltip .append('div') .attr('class', 'counter'); tooltip.call(listener); listener.on('click', function(which) { if (which === 'right') { d3_select('.curtain-tooltip.intro-mouse .counter') .text(String(++counter)); if (counter === times) { window.setTimeout(function() { continueTo(chapters); }, 1000); } } }); function continueTo(nextStep) { listener.on('click', null); tooltip.call(listener.off); tooltip.select('.counter').remove(); nextStep(); } } function chapters() { dispatch.call('done'); reveal('.intro-nav-wrap .chapter-navigation', t('intro.welcome.chapters', { next: t('intro.navigation.title') }) ); } chapter.enter = function() { welcome(); }; chapter.exit = function() { listener.off(); d3_select('.curtain-tooltip.intro-mouse') .selectAll('.counter') .remove(); }; chapter.restart = function() { chapter.exit(); chapter.enter(); }; return utilRebind(chapter, dispatch, 'on'); } function clickListener() { var dispatch = d3_dispatch('click'); var minTime = 120; var tooltip = d3_select(null); var down = {}; // `down` keeps track of which buttons/keys are down. // Setting a property in `down` happens immediately. // Unsetting a property in `down` is delayed because // on Windows a contextmenu event happens after keyup/mouseup function keydown() { if (d3_event.keyCode === 93) { // context menu d3_event.preventDefault(); d3_event.stopPropagation(); down.menu = d3_event.timeStamp; tooltip.classed('rightclick', true); } } function keyup() { if (d3_event.keyCode === 93) { // context menu d3_event.preventDefault(); d3_event.stopPropagation(); var endTime = d3_event.timeStamp; var startTime = down.menu || endTime; var delay = (endTime - startTime < minTime) ? minTime : 0; window.setTimeout(function() { tooltip.classed('rightclick', false); down.menu = undefined; // delayed, for Windows }, delay); dispatch.call('click', this, 'right'); } } function mousedown() { var button = d3_event.button; if (button === 0 && !d3_event.ctrlKey) { tooltip.classed('leftclick', true); } else if (button === 2) { tooltip.classed('rightclick', true); } down[button] = d3_event.timeStamp; } function mouseup() { var button = d3_event.button; var endTime = d3_event.timeStamp; var startTime = down[button] || endTime; var delay = (endTime - startTime < minTime) ? minTime : 0; if (button === 0 && !d3_event.ctrlKey) { window.setTimeout(function() { tooltip.classed('leftclick', false); down[button] = undefined; // delayed, for Windows }, delay); dispatch.call('click', this, 'left'); } else if (button === 2) { window.setTimeout(function() { tooltip.classed('rightclick', false); down[button] = undefined; // delayed, for Windows }, delay); dispatch.call('click', this, 'right'); } else { window.setTimeout(function() { down[button] = undefined; // delayed, for Windows }, delay); } } function contextmenu() { d3_event.preventDefault(); d3_event.stopPropagation(); if (!down[2] && !down.menu) { tooltip.classed('rightclick', true); window.setTimeout(function() { tooltip.classed('rightclick', false); }, minTime); dispatch.call('click', this, 'right'); } } var behavior = function(selection) { tooltip = selection; down = {}; d3_select(window) .on('keydown.intro', keydown) .on('keyup.intro', keyup) .on('mousedown.intro', mousedown) .on('mouseup.intro', mouseup) .on('contextmenu.intro', contextmenu); }; behavior.off = function() { d3_select(window) .on('keydown.intro', null) .on('keyup.intro', null) .on('mousedown.intro', null) .on('mouseup.intro', null) .on('contextmenu.intro', null); tooltip .classed('leftclick', false) .classed('rightclick', false); }; return utilRebind(behavior, dispatch, 'on'); }