From ac77289b4db4dca729b0b7f1c290bf1096056ceb Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Thu, 23 Jun 2022 18:24:48 +0200 Subject: [PATCH] refactor localized text rendering in tooltips, flash messages --- modules/behavior/draw_way.js | 8 ++++---- modules/behavior/operation.js | 2 +- modules/modes/add_note.js | 2 +- modules/modes/browse.js | 4 ++-- modules/modes/drag_node.js | 6 +++--- modules/modes/draw_area.js | 2 +- modules/modes/draw_line.js | 2 +- modules/modes/select.js | 2 +- modules/renderer/background_source.js | 8 ++++---- modules/ui/commit.js | 13 ++++++++----- modules/ui/edit_menu.js | 2 +- modules/ui/feature_info.js | 13 ++++++++++--- modules/ui/field.js | 2 +- modules/ui/fields/localized.js | 2 +- modules/ui/flash.js | 10 +++++++--- modules/ui/geolocate.js | 4 ++-- modules/ui/init.js | 10 +++++++--- modules/ui/issues_info.js | 2 +- modules/ui/pane.js | 5 +++-- modules/ui/panels/background.js | 4 ++-- modules/ui/panes/background.js | 4 ++-- modules/ui/panes/help.js | 6 +++--- modules/ui/panes/issues.js | 4 ++-- modules/ui/panes/map_data.js | 4 ++-- modules/ui/panes/preferences.js | 4 ++-- modules/ui/preset_list.js | 4 ++-- modules/ui/sections/background_list.js | 20 +++++++++----------- modules/ui/sections/data_layers.js | 18 +++++++++--------- modules/ui/sections/feature_type.js | 2 +- modules/ui/sections/map_features.js | 9 ++++++--- modules/ui/sections/map_style_options.js | 2 +- modules/ui/sections/overlay_list.js | 4 ++-- modules/ui/sections/photo_overlays.js | 12 ++++++------ modules/ui/sections/privacy.js | 2 +- modules/ui/sections/raw_membership_editor.js | 4 +++- modules/ui/sections/raw_tag_editor.js | 4 +++- modules/ui/sections/validation_rules.js | 2 +- modules/ui/tools/modes.js | 17 +++++++++-------- modules/ui/tools/notes.js | 2 +- modules/ui/tools/save.js | 8 ++++---- modules/ui/tools/sidebar_toggle.js | 4 ++-- modules/ui/tools/undo_redo.js | 14 +++++++------- modules/ui/tooltip.js | 11 ++++++++--- modules/ui/top_toolbar.js | 4 +--- modules/ui/version.js | 2 +- modules/ui/zoom.js | 8 ++++---- modules/ui/zoom_to_selection.js | 6 +++--- 47 files changed, 156 insertions(+), 128 deletions(-) diff --git a/modules/behavior/draw_way.js b/modules/behavior/draw_way.js index 44e61f1bc..29fa0aa1f 100644 --- a/modules/behavior/draw_way.js +++ b/modules/behavior/draw_way.js @@ -447,7 +447,7 @@ export function behaviorDrawWay(context, wayID, mode, startGraph) { context.ui().flash .duration(4000) .iconName('#iD-icon-no') - .label(t.html('operations.follow.error.needs_more_initial_nodes'))(); + .label(t.append('operations.follow.error.needs_more_initial_nodes'))(); return; } @@ -461,7 +461,7 @@ export function behaviorDrawWay(context, wayID, mode, startGraph) { context.ui().flash .duration(4000) .iconName('#iD-icon-no') - .label(t.html(`operations.follow.error.intersection_of_multiple_ways.${featureType}`))(); + .label(t.append(`operations.follow.error.intersection_of_multiple_ways.${featureType}`))(); return; } @@ -472,7 +472,7 @@ export function behaviorDrawWay(context, wayID, mode, startGraph) { context.ui().flash .duration(4000) .iconName('#iD-icon-no') - .label(t.html(`operations.follow.error.intersection_of_different_ways.${featureType}`))(); + .label(t.append(`operations.follow.error.intersection_of_different_ways.${featureType}`))(); return; } @@ -501,7 +501,7 @@ export function behaviorDrawWay(context, wayID, mode, startGraph) { context.ui().flash .duration(4000) .iconName('#iD-icon-no') - .label(t.html('operations.follow.error.unknown'))(); + .label(t.append('operations.follow.error.unknown'))(); } } diff --git a/modules/behavior/operation.js b/modules/behavior/operation.js index 724e18f9c..b10fcd3cb 100644 --- a/modules/behavior/operation.js +++ b/modules/behavior/operation.js @@ -19,7 +19,7 @@ export function behaviorOperation(context) { .duration(4000) .iconName('#iD-operation-' + _operation.id) .iconClass('operation disabled') - .label(_operation.tooltip)(); + .label(_operation.tooltip())(); } else { context.ui().flash diff --git a/modules/modes/add_note.js b/modules/modes/add_note.js index 430c70a26..71f9887cc 100644 --- a/modules/modes/add_note.js +++ b/modules/modes/add_note.js @@ -10,7 +10,7 @@ export function modeAddNote(context) { var mode = { id: 'add-note', button: 'note', - description: t.html('modes.add_note.description'), + description: t.append('modes.add_note.description'), key: t('modes.add_note.key') }; diff --git a/modules/modes/browse.js b/modules/modes/browse.js index b268b76c6..c12a17526 100644 --- a/modules/modes/browse.js +++ b/modules/modes/browse.js @@ -14,8 +14,8 @@ export function modeBrowse(context) { var mode = { button: 'browse', id: 'browse', - title: t('modes.browse.title'), - description: t('modes.browse.description') + title: t.append('modes.browse.title'), + description: t.append('modes.browse.description') }; var sidebar; diff --git a/modules/modes/drag_node.js b/modules/modes/drag_node.js index 0e531df9c..b229868ce 100644 --- a/modules/modes/drag_node.js +++ b/modules/modes/drag_node.js @@ -138,7 +138,7 @@ export function modeDragNode(context) { context.ui().flash .duration(4000) .iconName('#iD-icon-no') - .label(t('modes.drag_node.connected_to_hidden'))(); + .label(t.append('modes.drag_node.connected_to_hidden'))(); } return drag.cancel(); } @@ -239,7 +239,7 @@ export function modeDragNode(context) { context.ui().flash .duration(4000) .iconName('#iD-icon-no') - .label(t.html('operations.connect.' + isInvalid, + .label(t.append('operations.connect.' + isInvalid, { relation: presetManager.item('type/restriction').name() } ))(); } @@ -248,7 +248,7 @@ export function modeDragNode(context) { context.ui().flash .duration(3000) .iconName('#iD-icon-no') - .label(t.html('self_intersection.error.' + errorID))(); + .label(t.append('self_intersection.error.' + errorID))(); } else { if (nope) { // about to un-nope, remove hint context.ui().flash diff --git a/modules/modes/draw_area.js b/modules/modes/draw_area.js index 213fa127b..8014569b0 100644 --- a/modules/modes/draw_area.js +++ b/modules/modes/draw_area.js @@ -12,7 +12,7 @@ export function modeDrawArea(context, wayID, startGraph, button) { .on('rejectedSelfIntersection.modeDrawArea', function() { context.ui().flash .iconName('#iD-icon-no') - .label(t.html('self_intersection.error.areas'))(); + .label(t.append('self_intersection.error.areas'))(); }); mode.wayID = wayID; diff --git a/modules/modes/draw_line.js b/modules/modes/draw_line.js index b5dd99429..caa78f060 100644 --- a/modules/modes/draw_line.js +++ b/modules/modes/draw_line.js @@ -12,7 +12,7 @@ export function modeDrawLine(context, wayID, startGraph, button, affix, continui .on('rejectedSelfIntersection.modeDrawLine', function() { context.ui().flash .iconName('#iD-icon-no') - .label(t.html('self_intersection.error.lines'))(); + .label(t.append('self_intersection.error.lines'))(); }); mode.wayID = wayID; diff --git a/modules/modes/select.js b/modules/modes/select.js index d66d6e599..6af3acd4d 100644 --- a/modules/modes/select.js +++ b/modules/modes/select.js @@ -400,7 +400,7 @@ export function modeSelect(context, selectedIDs) { .duration(4000) .iconName('#iD-icon-no') .iconClass('operation disabled') - .label(t.html('operations.scale.' + disabled + '.' + multi))(); + .label(t.append('operations.scale.' + disabled + '.' + multi))(); } else { const pivot = context.projection(extent.center()); const annotation = t('operations.scale.annotation.' + (isUp ? 'up' : 'down') + '.feature', { n: selectedIDs.length }); diff --git a/modules/renderer/background_source.js b/modules/renderer/background_source.js index 8d406b262..e543f5004 100644 --- a/modules/renderer/background_source.js +++ b/modules/renderer/background_source.js @@ -75,13 +75,13 @@ export function rendererBackgroundSource(data) { source.label = function() { var id_safe = source.id.replace(/\./g, ''); - return t.html('imagery.' + id_safe + '.name', { default: escape(_name) }); + return t.append('imagery.' + id_safe + '.name', { default: escape(_name) }); }; source.description = function() { var id_safe = source.id.replace(/\./g, ''); - return t.html('imagery.' + id_safe + '.description', { default: escape(_description) }); + return t.append('imagery.' + id_safe + '.description', { default: escape(_description) }); }; @@ -536,7 +536,7 @@ rendererBackgroundSource.None = function() { source.label = function() { - return t.html('background.none'); + return t.append('background.none'); }; @@ -563,7 +563,7 @@ rendererBackgroundSource.Custom = function(template) { }; source.label = function() { - return t.html('background.custom'); + return t.append('background.custom'); }; diff --git a/modules/ui/commit.js b/modules/ui/commit.js index cba8e94b7..326b8202a 100644 --- a/modules/ui/commit.js +++ b/modules/ui/commit.js @@ -329,7 +329,9 @@ export function uiCommit(context) { if (!labelEnter.empty()) { labelEnter - .call(uiTooltip().title(t.html('commit.request_review_info')).placement('top')); + .call(uiTooltip() + .title(() => t.append('commit.request_review_info')) + .placement('top')); } labelEnter @@ -405,7 +407,9 @@ export function uiCommit(context) { if (uploadBlockerTooltipText) { buttonSection.selectAll('.save-button') - .call(uiTooltip().title(uploadBlockerTooltipText).placement('top')); + .call(uiTooltip() + .title(() => uploadBlockerTooltipText) + .placement('top')); } // Raw Tag Editor @@ -453,12 +457,11 @@ export function uiCommit(context) { .getIssuesBySeverity({ what: 'edited', where: 'all' }).error; if (errors.length) { - return t('commit.outstanding_errors_message', { count: errors.length }); - + return t.append('commit.outstanding_errors_message', { count: errors.length }); } else { var hasChangesetComment = context.changeset && context.changeset.tags.comment && context.changeset.tags.comment.trim().length; if (!hasChangesetComment) { - return t('commit.comment_needed_message'); + return t.append('commit.comment_needed_message'); } } return null; diff --git a/modules/ui/edit_menu.js b/modules/ui/edit_menu.js index de483b423..4b199e98a 100644 --- a/modules/ui/edit_menu.js +++ b/modules/ui/edit_menu.js @@ -105,7 +105,7 @@ export function uiEditMenu(context) { buttonsEnter.each(function(d) { var tooltip = uiTooltip() .heading(d.title) - .title(d.tooltip()) + .title(d.tooltip) .keys([d.keys[0]]); _tooltips.push(tooltip); diff --git a/modules/ui/feature_info.js b/modules/ui/feature_info.js index 522fdd67d..84f146d7c 100644 --- a/modules/ui/feature_info.js +++ b/modules/ui/feature_info.js @@ -9,18 +9,25 @@ export function uiFeatureInfo(context) { var hiddenList = features.hidden().map(function(k) { if (stats[k]) { count += stats[k]; - return t.html('inspector.title_count', { title: { html: t.html('feature.' + k + '.description') }, count: stats[k] }); + return t.append('inspector.title_count', { + title: t('feature.' + k + '.description'), + count: stats[k] + }); } return null; }).filter(Boolean); - selection.html(''); + selection.text(''); if (hiddenList.length) { var tooltipBehavior = uiTooltip() .placement('top') .title(function() { - return hiddenList.join('
'); + return selection => { + hiddenList.forEach(hiddenFeature => { + selection.append('div').call(hiddenFeature); + }) + }; }); selection.append('a') diff --git a/modules/ui/field.js b/modules/ui/field.js index 973f69728..11cff9813 100644 --- a/modules/ui/field.js +++ b/modules/ui/field.js @@ -38,7 +38,7 @@ export function uiField(context, presetField, entityIDs, options) { var _locked = false; var _lockedTip = uiTooltip() - .title(t.html('inspector.lock.suggestion', { label: field.label })) + .title(() => t.append('inspector.lock.suggestion', { label: field.label })) .placement('bottom'); diff --git a/modules/ui/fields/localized.js b/modules/ui/fields/localized.js index b59a55aa0..d86fc79c6 100644 --- a/modules/ui/fields/localized.js +++ b/modules/ui/fields/localized.js @@ -43,7 +43,7 @@ export function uiFieldLocalized(field, context) { var _selection = d3_select(null); var _multilingual = []; var _buttonTip = uiTooltip() - .title(t.html('translate.translate')) + .title(() => t.append('translate.translate')) .placement('left'); var _wikiTitles; var _entityIDs = []; diff --git a/modules/ui/flash.js b/modules/ui/flash.js index 39b04a35c..82062025c 100644 --- a/modules/ui/flash.js +++ b/modules/ui/flash.js @@ -6,7 +6,7 @@ export function uiFlash(context) { var _duration = 2000; var _iconName = '#iD-icon-no'; var _iconClass = 'disabled'; - var _label = ''; + var _label = s => s.text(''); function flash() { if (_flashTimer) { @@ -64,7 +64,7 @@ export function uiFlash(context) { content .selectAll('.flash-text') .attr('class', 'flash-text') - .html(_label); + .call(_label); _flashTimer = d3_timeout(function() { @@ -89,7 +89,11 @@ export function uiFlash(context) { flash.label = function(_) { if (!arguments.length) return _label; - _label = _; + if (typeof _ !== 'function') { + _label = selection => selection.text(_); + } else { + _label = _; + } return flash; }; diff --git a/modules/ui/geolocate.js b/modules/ui/geolocate.js index 21e4c201a..67c359592 100644 --- a/modules/ui/geolocate.js +++ b/modules/ui/geolocate.js @@ -62,7 +62,7 @@ export function uiGeolocate(context) { zoomTo(); } else { context.ui().flash - .label(t.html('geolocate.location_unavailable')) + .label(t.append('geolocate.location_unavailable')) .iconName('#iD-icon-geolocate')(); } @@ -90,7 +90,7 @@ export function uiGeolocate(context) { .call(svgIcon('#iD-icon-geolocate', 'light')) .call(uiTooltip() .placement((localizer.textDirection() === 'rtl') ? 'right' : 'left') - .title(t.html('geolocate.title')) + .title(() => t.append('geolocate.title')) .keys([t('geolocate.key')]) ); diff --git a/modules/ui/init.js b/modules/ui/init.js index 3235364a5..b857719d7 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -128,7 +128,7 @@ export function uiInit(context) { .on('hitMinZoom.ui', function() { ui.flash .iconName('#iD-icon-no') - .label(t.html('cannot_zoom'))(); + .label(t.append('cannot_zoom'))(); }); container @@ -322,7 +322,9 @@ export function uiInit(context) { .attr('href', 'https://github.com/openstreetmap/iD/issues') .attr('aria-label', t('report_a_bug')) .call(svgIcon('#iD-icon-bug', 'light')) - .call(uiTooltip().title(t.html('report_a_bug')).placement('top')); + .call(uiTooltip() + .title(() => t.append('report_a_bug')) + .placement('top')); issueLinks .append('a') @@ -330,7 +332,9 @@ export function uiInit(context) { .attr('href', 'https://github.com/openstreetmap/iD/blob/develop/CONTRIBUTING.md#translating') .attr('aria-label', t('help_translate')) .call(svgIcon('#iD-icon-translate', 'light')) - .call(uiTooltip().title(t.html('help_translate')).placement('top')); + .call(uiTooltip() + .title(() => t.append('help_translate')) + .placement('top')); aboutList .append('li') diff --git a/modules/ui/issues_info.js b/modules/ui/issues_info.js index 04f70348e..b161e7f09 100644 --- a/modules/ui/issues_info.js +++ b/modules/ui/issues_info.js @@ -62,7 +62,7 @@ export function uiIssuesInfo(context) { var tooltipBehavior = uiTooltip() .placement('top') - .title(t.html(d.descriptionID)); + .title(() => t.append(d.descriptionID)); chipSelection .call(tooltipBehavior) diff --git a/modules/ui/pane.js b/modules/ui/pane.js index 6b41fd8a8..5625835b5 100644 --- a/modules/ui/pane.js +++ b/modules/ui/pane.js @@ -72,7 +72,7 @@ export function uiPane(id, context) { if (!_paneTooltip) { _paneTooltip = uiTooltip() .placement((localizer.textDirection() === 'rtl') ? 'right' : 'left') - .title(_description) + .title(() => _description) .keys([_key]); } @@ -106,7 +106,8 @@ export function uiPane(id, context) { heading .append('h2') - .html(_label); + .text('') + .call(_label); heading .append('button') diff --git a/modules/ui/panels/background.js b/modules/ui/panels/background.js index cd167db30..6668d83a8 100644 --- a/modules/ui/panels/background.js +++ b/modules/ui/panels/background.js @@ -25,7 +25,7 @@ export function uiPanelBackground(context) { _metadata = {}; } - selection.html(''); + selection.text(''); var list = selection .append('ul') @@ -33,7 +33,7 @@ export function uiPanelBackground(context) { list .append('li') - .text(_currSourceName); + .call(_currSourceName); _metadataKeys.forEach(function(k) { // DigitalGlobe vintage is available in raster layers for now. diff --git a/modules/ui/panes/background.js b/modules/ui/panes/background.js index 9d2e65505..b041668e9 100644 --- a/modules/ui/panes/background.js +++ b/modules/ui/panes/background.js @@ -11,8 +11,8 @@ export function uiPaneBackground(context) { var backgroundPane = uiPane('background', context) .key(t('background.key')) - .label(t.html('background.title')) - .description(t.html('background.description')) + .label(t.append('background.title')) + .description(t.append('background.description')) .iconName('iD-icon-layers') .sections([ uiSectionBackgroundList(context), diff --git a/modules/ui/panes/help.js b/modules/ui/panes/help.js index 0cd0b107a..7fe8cfd4e 100644 --- a/modules/ui/panes/help.js +++ b/modules/ui/panes/help.js @@ -273,8 +273,8 @@ export function uiPaneHelp(context) { var helpPane = uiPane('help', context) .key(t('help.key')) - .label(t.html('help.title')) - .description(t.html('help.title')) + .label(t.append('help.title')) + .description(t.append('help.title')) .iconName('iD-icon-help'); helpPane.renderContent = function(content) { @@ -373,7 +373,7 @@ export function uiPaneHelp(context) { .append('li') .attr('class', 'shortcuts') .call(uiTooltip() - .title(t.html('shortcuts.tooltip')) + .title(() => t.append('shortcuts.tooltip')) .keys(['?']) .placement('top') ) diff --git a/modules/ui/panes/issues.js b/modules/ui/panes/issues.js index b2e5a1acf..3313ecf09 100644 --- a/modules/ui/panes/issues.js +++ b/modules/ui/panes/issues.js @@ -11,8 +11,8 @@ export function uiPaneIssues(context) { var issuesPane = uiPane('issues', context) .key(t('issues.key')) - .label(t.html('issues.title')) - .description(t.html('issues.title')) + .label(t.append('issues.title')) + .description(t.append('issues.title')) .iconName('iD-icon-alert') .sections([ uiSectionValidationOptions(context), diff --git a/modules/ui/panes/map_data.js b/modules/ui/panes/map_data.js index d46d8f1df..3708fbd80 100644 --- a/modules/ui/panes/map_data.js +++ b/modules/ui/panes/map_data.js @@ -11,8 +11,8 @@ export function uiPaneMapData(context) { var mapDataPane = uiPane('map-data', context) .key(t('map_data.key')) - .label(t.html('map_data.title')) - .description(t.html('map_data.description')) + .label(t.append('map_data.title')) + .description(t.append('map_data.description')) .iconName('iD-icon-data') .sections([ uiSectionDataLayers(context), diff --git a/modules/ui/panes/preferences.js b/modules/ui/panes/preferences.js index 6d7d84356..94eb5fd83 100644 --- a/modules/ui/panes/preferences.js +++ b/modules/ui/panes/preferences.js @@ -7,8 +7,8 @@ export function uiPanePreferences(context) { let preferencesPane = uiPane('preferences', context) .key(t('preferences.key')) - .label(t.html('preferences.title')) - .description(t.html('preferences.description')) + .label(t.append('preferences.title')) + .description(t.append('preferences.description')) .iconName('fas-user-cog') .sections([ uiSectionPrivacy(context) diff --git a/modules/ui/preset_list.js b/modules/ui/preset_list.js index bf449be47..f2e9100fc 100644 --- a/modules/ui/preset_list.js +++ b/modules/ui/preset_list.js @@ -466,8 +466,8 @@ export function uiPresetList(context) { if (isHiddenPreset) { var isAutoHidden = context.features().autoHidden(hiddenPresetFeaturesId); d3_select(this).call(uiTooltip() - .title(t.html('inspector.hidden_preset.' + (isAutoHidden ? 'zoom' : 'manual'), { - features: { html: t.html('feature.' + hiddenPresetFeaturesId + '.description') } + .title(() => t.append('inspector.hidden_preset.' + (isAutoHidden ? 'zoom' : 'manual'), { + features: t('feature.' + hiddenPresetFeaturesId + '.description') })) .placement(index < 2 ? 'bottom' : 'top') ); diff --git a/modules/ui/sections/background_list.js b/modules/ui/sections/background_list.js index 1fba2a690..6d51f2d0b 100644 --- a/modules/ui/sections/background_list.js +++ b/modules/ui/sections/background_list.js @@ -1,8 +1,6 @@ import _debounce from 'lodash-es/debounce'; import { descending as d3_descending, ascending as d3_ascending } from 'd3-array'; -import { - select as d3_select -} from 'd3-selection'; +import { select as d3_select } from 'd3-selection'; import { prefs } from '../../core/preferences'; import { t, localizer } from '../../core/localizer'; @@ -55,7 +53,7 @@ export function uiSectionBackgroundList(context) { .attr('class', 'minimap-toggle-item') .append('label') .call(uiTooltip() - .title(t.html('background.minimap.tooltip')) + .title(() => t.append('background.minimap.tooltip')) .keys([t('background.minimap.key')]) .placement('top') ); @@ -78,7 +76,7 @@ export function uiSectionBackgroundList(context) { .attr('class', 'background-panel-toggle-item') .append('label') .call(uiTooltip() - .title(t.html('background.panel.tooltip')) + .title(() => t.append('background.panel.tooltip')) .keys([uiCmd('⌘⇧' + t('info_panels.background.key'))]) .placement('top') ); @@ -100,7 +98,7 @@ export function uiSectionBackgroundList(context) { .attr('class', 'location-panel-toggle-item') .append('label') .call(uiTooltip() - .title(t.html('background.location_panel.tooltip')) + .title(() => t.append('background.location_panel.tooltip')) .keys([uiCmd('⌘⇧' + t('info_panels.location.key'))]) .placement('top') ); @@ -152,13 +150,13 @@ export function uiSectionBackgroundList(context) { if (d.id === previousBackgroundID()) { item.call(uiTooltip() .placement(placement) - .title('
' + t.html('background.switch') + '
') + .title(() => t.append('background.switch')) .keys([uiCmd('⌘' + t('background.key'))]) ); } else if (description || isOverflowing) { item.call(uiTooltip() .placement(placement) - .title(description || d.label()) + .title(() => description || d.label()) ); } }); @@ -202,13 +200,13 @@ export function uiSectionBackgroundList(context) { label .append('span') - .text(function(d) { return d.label(); }); + .each(function(d) { d.label()(d3_select(this)); }); enter.filter(function(d) { return d.id === 'custom'; }) .append('button') .attr('class', 'layer-browse') .call(uiTooltip() - .title(t.html('settings.custom_background.tooltip')) + .title(() => t.append('settings.custom_background.tooltip')) .placement((localizer.textDirection() === 'rtl') ? 'right' : 'left') ) .on('click', function(d3_event) { @@ -221,7 +219,7 @@ export function uiSectionBackgroundList(context) { .append('div') .attr('class', 'best') .call(uiTooltip() - .title(t.html('background.best_imagery')) + .title(() => t.append('background.best_imagery')) .placement((localizer.textDirection() === 'rtl') ? 'right' : 'left') ) .append('span') diff --git a/modules/ui/sections/data_layers.js b/modules/ui/sections/data_layers.js index da0c1830c..9580aae5a 100644 --- a/modules/ui/sections/data_layers.js +++ b/modules/ui/sections/data_layers.js @@ -95,14 +95,14 @@ export function uiSectionDataLayers(context) { if (d.id === 'osm') { d3_select(this) .call(uiTooltip() - .title(t.html('map_data.layers.' + d.id + '.tooltip')) + .title(() => t.append('map_data.layers.' + d.id + '.tooltip')) .keys([uiCmd('⌥' + t('area_fill.wireframe.key'))]) .placement('bottom') ); } else { d3_select(this) .call(uiTooltip() - .title(t.html('map_data.layers.' + d.id + '.tooltip')) + .title(() => t.append('map_data.layers.' + d.id + '.tooltip')) .placement('bottom') ); } @@ -154,7 +154,7 @@ export function uiSectionDataLayers(context) { .each(function(d) { d3_select(this) .call(uiTooltip() - .title(t.html('map_data.layers.' + d.id + '.tooltip')) + .title(() => t.append('map_data.layers.' + d.id + '.tooltip')) .placement('bottom') ); }); @@ -166,7 +166,7 @@ export function uiSectionDataLayers(context) { labelEnter .append('span') - .html(function(d) { return t.html('map_data.layers.' + d.id + '.title'); }); + .each(function(d) { t.append('map_data.layers.' + d.id + '.title')(d3_select(this)); }); // Update @@ -313,7 +313,7 @@ export function uiSectionDataLayers(context) { var labelEnter = liEnter .append('label') .call(uiTooltip() - .title(t.html('map_data.layers.custom.tooltip')) + .title(() => t.append('map_data.layers.custom.tooltip')) .placement('top') ); @@ -330,7 +330,7 @@ export function uiSectionDataLayers(context) { .append('button') .attr('class', 'open-data-options') .call(uiTooltip() - .title(t.html('settings.custom_data.tooltip')) + .title(() => t.append('settings.custom_data.tooltip')) .placement((localizer.textDirection() === 'rtl') ? 'right' : 'left') ) .on('click', function(d3_event) { @@ -343,7 +343,7 @@ export function uiSectionDataLayers(context) { .append('button') .attr('class', 'zoom-to-data') .call(uiTooltip() - .title(t.html('map_data.layers.custom.zoom')) + .title(() => t.append('map_data.layers.custom.zoom')) .placement((localizer.textDirection() === 'rtl') ? 'right' : 'left') ) .on('click', function(d3_event) { @@ -400,7 +400,7 @@ export function uiSectionDataLayers(context) { .attr('class', 'history-panel-toggle-item') .append('label') .call(uiTooltip() - .title(t.html('map_data.history_panel.tooltip')) + .title(() => t.append('map_data.history_panel.tooltip')) .keys([uiCmd('⌘⇧' + t('info_panels.history.key'))]) .placement('top') ); @@ -422,7 +422,7 @@ export function uiSectionDataLayers(context) { .attr('class', 'measurement-panel-toggle-item') .append('label') .call(uiTooltip() - .title(t.html('map_data.measurement_panel.tooltip')) + .title(() => t.append('map_data.measurement_panel.tooltip')) .keys([uiCmd('⌘⇧' + t('info_panels.measurement.key'))]) .placement('top') ); diff --git a/modules/ui/sections/feature_type.js b/modules/ui/sections/feature_type.js index 9c0c0ac6a..e4877484c 100644 --- a/modules/ui/sections/feature_type.js +++ b/modules/ui/sections/feature_type.js @@ -39,7 +39,7 @@ export function uiSectionFeatureType(context) { .append('button') .attr('class', 'preset-list-button preset-reset') .call(uiTooltip() - .title(t.html('inspector.back_tooltip')) + .title(() => t.append('inspector.back_tooltip')) .placement('bottom') ); diff --git a/modules/ui/sections/map_features.js b/modules/ui/sections/map_features.js index 5922dcbb8..ad12ec4f5 100644 --- a/modules/ui/sections/map_features.js +++ b/modules/ui/sections/map_features.js @@ -71,10 +71,13 @@ export function uiSectionMapFeatures(context) { .append('li') .call(uiTooltip() .title(function(d) { - var tip = t.html(name + '.' + d + '.tooltip'); + var tip = t.append(name + '.' + d + '.tooltip'); if (autoHiddenFeature(d)) { - var msg = showsLayer('osm') ? t.html('map_data.autohidden') : t.html('map_data.osmhidden'); - tip += '
' + msg + '
'; + var msg = showsLayer('osm') ? t.append('map_data.autohidden') : t.append('map_data.osmhidden'); + return selection => { + selection.call(tip); + selection.append('div').call(msg); + }; } return tip; }) diff --git a/modules/ui/sections/map_style_options.js b/modules/ui/sections/map_style_options.js index 8cd2d636e..eac759aa9 100644 --- a/modules/ui/sections/map_style_options.js +++ b/modules/ui/sections/map_style_options.js @@ -44,7 +44,7 @@ export function uiSectionMapStyleOptions(context) { .append('li') .call(uiTooltip() .title(function(d) { - return t.html(name + '.' + d + '.tooltip'); + return t.append(name + '.' + d + '.tooltip'); }) .keys(function(d) { var key = (d === 'wireframe' ? t('area_fill.wireframe.key') : null); diff --git a/modules/ui/sections/overlay_list.js b/modules/ui/sections/overlay_list.js index 97eb0f9d8..14640ebdc 100644 --- a/modules/ui/sections/overlay_list.js +++ b/modules/ui/sections/overlay_list.js @@ -29,7 +29,7 @@ export function uiSectionOverlayList(context) { if (description || isOverflowing) { item.call(uiTooltip() .placement(placement) - .title(description || d.name()) + .title(() => description || d.name()) ); } }); @@ -80,7 +80,7 @@ export function uiSectionOverlayList(context) { label .append('span') - .html(function(d) { return d.label(); }); + .each(function(d) { d.label()(d3_select(this)); }); layerList.selectAll('li') diff --git a/modules/ui/sections/photo_overlays.js b/modules/ui/sections/photo_overlays.js index a96233608..79930ea5a 100644 --- a/modules/ui/sections/photo_overlays.js +++ b/modules/ui/sections/photo_overlays.js @@ -77,7 +77,7 @@ export function uiSectionPhotoOverlays(context) { else titleID = d.id.replace(/-/g, '_') + '.tooltip'; d3_select(this) .call(uiTooltip() - .title(t.html(titleID)) + .title(() => t.append(titleID)) .placement('top') ); }); @@ -139,7 +139,7 @@ export function uiSectionPhotoOverlays(context) { .each(function(d) { d3_select(this) .call(uiTooltip() - .title(t.html('photo_overlays.photo_type.' + d + '.tooltip')) + .title(() => t.append('photo_overlays.photo_type.' + d + '.tooltip')) .placement('top') ); }); @@ -200,15 +200,15 @@ export function uiSectionPhotoOverlays(context) { .each(function(d) { d3_select(this) .call(uiTooltip() - .title(t.html('photo_overlays.date_filter.' + d + '.tooltip')) + .title(() => t.append('photo_overlays.date_filter.' + d + '.tooltip')) .placement('top') ); }); labelEnter .append('span') - .html(function(d) { - return t.html('photo_overlays.date_filter.' + d + '.title'); + .each(function(d) { + t.append('photo_overlays.date_filter.' + d + '.title')(d3_select(this)); }); labelEnter @@ -266,7 +266,7 @@ export function uiSectionPhotoOverlays(context) { .each(function() { d3_select(this) .call(uiTooltip() - .title(t.html('photo_overlays.username_filter.tooltip')) + .title(() => t.append('photo_overlays.username_filter.tooltip')) .placement('top') ); }); diff --git a/modules/ui/sections/privacy.js b/modules/ui/sections/privacy.js index 15780a8bb..12547555d 100644 --- a/modules/ui/sections/privacy.js +++ b/modules/ui/sections/privacy.js @@ -25,7 +25,7 @@ export function uiSectionPrivacy(context) { .attr('class', 'privacy-third-party-icons-item') .append('label') .call(uiTooltip() - .title(t.html('preferences.privacy.third_party_icons.tooltip')) + .title(() => t.append('preferences.privacy.third_party_icons.tooltip')) .placement('bottom') ); diff --git a/modules/ui/sections/raw_membership_editor.js b/modules/ui/sections/raw_membership_editor.js index 824d9a091..9f44d8d99 100644 --- a/modules/ui/sections/raw_membership_editor.js +++ b/modules/ui/sections/raw_membership_editor.js @@ -469,7 +469,9 @@ export function uiSectionRawMembershipEditor(context) { addRelationButton .call(svgIcon('#iD-icon-plus', 'light')); addRelationButton - .call(uiTooltip().title(t.html('inspector.add_to_relation')).placement(localizer.textDirection() === 'ltr' ? 'right' : 'left')); + .call(uiTooltip() + .title(() => t.append('inspector.add_to_relation')) + .placement(localizer.textDirection() === 'ltr' ? 'right' : 'left')); addRowEnter .append('div') diff --git a/modules/ui/sections/raw_tag_editor.js b/modules/ui/sections/raw_tag_editor.js index be6da5c23..6a7caba6a 100644 --- a/modules/ui/sections/raw_tag_editor.js +++ b/modules/ui/sections/raw_tag_editor.js @@ -165,7 +165,9 @@ export function uiSectionRawTagEditor(id, context) { .attr('class', 'add-tag') .attr('aria-label', t('inspector.add_to_tag')) .call(svgIcon('#iD-icon-plus', 'light')) - .call(uiTooltip().title(t.html('inspector.add_to_tag')).placement(localizer.textDirection() === 'ltr' ? 'right' : 'left')) + .call(uiTooltip() + .title(() => t.append('inspector.add_to_tag')) + .placement(localizer.textDirection() === 'ltr' ? 'right' : 'left')) .on('click', addTag); addRowEnter diff --git a/modules/ui/sections/validation_rules.js b/modules/ui/sections/validation_rules.js index 977b53a7f..6fe7f5931 100644 --- a/modules/ui/sections/validation_rules.js +++ b/modules/ui/sections/validation_rules.js @@ -87,7 +87,7 @@ export function uiSectionValidationRules(context) { if (name === 'rule') { enter .call(uiTooltip() - .title(function(d) { return t.html('issues.' + d + '.tip'); }) + .title(function(d) { return t.append('issues.' + d + '.tip'); }) .placement('top') ); } diff --git a/modules/ui/tools/modes.js b/modules/ui/tools/modes.js index 325b92aea..edaa8a7f3 100644 --- a/modules/ui/tools/modes.js +++ b/modules/ui/tools/modes.js @@ -18,28 +18,28 @@ export function uiToolDrawModes(context) { var tool = { id: 'old_modes', - label: t.html('toolbar.add_feature') + label: t.append('toolbar.add_feature') }; var modes = [ modeAddPoint(context, { - title: t.html('modes.add_point.title'), + title: t.append('modes.add_point.title'), button: 'point', - description: t.html('modes.add_point.description'), + description: t.append('modes.add_point.description'), preset: presetManager.item('point'), key: '1' }), modeAddLine(context, { - title: t.html('modes.add_line.title'), + title: t.append('modes.add_line.title'), button: 'line', - description: t.html('modes.add_line.description'), + description: t.append('modes.add_line.description'), preset: presetManager.item('line'), key: '2' }), modeAddArea(context, { - title: t.html('modes.add_area.title'), + title: t.append('modes.add_area.title'), button: 'area', - description: t.html('modes.add_area.description'), + description: t.append('modes.add_area.description'), preset: presetManager.item('area'), key: '3' }) @@ -130,7 +130,8 @@ export function uiToolDrawModes(context) { buttonsEnter .append('span') .attr('class', 'label') - .html(function(mode) { return mode.title; }); + .text('') + .each(function(mode) { mode.title(d3_select(this)); }); // if we are adding/removing the buttons, check if toolbar has overflowed if (buttons.enter().size() || buttons.exit().size()) { diff --git a/modules/ui/tools/notes.js b/modules/ui/tools/notes.js index bbb4cc325..fe5703f79 100644 --- a/modules/ui/tools/notes.js +++ b/modules/ui/tools/notes.js @@ -15,7 +15,7 @@ export function uiToolNotes(context) { var tool = { id: 'notes', - label: t.html('modes.add_note.label') + label: t.append('modes.add_note.label') }; var mode = modeAddNote(context); diff --git a/modules/ui/tools/save.js b/modules/ui/tools/save.js index 494cb9d93..5b86eab63 100644 --- a/modules/ui/tools/save.js +++ b/modules/ui/tools/save.js @@ -11,7 +11,7 @@ export function uiToolSave(context) { var tool = { id: 'save', - label: t.html('save.title') + label: t.append('save.title') }; var button = null; @@ -57,7 +57,7 @@ export function uiToolSave(context) { if (tooltipBehavior) { tooltipBehavior - .title(t.html(_numChanges > 0 ? 'save.help' : 'save.no_changes')) + .title(() => t.append(_numChanges > 0 ? 'save.help' : 'save.no_changes')) .keys([key]); } @@ -75,7 +75,7 @@ export function uiToolSave(context) { tool.render = function(selection) { tooltipBehavior = uiTooltip() .placement('bottom') - .title(t.html('save.no_changes')) + .title(() => t.append('save.no_changes')) .keys([key]) .scrollContainer(context.container().select('.top-toolbar')); @@ -99,7 +99,7 @@ export function uiToolSave(context) { .duration(2000) .iconName('#iD-icon-save') .iconClass('disabled') - .label(t.html('save.no_changes'))(); + .label(t.append('save.no_changes'))(); } lastPointerUpType = null; }) diff --git a/modules/ui/tools/sidebar_toggle.js b/modules/ui/tools/sidebar_toggle.js index d99051a91..2a1f3cde2 100644 --- a/modules/ui/tools/sidebar_toggle.js +++ b/modules/ui/tools/sidebar_toggle.js @@ -6,7 +6,7 @@ export function uiToolSidebarToggle(context) { var tool = { id: 'sidebar_toggle', - label: t.html('toolbar.inspect') + label: t.append('toolbar.inspect') }; tool.render = function(selection) { @@ -19,7 +19,7 @@ export function uiToolSidebarToggle(context) { }) .call(uiTooltip() .placement('bottom') - .title(t.html('sidebar.tooltip')) + .title(() => t.append('sidebar.tooltip')) .keys([t('sidebar.key')]) .scrollContainer(context.container().select('.top-toolbar')) ) diff --git a/modules/ui/tools/undo_redo.js b/modules/ui/tools/undo_redo.js index d8b7b4e5d..626729bbe 100644 --- a/modules/ui/tools/undo_redo.js +++ b/modules/ui/tools/undo_redo.js @@ -14,7 +14,7 @@ export function uiToolUndoRedo(context) { var tool = { id: 'undo_redo', - label: t.html('toolbar.undo_redo') + label: t.append('toolbar.undo_redo') }; var commands = [{ @@ -50,8 +50,8 @@ export function uiToolUndoRedo(context) { .placement('bottom') .title(function (d) { return d.annotation() ? - t.html(d.id + '.tooltip', { action: d.annotation() }) : - t.html(d.id + '.nothing'); + t.append(d.id + '.tooltip', { action: d.annotation() }) : + t.append(d.id + '.nothing'); }) .keys(function(d) { return [d.cmd]; @@ -84,14 +84,14 @@ export function uiToolUndoRedo(context) { ) { // there are no tooltips for touch interactions so flash feedback instead - var text = annotation ? - t.html(d.id + '.tooltip', { action: annotation }) : - t.html(d.id + '.nothing'); + var label = annotation ? + t.append(d.id + '.tooltip', { action: annotation }) : + t.append(d.id + '.nothing'); context.ui().flash .duration(2000) .iconName('#' + d.icon) .iconClass(annotation ? '' : 'disabled') - .label(text)(); + .label(label)(); } lastPointerUpType = null; }) diff --git a/modules/ui/tooltip.js b/modules/ui/tooltip.js index d5f040331..e54b508fb 100644 --- a/modules/ui/tooltip.js +++ b/modules/ui/tooltip.js @@ -45,6 +45,9 @@ export function uiTooltip(klass) { var text = _title.apply(this, arguments); var keys = _keys.apply(this, arguments); + var headingCallback = typeof heading === 'function' ? heading : s => s.text(heading); + var textCallback = typeof text === 'function' ? text : s => s.text(text); + return function(selection) { var headingSelect = selection @@ -58,7 +61,8 @@ export function uiTooltip(klass) { .append('div') .attr('class', 'tooltip-heading') .merge(headingSelect) - .html(heading); + .text('') + .call(headingCallback); var textSelect = selection .selectAll('.tooltip-text') @@ -71,7 +75,8 @@ export function uiTooltip(klass) { .append('div') .attr('class', 'tooltip-text') .merge(textSelect) - .html(text); + .text('') + .call(textCallback); var keyhintWrap = selection .selectAll('.keyhint-wrap') @@ -95,7 +100,7 @@ export function uiTooltip(klass) { .enter() .append('kbd') .attr('class', 'shortcut') - .html(function(d) { + .text(function(d) { return d; }); }; diff --git a/modules/ui/top_toolbar.js b/modules/ui/top_toolbar.js index ec66b090e..2fcaa408c 100644 --- a/modules/ui/top_toolbar.js +++ b/modules/ui/top_toolbar.js @@ -85,9 +85,7 @@ export function uiTopToolbar(context) { actionableItems .append('div') .attr('class', 'item-label') - .html(function(d) { - return d.label; - }); + .each(function(d) { d.label(d3_select(this)); }); } } diff --git a/modules/ui/version.js b/modules/ui/version.js index 1c178294c..9c26b1bd5 100644 --- a/modules/ui/version.js +++ b/modules/ui/version.js @@ -43,7 +43,7 @@ export function uiVersion(context) { .attr('href', 'https://github.com/openstreetmap/iD/blob/release/CHANGELOG.md#whats-new') .call(svgIcon('#maki-gift')) .call(uiTooltip() - .title(t.html('version.whats_new', { version: currVersion })) + .title(() => t.append('version.whats_new', { version: currVersion })) .placement('top') .scrollContainer(context.container().select('.main-footer-wrap')) ); diff --git a/modules/ui/zoom.js b/modules/ui/zoom.js index 9a4eea629..f707e850c 100644 --- a/modules/ui/zoom.js +++ b/modules/ui/zoom.js @@ -14,22 +14,22 @@ export function uiZoom(context) { var zooms = [{ id: 'zoom-in', icon: 'iD-icon-plus', - title: t.html('zoom.in'), + title: t.append('zoom.in'), action: zoomIn, disabled: function() { return !context.map().canZoomIn(); }, - disabledTitle: t.html('zoom.disabled.in'), + disabledTitle: t.append('zoom.disabled.in'), key: '+' }, { id: 'zoom-out', icon: 'iD-icon-minus', - title: t.html('zoom.out'), + title: t.append('zoom.out'), action: zoomOut, disabled: function() { return !context.map().canZoomOut(); }, - disabledTitle: t.html('zoom.disabled.out'), + disabledTitle: t.append('zoom.disabled.out'), key: '-' }]; diff --git a/modules/ui/zoom_to_selection.js b/modules/ui/zoom_to_selection.js index 5913295a2..39f26584c 100644 --- a/modules/ui/zoom_to_selection.js +++ b/modules/ui/zoom_to_selection.js @@ -24,7 +24,7 @@ export function uiZoomToSelection(context) { .duration(2000) .iconName('#iD-icon-framed-dot') .iconClass('disabled') - .label(t.html('inspector.zoom_to.no_selection'))(); + .label(t.append('inspector.zoom_to.no_selection'))(); } } else { var mode = context.mode(); @@ -42,9 +42,9 @@ export function uiZoomToSelection(context) { .placement((localizer.textDirection() === 'rtl') ? 'right' : 'left') .title(function() { if (isDisabled()) { - return t.html('inspector.zoom_to.no_selection'); + return t.append('inspector.zoom_to.no_selection'); } - return t.html('inspector.zoom_to.title'); + return t.append('inspector.zoom_to.title'); }) .keys([t('inspector.zoom_to.key')]);