diff --git a/css/80_app.css b/css/80_app.css index 310adf82d..593da509e 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -2006,14 +2006,15 @@ div.combobox { .field-help-body { display: block; position: absolute; + top: 0; + left: 20px; + right: 20px; + margin: 5px; + padding: 8px; border: 1px solid #ccc; border-top: 0; border-radius: 0 0 4px 4px; - margin-left: 5px; - margin-right: 5px; - top: 0; z-index: 20; - max-height: 550px; background: rgba(255,255,255,0.95); box-shadow: 0 0 30px 5px rgba(0,0,0,.4); } @@ -2021,13 +2022,31 @@ div.combobox { .field-help-title h2 { padding: 10px; margin-bottom: 0px; - font-size: 16px; + font-size: 17px; +} +.field-help-title button { + width: 45px; + height: 55px; + border-radius: 0; } -.field-help-title button { - width: 32px; - height: 40px; - border-radius: 0; +.field-help-nav { + font-size: 13px; + font-weight: bold; + margin-bottom: 10px; +} +.field-help-nav-item { + display: inline-block; + padding: 5px 10px; + cursor: pointer; + color: #666; +} +.field-help-nav-item.active { + color: #7092ff; +} +.field-help-nav-item:hover { + color: #597be7; + background-color: #efefef; } .field-help-content { @@ -2035,21 +2054,23 @@ div.combobox { overflow-y: auto; overflow-x: hidden; } - .field-help-content h3 { font-size: 12px; margin-bottom: 5px; } - .field-help-content p { - margin-bottom: 5px; + margin-bottom: 15px; } - .field-help-content ul li { list-style: inside; margin-bottom: 5px; } +.field-help-content .field-help-image { + width: 100%; + margin-bottom: 15px; +} + .field-help-content svg.turn { width: 40px; height: 20px; @@ -2072,17 +2093,12 @@ div.combobox { color: #68f; } -.field-help-nav { - position: relative; -} -.field-help-nav a { - float: left; - width: 50%; - text-align: center; -} -.field-help-nav-item { - display: inline-block; - list-style: none; +.field-help-content p.from_shadow, +.field-help-content p.allow_shadow, +.field-help-content p.restrict_shadow, +.field-help-content p.allow_turn, +.field-help-content p.restrict_turn { + margin-bottom: 5px; } diff --git a/data/core.yaml b/data/core.yaml index ed2dafbc1..3cd073fd5 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -744,28 +744,36 @@ en: upload: "You can also [upload your GPS data to OpenStreetMap](https://www.openstreetmap.org/trace/create) for other users to use." field: restrictions: - title: Editing Turn Restrictions + title: Turn Restrictions Help + about: + title: About + about: "This field allows you to inspect and modify turn restrictions. It displays a model of the selected intersection including other nearby connected roads." + from_via_to: "A turn restriction always contains: one **FROM way**, one **TO way**, and one **VIA node** or one or more **VIA ways**." + maxdist: "The \"{distField}\" slider controls how far to search for additional connected roads." + maxvia: "The \"{viaField}\" slider adjusts how many via ways may be included in the search. (Tip: simple is better)" inspecting: title: Inspecting - about: "Hover over any starting segment. All possible **TO** destinations will be drawn with a shadow." - from: "{fromShadow} **FROM**" - allow: "{allowShadow} **Allowed**" - restrict: "{restrictShadow} **Restricted**" - only: "{onlyShadow} **Only**" + about: "Hover over any **FROM** segment. Possible **TO** destinations will be drawn with a shadow." + from_shadow: "{fromShadow} **FROM segment**" + allow_shadow: "{allowShadow} **TO Allowed**" + restrict_shadow: "{restrictShadow} **TO Restricted**" + only_shadow: "{onlyShadow} **TO Only**" + restricted: "\"Restricted\" means that there is a turn restriction, for example \"No Left Turn\"." + only: "\"Only\" means that a vehicle may only make that choice, for example \"Only Straight On\"." modifying: title: Modifying - about: "Click on any starting segment to select it. All possible **TO** destinations will appear as turn indicators." - indicators: "Click on a turn indicator to toggle it between \"Allowed\", \"Restricted\", and \"Only\"." - allow: "{allowTurn} **Allowed**" - restrict: "{restrictTurn} **Restricted**" - only: "{onlyTurn} **Only**" + about: "Click on any starting **FROM** segment to select it. The selected segment will pulse, and all possible **TO** destinations will appear as turn symbols." + indicators: "Click on a turn symbol to toggle it between \"Allowed\", \"Restricted\", and \"Only\"." + allow_turn: "{allowTurn} **TO Allowed**" + restrict_turn: "{restrictTurn} **TO Restricted**" + only_turn: "{onlyTurn} **TO Only**" tips: title: Tips - tip1: "* Prefer simple restrictions over complex ones." - tip2: For example, avoid using a via-way restriction if a simpler turn restriction will do. - tip3: "* Some restrictions are \"(indirect)\". These restrictions exist because of another nearby restriction." - tip4: "For example, a route with an \"Only Straight On\" turn restriction will indirectly create \"No Turn\" restrictions." - tip5: "* You may not edit an indirect restriction. Instead, edit the nearby direct restriction." + simple: "**Prefer simple restrictions over complex ones.**" + simple_example: "For example, avoid creating a via-way restriction if a simpler via-node turn restriction will do." + indirect: "**Some restrictions display the text \"(indirect)\" and are drawn lighter.**" + indirect_example: "These restrictions exist because of another nearby restriction. For example, a route with an \"Only Straight On\" restriction will indirectly create \"No Turn\" restrictions for all other paths through the intersection." + indirect_noedit: "You may not edit indirect restrictions. Instead, edit the nearby direct restriction." intro: done: done ok: OK diff --git a/dist/locales/en.json b/dist/locales/en.json index 2a24b2caa..434e0704f 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -885,30 +885,39 @@ }, "field": { "restrictions": { - "title": "Editing Turn Restrictions", + "title": "Turn Restrictions Help", + "about": { + "title": "About", + "about": "This field allows you to inspect and modify turn restrictions. It displays a model of the selected intersection including other nearby connected roads.", + "from_via_to": "A turn restriction always contains: one **FROM way**, one **TO way**, and one **VIA node** or one or more **VIA ways**.", + "maxdist": "The \"{distField}\" slider controls how far to search for additional connected roads.", + "maxvia": "The \"{viaField}\" slider adjusts how many via ways may be included in the search. (Tip: simple is better)" + }, "inspecting": { "title": "Inspecting", - "about": "Hover over any starting segment. All possible **TO** destinations will be drawn with a shadow.", - "from": "{fromShadow} **FROM**", - "allow": "{allowShadow} **Allowed**", - "restrict": "{restrictShadow} **Restricted**", - "only": "{onlyShadow} **Only**" + "about": "Hover over any **FROM** segment. Possible **TO** destinations will be drawn with a shadow.", + "from_shadow": "{fromShadow} **FROM segment**", + "allow_shadow": "{allowShadow} **TO Allowed**", + "restrict_shadow": "{restrictShadow} **TO Restricted**", + "only_shadow": "{onlyShadow} **TO Only**", + "restricted": "\"Restricted\" means that there is a turn restriction, for example \"No Left Turn\".", + "only": "\"Only\" means that a vehicle may only make that choice, for example \"Only Straight On\"." }, "modifying": { "title": "Modifying", - "about": "Click on any starting segment to select it. All possible **TO** destinations will appear as turn indicators.", - "indicators": "Click on a turn indicator to toggle it between \"Allowed\", \"Restricted\", and \"Only\".", - "allow": "{allowTurn} **Allowed**", - "restrict": "{restrictTurn} **Restricted**", - "only": "{onlyTurn} **Only**" + "about": "Click on any starting **FROM** segment to select it. The selected segment will pulse, and all possible **TO** destinations will appear as turn symbols.", + "indicators": "Click on a turn symbol to toggle it between \"Allowed\", \"Restricted\", and \"Only\".", + "allow_turn": "{allowTurn} **TO Allowed**", + "restrict_turn": "{restrictTurn} **TO Restricted**", + "only_turn": "{onlyTurn} **TO Only**" }, "tips": { "title": "Tips", - "tip1": "* Prefer simple restrictions over complex ones.", - "tip2": "For example, avoid using a via-way restriction if a simpler turn restriction will do.", - "tip3": "* Some restrictions are \"(indirect)\". These restrictions exist because of another nearby restriction.", - "tip4": "For example, a route with an \"Only Straight On\" turn restriction will indirectly create \"No Turn\" restrictions.", - "tip5": "* You may not edit an indirect restriction. Instead, edit the nearby direct restriction." + "simple": "**Prefer simple restrictions over complex ones.**", + "simple_example": "For example, avoid creating a via-way restriction if a simpler via-node turn restriction will do.", + "indirect": "**Some restrictions display the text \"(indirect)\" and are drawn lighter.**", + "indirect_example": "These restrictions exist because of another nearby restriction. For example, a route with an \"Only Straight On\" restriction will indirectly create \"No Turn\" restrictions for all other paths through the intersection.", + "indirect_noedit": "You may not edit indirect restrictions. Instead, edit the nearby direct restriction." } } } diff --git a/modules/ui/field_help.js b/modules/ui/field_help.js index df334a5fe..803e40c67 100644 --- a/modules/ui/field_help.js +++ b/modules/ui/field_help.js @@ -10,51 +10,7 @@ import { icon } from 'intro/helper'; // This currently only works with the 'restrictions' field -var fieldHelpKeys = { - restrictions: [ - ['inspecting',[ - 'title', - 'about', - 'from', - 'allow', - 'restrict', - 'only' - ]], - ['modifying',[ - 'title', - 'about', - 'indicators', - 'allow', - 'restrict', - 'only' - ]], - ['tips',[ - 'title', - 'tip1', - 'tip2', - 'tip3', - 'tip4', - 'tip5' - ]] - ] -}; - -var fieldHelpHeadings = { - 'help.field.restrictions.inspecting.title': 3, - 'help.field.restrictions.modifying.title': 3, - 'help.field.restrictions.tips.title': 3 -}; - -var replacements = { - fromShadow: icon('#turn-shadow', 'pre-text shadow from'), - allowShadow: icon('#turn-shadow', 'pre-text shadow allow'), - restrictShadow: icon('#turn-shadow', 'pre-text shadow restrict'), - onlyShadow: icon('#turn-shadow', 'pre-text shadow only'), - allowTurn: icon('#turn-yes', 'pre-text turn'), - restrictTurn: icon('#turn-no', 'pre-text turn'), - onlyTurn: icon('#turn-only', 'pre-text turn') -}; - +// It borrows some code from uiHelp export function uiFieldHelp(context, fieldName) { var fieldHelp = {}; @@ -62,6 +18,55 @@ export function uiFieldHelp(context, fieldName) { var _wrap = d3_select(null); var _body = d3_select(null); + var fieldHelpKeys = { + restrictions: [ + ['about',[ + 'about', + 'from_via_to', + 'maxdist', + 'maxvia' + ]], + ['inspecting',[ + 'about', + 'from_shadow', + 'allow_shadow', + 'restrict_shadow', + 'only_shadow', + 'restricted', + 'only' + ]], + ['modifying',[ + 'about', + 'indicators', + 'allow_turn', + 'restrict_turn', + 'only_turn' + ]], + ['tips',[ + 'simple', + 'simple_example', + 'indirect', + 'indirect_example', + 'indirect_noedit' + ]] + ] + }; + + var fieldHelpHeadings = {}; + + var replacements = { + distField: t('restriction.controls.distance'), + viaField: t('restriction.controls.via'), + fromShadow: icon('#turn-shadow', 'pre-text shadow from'), + allowShadow: icon('#turn-shadow', 'pre-text shadow allow'), + restrictShadow: icon('#turn-shadow', 'pre-text shadow restrict'), + onlyShadow: icon('#turn-shadow', 'pre-text shadow only'), + allowTurn: icon('#turn-yes', 'pre-text turn'), + restrictTurn: icon('#turn-no', 'pre-text turn'), + onlyTurn: icon('#turn-only', 'pre-text turn') + }; + + // For each section, squash all the texts into a single markdown document var docs = fieldHelpKeys[fieldName].map(function(key) { var helpkey = 'help.field.' + fieldName + '.' + key[0]; @@ -104,26 +109,32 @@ export function uiFieldHelp(context, fieldName) { } - function clickHelp(d, i) { + function clickHelp(index) { + var d = docs[index]; + var tkeys = fieldHelpKeys[fieldName][index][1]; + + _body.selectAll('.field-help-nav-item') + .classed('active', function(d, i) { return i === index; }); + var content = _body.selectAll('.field-help-content') .html(d.html); - // add an image for some help sections - var img; - switch (d.key) { - case 'help.field.restrictions.inspecting': - img = 'tr_inspect.gif'; - break; - case 'help.field.restrictions.modifying': - img = 'tr_modify.gif'; - break; - } + // class the paragraphs so we can find and style them + content.selectAll('p') + .attr('class', function(d, i) { return tkeys[i]; }); - if (img) { + // insert special content for certain help sections + if (d.key === 'help.field.restrictions.inspecting') { content - .append('img') - .attr('class', 'field-help-image') - .attr('src', context.imagePath(img)); + .insert('img', 'p.from_shadow') + .attr('class', 'field-help-image cf') + .attr('src', context.imagePath('tr_inspect.gif')); + + } else if (d.key === 'help.field.restrictions.modifying') { + content + .insert('img', 'p.allow_turn') + .attr('class', 'field-help-image cf') + .attr('src', context.imagePath('tr_modify.gif')); } } @@ -160,17 +171,16 @@ export function uiFieldHelp(context, fieldName) { var iRect = inspector.getBoundingClientRect(); _body - .style('left', wRect.left + 'px') - .style('width', wRect.width - 10 + 'px') - .style('top', wRect.top + inspector.scrollTop - iRect.top + 5 + 'px'); + .style('top', wRect.top + inspector.scrollTop - iRect.top + 'px'); } fieldHelp.body = function(selection) { - // this control expects the field to have a preset-input-wrap div + // This control expects the field to have a preset-input-wrap div _wrap = selection.selectAll('.preset-input-wrap'); if (_wrap.empty()) return; + // absolute position relative to the inspector, so it "floats" above the fields _inspector = d3_select('#sidebar .entity-editor-pane .inspector-body'); if (_inspector.empty()) return; @@ -180,7 +190,6 @@ export function uiFieldHelp(context, fieldName) { var enter = _body.enter() .append('div') .attr('class', 'field-help-body hide'); // initially hidden - // .style('height', '0px'); var titleEnter = enter .append('div') @@ -202,22 +211,20 @@ export function uiFieldHelp(context, fieldName) { .call(svgIcon('#icon-close')); var navEnter = enter - .append('ul') - .attr('class', 'field-help-nav'); + .append('div') + .attr('class', 'field-help-nav cf'); var titles = docs.map(function(d) { return d.title; }); navEnter.selectAll('.field-help-nav-item') .data(titles) .enter() - .append('li') + .append('div') .attr('class', 'field-help-nav-item') - .append('a') - .attr('class', 'next') .text(function(d) { return d; }) .on('click', function(d, i) { d3_event.stopPropagation(); d3_event.preventDefault(); - clickHelp(docs[i], i); + clickHelp(i); }); enter @@ -227,7 +234,7 @@ export function uiFieldHelp(context, fieldName) { _body = _body .merge(enter); - clickHelp(docs[0], 0); + clickHelp(0); };