Files
iD/modules/ui/intro/line.js
Martin Raifer 7559dead80 add missing retries in walkthrough if edit menu is closed accidentally
e.g. for the "delete node" step, when the map is accidentally panned the edit menu will be closed, causing the walkthrough to get stuck
2025-01-10 16:04:55 +01:00

1087 lines
39 KiB
JavaScript

import { dispatch as d3_dispatch } from 'd3-dispatch';
import {
select as d3_select
} from 'd3-selection';
import { presetManager } from '../../presets';
import { t } from '../../core/localizer';
import { geoSphericalDistance } from '../../geo';
import { modeBrowse } from '../../modes/browse';
import { modeSelect } from '../../modes/select';
import { utilRebind } from '../../util/rebind';
import { helpHtml, icon, pad, selectMenuItem, transitionTime } from './helper';
export function uiIntroLine(context, reveal) {
var dispatch = d3_dispatch('done');
var timeouts = [];
var _tulipRoadID = null;
var flowerRoadID = 'w646';
var tulipRoadStart = [-85.6297754121684, 41.95805253325314];
var tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204];
var tulipRoadIntersection = [-85.62974496187628, 41.95742515554585];
var roadCategory = presetManager.item('category-road_minor');
var residentialPreset = presetManager.item('highway/residential');
var woodRoadID = 'w525';
var woodRoadEndID = 'n2862';
var woodRoadAddNode = [-85.62390110349587, 41.95397111462291];
var woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487];
var woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872];
var washingtonStreetID = 'w522';
var twelfthAvenueID = 'w1';
var eleventhAvenueEndID = 'n3550';
var twelfthAvenueEndID = 'n5';
var _washingtonSegmentID = null;
var eleventhAvenueEnd = context.entity(eleventhAvenueEndID).loc;
var twelfthAvenueEnd = context.entity(twelfthAvenueEndID).loc;
var deleteLinesLoc = [-85.6219395542764, 41.95228033922477];
var twelfthAvenue = [-85.62219310052491, 41.952505413152956];
var chapter = {
title: 'intro.lines.title'
};
function timeout(f, t) {
timeouts.push(window.setTimeout(f, t));
}
function eventCancel(d3_event) {
d3_event.stopPropagation();
d3_event.preventDefault();
}
function addLine() {
context.enter(modeBrowse(context));
context.history().reset('initial');
var msec = transitionTime(tulipRoadStart, context.map().center());
if (msec) { reveal(null, null, { duration: 0 }); }
context.map().centerZoomEase(tulipRoadStart, 18.5, msec);
timeout(function() {
var tooltip = reveal('button.add-line',
helpHtml('intro.lines.add_line'));
tooltip.selectAll('.popover-inner')
.insert('svg', 'span')
.attr('class', 'tooltip-illustration')
.append('use')
.attr('xlink:href', '#iD-graphic-lines');
context.on('enter.intro', function(mode) {
if (mode.id !== 'add-line') return;
continueTo(startLine);
});
}, msec + 100);
function continueTo(nextStep) {
context.on('enter.intro', null);
nextStep();
}
}
function startLine() {
if (context.mode().id !== 'add-line') return chapter.restart();
_tulipRoadID = null;
var padding = 70 * Math.pow(2, context.map().zoom() - 18);
var box = pad(tulipRoadStart, padding, context);
box.height = box.height + 100;
var textId = context.lastPointerType() === 'mouse' ? 'start_line' : 'start_line_tap';
var startLineString = helpHtml('intro.lines.missing_road') + '{br}' +
helpHtml('intro.lines.line_draw_info') +
helpHtml('intro.lines.' + textId);
reveal(box, startLineString);
context.map().on('move.intro drawn.intro', function() {
padding = 70 * Math.pow(2, context.map().zoom() - 18);
box = pad(tulipRoadStart, padding, context);
box.height = box.height + 100;
reveal(box, startLineString, { duration: 0 });
});
context.on('enter.intro', function(mode) {
if (mode.id !== 'draw-line') return chapter.restart();
continueTo(drawLine);
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.on('enter.intro', null);
nextStep();
}
}
function drawLine() {
if (context.mode().id !== 'draw-line') return chapter.restart();
_tulipRoadID = context.mode().selectedIDs()[0];
context.map().centerEase(tulipRoadMidpoint, 500);
timeout(function() {
var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
var box = pad(tulipRoadMidpoint, padding, context);
box.height = box.height * 2;
reveal(box,
helpHtml('intro.lines.intersect', { name: t('intro.graph.name.flower-street') })
);
context.map().on('move.intro drawn.intro', function() {
padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
box = pad(tulipRoadMidpoint, padding, context);
box.height = box.height * 2;
reveal(box,
helpHtml('intro.lines.intersect', { name: t('intro.graph.name.flower-street') }),
{ duration: 0 }
);
});
}, 550); // after easing..
context.history().on('change.intro', function() {
if (isLineConnected()) {
continueTo(continueLine);
}
});
context.on('enter.intro', function(mode) {
if (mode.id === 'draw-line') {
return;
} else if (mode.id === 'select') {
continueTo(retryIntersect);
return;
} else {
return chapter.restart();
}
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.history().on('change.intro', null);
context.on('enter.intro', null);
nextStep();
}
}
function isLineConnected() {
var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
if (!entity) return false;
var drawNodes = context.graph().childNodes(entity);
return drawNodes.some(function(node) {
return context.graph().parentWays(node).some(function(parent) {
return parent.id === flowerRoadID;
});
});
}
function retryIntersect() {
d3_select(window).on('pointerdown.intro mousedown.intro', eventCancel, true);
var box = pad(tulipRoadIntersection, 80, context);
reveal(box,
helpHtml('intro.lines.retry_intersect', { name: t('intro.graph.name.flower-street') })
);
timeout(chapter.restart, 3000);
}
function continueLine() {
if (context.mode().id !== 'draw-line') return chapter.restart();
var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
if (!entity) return chapter.restart();
context.map().centerEase(tulipRoadIntersection, 500);
var continueLineText = helpHtml('intro.lines.continue_line') + '{br}' +
helpHtml('intro.lines.finish_line_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) +
helpHtml('intro.lines.finish_road');
reveal('.main-map .surface', continueLineText);
context.on('enter.intro', function(mode) {
if (mode.id === 'draw-line') {
return;
} else if (mode.id === 'select') {
return continueTo(chooseCategoryRoad);
} else {
return chapter.restart();
}
});
function continueTo(nextStep) {
context.on('enter.intro', null);
nextStep();
}
}
function chooseCategoryRoad() {
if (context.mode().id !== 'select') return chapter.restart();
context.on('exit.intro', function() {
return chapter.restart();
});
var button = context.container().select('.preset-category-road_minor .preset-list-button');
if (button.empty()) return chapter.restart();
// disallow scrolling
context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
timeout(function() {
// reset pane, in case user somehow happened to change it..
context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
reveal(button.node(),
helpHtml('intro.lines.choose_category_road', { category: roadCategory.name() })
);
button.on('click.intro', function() {
continueTo(choosePresetResidential);
});
}, 400); // after editor pane visible
function continueTo(nextStep) {
context.container().select('.inspector-wrap').on('wheel.intro', null);
context.container().select('.preset-list-button').on('click.intro', null);
context.on('exit.intro', null);
nextStep();
}
}
function choosePresetResidential() {
if (context.mode().id !== 'select') return chapter.restart();
context.on('exit.intro', function() {
return chapter.restart();
});
var subgrid = context.container().select('.preset-category-road_minor .subgrid');
if (subgrid.empty()) return chapter.restart();
subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button')
.on('click.intro', function() {
continueTo(retryPresetResidential);
});
subgrid.selectAll('.preset-highway-residential .preset-list-button')
.on('click.intro', function() {
continueTo(nameRoad);
});
timeout(function() {
reveal(subgrid.node(),
helpHtml('intro.lines.choose_preset_residential', { preset: residentialPreset.name() }),
{ tooltipBox: '.preset-highway-residential .preset-list-button', duration: 300 }
);
}, 300);
function continueTo(nextStep) {
context.container().select('.preset-list-button').on('click.intro', null);
context.on('exit.intro', null);
nextStep();
}
}
// selected wrong road type
function retryPresetResidential() {
if (context.mode().id !== 'select') return chapter.restart();
context.on('exit.intro', function() {
return chapter.restart();
});
// disallow scrolling
context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
timeout(function() {
var button = context.container().select('.entity-editor-pane .preset-list-button');
reveal(button.node(),
helpHtml('intro.lines.retry_preset_residential', { preset: residentialPreset.name() })
);
button.on('click.intro', function() {
continueTo(chooseCategoryRoad);
});
}, 500);
function continueTo(nextStep) {
context.container().select('.inspector-wrap').on('wheel.intro', null);
context.container().select('.preset-list-button').on('click.intro', null);
context.on('exit.intro', null);
nextStep();
}
}
function nameRoad() {
context.on('exit.intro', function() {
continueTo(didNameRoad);
});
timeout(function() {
reveal('.entity-editor-pane',
helpHtml('intro.lines.name_road', { button: { html: icon('#iD-icon-close', 'inline') } }),
{ tooltipClass: 'intro-lines-name_road' }
);
}, 500);
function continueTo(nextStep) {
context.on('exit.intro', null);
nextStep();
}
}
function didNameRoad() {
context.history().checkpoint('doneAddLine');
timeout(function() {
reveal('.main-map .surface', helpHtml('intro.lines.did_name_road'), {
buttonText: t.html('intro.ok'),
buttonCallback: function() { continueTo(updateLine); }
});
}, 500);
function continueTo(nextStep) {
nextStep();
}
}
function updateLine() {
context.history().reset('doneAddLine');
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return chapter.restart();
}
var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
if (msec) { reveal(null, null, { duration: 0 }); }
context.map().centerZoomEase(woodRoadDragMidpoint, 19, msec);
timeout(function() {
var padding = 250 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragMidpoint, padding, context);
var advance = function() { continueTo(addNode); };
reveal(box, helpHtml('intro.lines.update_line'),
{ buttonText: t.html('intro.ok'), buttonCallback: advance }
);
context.map().on('move.intro drawn.intro', function() {
var padding = 250 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragMidpoint, padding, context);
reveal(box, helpHtml('intro.lines.update_line'),
{ duration: 0, buttonText: t.html('intro.ok'), buttonCallback: advance }
);
});
}, msec + 100);
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
nextStep();
}
}
function addNode() {
context.history().reset('doneAddLine');
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return chapter.restart();
}
var padding = 40 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadAddNode, padding, context);
var addNodeString = helpHtml('intro.lines.add_node' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
reveal(box, addNodeString);
context.map().on('move.intro drawn.intro', function() {
var padding = 40 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadAddNode, padding, context);
reveal(box, addNodeString, { duration: 0 });
});
context.history().on('change.intro', function(changed) {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
if (changed.created().length === 1) {
timeout(function() { continueTo(startDragEndpoint); }, 500);
}
});
context.on('enter.intro', function(mode) {
if (mode.id !== 'select') {
continueTo(updateLine);
}
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.history().on('change.intro', null);
context.on('enter.intro', null);
nextStep();
}
}
function startDragEndpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
var startDragString = helpHtml('intro.lines.start_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch')) +
helpHtml('intro.lines.drag_to_intersection');
reveal(box, startDragString);
context.map().on('move.intro drawn.intro', function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
reveal(box, startDragString, { duration: 0 });
var entity = context.entity(woodRoadEndID);
if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
continueTo(finishDragEndpoint);
}
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
nextStep();
}
}
function finishDragEndpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
var finishDragString = helpHtml('intro.lines.spot_looks_good') +
helpHtml('intro.lines.finish_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
reveal(box, finishDragString);
context.map().on('move.intro drawn.intro', function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
reveal(box, finishDragString, { duration: 0 });
var entity = context.entity(woodRoadEndID);
if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
continueTo(startDragEndpoint);
}
});
context.on('enter.intro', function() {
continueTo(startDragMidpoint);
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.on('enter.intro', null);
nextStep();
}
}
function startDragMidpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
if (context.selectedIDs().indexOf(woodRoadID) === -1) {
context.enter(modeSelect(context, [woodRoadID]));
}
var padding = 80 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragMidpoint, padding, context);
reveal(box, helpHtml('intro.lines.start_drag_midpoint'));
context.map().on('move.intro drawn.intro', function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 80 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragMidpoint, padding, context);
reveal(box, helpHtml('intro.lines.start_drag_midpoint'), { duration: 0 });
});
context.history().on('change.intro', function(changed) {
if (changed.created().length === 1) {
continueTo(continueDragMidpoint);
}
});
context.on('enter.intro', function(mode) {
if (mode.id !== 'select') {
// keep Wood Road selected so midpoint triangles are drawn..
context.enter(modeSelect(context, [woodRoadID]));
}
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.history().on('change.intro', null);
context.on('enter.intro', null);
nextStep();
}
}
function continueDragMidpoint() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
box.height += 400;
var advance = function() {
context.history().checkpoint('doneUpdateLine');
continueTo(deleteLines);
};
reveal(box, helpHtml('intro.lines.continue_drag_midpoint'),
{ buttonText: t.html('intro.ok'), buttonCallback: advance }
);
context.map().on('move.intro drawn.intro', function() {
if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
return continueTo(updateLine);
}
var padding = 100 * Math.pow(2, context.map().zoom() - 19);
var box = pad(woodRoadDragEndpoint, padding, context);
box.height += 400;
reveal(box, helpHtml('intro.lines.continue_drag_midpoint'),
{ duration: 0, buttonText: t.html('intro.ok'), buttonCallback: advance }
);
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
nextStep();
}
}
function deleteLines() {
context.history().reset('doneUpdateLine');
context.enter(modeBrowse(context));
if (!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return chapter.restart();
}
var msec = transitionTime(deleteLinesLoc, context.map().center());
if (msec) { reveal(null, null, { duration: 0 }); }
context.map().centerZoomEase(deleteLinesLoc, 18, msec);
timeout(function() {
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(deleteLinesLoc, padding, context);
box.top -= 200;
box.height += 400;
var advance = function() { continueTo(rightClickIntersection); };
reveal(box, helpHtml('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
{ buttonText: t.html('intro.ok'), buttonCallback: advance }
);
context.map().on('move.intro drawn.intro', function() {
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(deleteLinesLoc, padding, context);
box.top -= 200;
box.height += 400;
reveal(box, helpHtml('intro.lines.delete_lines', { street: t('intro.graph.name.12th-avenue') }),
{ duration: 0, buttonText: t.html('intro.ok'), buttonCallback: advance }
);
});
context.history().on('change.intro', function() {
timeout(function() {
continueTo(deleteLines);
}, 500); // after any transition (e.g. if user deleted intersection)
});
}, msec + 100);
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.history().on('change.intro', null);
nextStep();
}
}
function rightClickIntersection() {
context.history().reset('doneUpdateLine');
context.enter(modeBrowse(context));
context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
var rightClickString = helpHtml('intro.lines.split_street', {
street1: t('intro.graph.name.11th-avenue'),
street2: t('intro.graph.name.washington-street')
}) +
helpHtml('intro.lines.' + (context.lastPointerType() === 'mouse' ? 'rightclick_intersection' : 'edit_menu_intersection_touch'));
timeout(function() {
var padding = 60 * Math.pow(2, context.map().zoom() - 18);
var box = pad(eleventhAvenueEnd, padding, context);
reveal(box, rightClickString);
context.map().on('move.intro drawn.intro', function() {
var padding = 60 * Math.pow(2, context.map().zoom() - 18);
var box = pad(eleventhAvenueEnd, padding, context);
reveal(box, rightClickString,
{ duration: 0 }
);
});
context.on('enter.intro', function(mode) {
if (mode.id !== 'select') return;
var ids = context.selectedIDs();
if (ids.length !== 1 || ids[0] !== eleventhAvenueEndID) return;
timeout(function() {
var node = selectMenuItem(context, 'split').node();
if (!node) return;
continueTo(splitIntersection);
}, 50); // after menu visible
});
context.history().on('change.intro', function() {
timeout(function() {
continueTo(deleteLines);
}, 300); // after any transition (e.g. if user deleted intersection)
});
}, 600);
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.on('enter.intro', null);
context.history().on('change.intro', null);
nextStep();
}
}
function splitIntersection() {
if (!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(deleteLines);
}
var node = selectMenuItem(context, 'split').node();
if (!node) { return continueTo(rightClickIntersection); }
var wasChanged = false;
_washingtonSegmentID = null;
reveal('.edit-menu', helpHtml('intro.lines.split_intersection',
{ street: t('intro.graph.name.washington-street') }),
{ padding: 50 }
);
context.map().on('move.intro drawn.intro', function() {
var node = selectMenuItem(context, 'split').node();
if (!wasChanged && !node) { return continueTo(rightClickIntersection); }
reveal('.edit-menu', helpHtml('intro.lines.split_intersection',
{ street: t('intro.graph.name.washington-street') }),
{ duration: 0, padding: 50 }
);
});
context.history().on('change.intro', function(changed) {
wasChanged = true;
timeout(function() {
if (context.history().undoAnnotation() === t('operations.split.annotation.line', { n: 1 })) {
_washingtonSegmentID = changed.created()[0].id;
continueTo(didSplit);
} else {
_washingtonSegmentID = null;
continueTo(retrySplit);
}
}, 300); // after any transition (e.g. if user deleted intersection)
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.history().on('change.intro', null);
nextStep();
}
}
function retrySplit() {
context.enter(modeBrowse(context));
context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
var advance = function() { continueTo(rightClickIntersection); };
var padding = 60 * Math.pow(2, context.map().zoom() - 18);
var box = pad(eleventhAvenueEnd, padding, context);
reveal(box, helpHtml('intro.lines.retry_split'),
{ buttonText: t.html('intro.ok'), buttonCallback: advance }
);
context.map().on('move.intro drawn.intro', function() {
var padding = 60 * Math.pow(2, context.map().zoom() - 18);
var box = pad(eleventhAvenueEnd, padding, context);
reveal(box, helpHtml('intro.lines.retry_split'),
{ duration: 0, buttonText: t.html('intro.ok'), buttonCallback: advance }
);
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
nextStep();
}
}
function didSplit() {
if (!_washingtonSegmentID ||
!context.hasEntity(_washingtonSegmentID) ||
!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var ids = context.selectedIDs();
var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single');
var street = t('intro.graph.name.washington-street');
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
box.width = box.width / 2;
reveal(box, helpHtml(string, { street1: street, street2: street }),
{ duration: 500 }
);
timeout(function() {
context.map().centerZoomEase(twelfthAvenue, 18, 500);
context.map().on('move.intro drawn.intro', function() {
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
box.width = box.width / 2;
reveal(box, helpHtml(string, { street1: street, street2: street }),
{ duration: 0 }
);
});
}, 600); // after initial reveal and curtain cut
context.on('enter.intro', function() {
var ids = context.selectedIDs();
if (ids.length === 1 && ids[0] === _washingtonSegmentID) {
continueTo(multiSelect);
}
});
context.history().on('change.intro', function() {
if (!_washingtonSegmentID ||
!context.hasEntity(_washingtonSegmentID) ||
!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.on('enter.intro', null);
context.history().on('change.intro', null);
nextStep();
}
}
function multiSelect() {
if (!_washingtonSegmentID ||
!context.hasEntity(_washingtonSegmentID) ||
!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var ids = context.selectedIDs();
var hasWashington = ids.indexOf(_washingtonSegmentID) !== -1;
var hasTwelfth = ids.indexOf(twelfthAvenueID) !== -1;
if (hasWashington && hasTwelfth) {
return continueTo(multiRightClick);
} else if (!hasWashington && !hasTwelfth) {
return continueTo(didSplit);
}
context.map().centerZoomEase(twelfthAvenue, 18, 500);
timeout(function() {
var selected, other, padding, box;
if (hasWashington) {
selected = t('intro.graph.name.washington-street');
other = t('intro.graph.name.12th-avenue');
padding = 60 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenueEnd, padding, context);
box.width *= 3;
} else {
selected = t('intro.graph.name.12th-avenue');
other = t('intro.graph.name.washington-street');
padding = 200 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenue, padding, context);
box.width /= 2;
}
reveal(box,
helpHtml('intro.lines.multi_select',
{ selected: selected, other1: other }) + ' ' +
helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'),
{ selected: selected, other2: other })
);
context.map().on('move.intro drawn.intro', function() {
if (hasWashington) {
selected = t('intro.graph.name.washington-street');
other = t('intro.graph.name.12th-avenue');
padding = 60 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenueEnd, padding, context);
box.width *= 3;
} else {
selected = t('intro.graph.name.12th-avenue');
other = t('intro.graph.name.washington-street');
padding = 200 * Math.pow(2, context.map().zoom() - 18);
box = pad(twelfthAvenue, padding, context);
box.width /= 2;
}
reveal(box,
helpHtml('intro.lines.multi_select',
{ selected: selected, other1: other }) + ' ' +
helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'),
{ selected: selected, other2: other }),
{ duration: 0 }
);
});
context.on('enter.intro', function() {
continueTo(multiSelect);
});
context.history().on('change.intro', function() {
if (!_washingtonSegmentID ||
!context.hasEntity(_washingtonSegmentID) ||
!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
});
}, 600);
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.on('enter.intro', null);
context.history().on('change.intro', null);
nextStep();
}
}
function multiRightClick() {
if (!_washingtonSegmentID ||
!context.hasEntity(_washingtonSegmentID) ||
!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
var rightClickString = helpHtml('intro.lines.multi_select_success') +
helpHtml('intro.lines.multi_' + (context.lastPointerType() === 'mouse' ? 'rightclick' : 'edit_menu_touch'));
reveal(box, rightClickString);
context.map().on('move.intro drawn.intro', function() {
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
reveal(box, rightClickString, { duration: 0 });
});
context.ui().editMenu().on('toggled.intro', function(open) {
if (!open) return;
timeout(function() {
var ids = context.selectedIDs();
if (ids.length === 2 &&
ids.indexOf(twelfthAvenueID) !== -1 &&
ids.indexOf(_washingtonSegmentID) !== -1) {
var node = selectMenuItem(context, 'delete').node();
if (!node) return;
continueTo(multiDelete);
} else if (ids.length === 1 &&
ids.indexOf(_washingtonSegmentID) !== -1) {
return continueTo(multiSelect);
} else {
return continueTo(didSplit);
}
}, 300); // after edit menu visible
});
context.history().on('change.intro', function() {
if (!_washingtonSegmentID ||
!context.hasEntity(_washingtonSegmentID) ||
!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.ui().editMenu().on('toggled.intro', null);
context.history().on('change.intro', null);
nextStep();
}
}
function multiDelete() {
if (!_washingtonSegmentID ||
!context.hasEntity(_washingtonSegmentID) ||
!context.hasEntity(washingtonStreetID) ||
!context.hasEntity(twelfthAvenueID) ||
!context.hasEntity(eleventhAvenueEndID)) {
return continueTo(rightClickIntersection);
}
var node = selectMenuItem(context, 'delete').node();
if (!node) return continueTo(multiRightClick);
reveal('.edit-menu',
helpHtml('intro.lines.multi_delete'),
{ padding: 50 }
);
context.map().on('move.intro drawn.intro', function() {
if (selectMenuItem(context, 'delete').empty()) {
return continueTo(multiRightClick);
}
reveal('.edit-menu',
helpHtml('intro.lines.multi_delete'),
{ duration: 0, padding: 50 }
);
});
context.on('exit.intro', function() {
if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
return continueTo(multiSelect); // left select mode but roads still exist
}
});
context.history().on('change.intro', function() {
if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
continueTo(retryDelete); // changed something but roads still exist
} else {
continueTo(play);
}
});
function continueTo(nextStep) {
context.map().on('move.intro drawn.intro', null);
context.on('exit.intro', null);
context.history().on('change.intro', null);
nextStep();
}
}
function retryDelete() {
context.enter(modeBrowse(context));
var padding = 200 * Math.pow(2, context.map().zoom() - 18);
var box = pad(twelfthAvenue, padding, context);
reveal(box, helpHtml('intro.lines.retry_delete'), {
buttonText: t.html('intro.ok'),
buttonCallback: function() { continueTo(multiSelect); }
});
function continueTo(nextStep) {
nextStep();
}
}
function play() {
dispatch.call('done');
reveal('.ideditor',
helpHtml('intro.lines.play', { next: t('intro.buildings.title') }), {
tooltipBox: '.intro-nav-wrap .chapter-building',
buttonText: t.html('intro.ok'),
buttonCallback: function() { reveal('.ideditor'); }
}
);
}
chapter.enter = function() {
addLine();
};
chapter.exit = function() {
timeouts.forEach(window.clearTimeout);
d3_select(window).on('pointerdown.intro mousedown.intro', null, true);
context.on('enter.intro exit.intro', null);
context.map().on('move.intro drawn.intro', null);
context.history().on('change.intro', null);
context.container().select('.inspector-wrap').on('wheel.intro', null);
context.container().select('.preset-list-button').on('click.intro', null);
};
chapter.restart = function() {
chapter.exit();
chapter.enter();
};
return utilRebind(chapter, dispatch, 'on');
}