modules/ui/intro/line.js (869 lines of code) (raw):
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 '@id-sdk/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('.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: 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('.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() {
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');
}