From 34a6382752bc95fb7689e181022b3bc73a754238 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Tue, 26 Apr 2016 17:41:35 -0700 Subject: [PATCH 1/7] revised RTL features and detection --- css/app.css | 284 +++++++++++++++++++++++++++++++++++- modules/ui/entity_editor.js | 2 +- modules/ui/init.js | 6 + modules/ui/preset_list.js | 2 +- 4 files changed, 290 insertions(+), 4 deletions(-) diff --git a/css/app.css b/css/app.css index 6a7c9a920..5ad787b69 100644 --- a/css/app.css +++ b/css/app.css @@ -3318,8 +3318,6 @@ img.tile-removing { margin: auto; } -/* Mapillary -------------------------------------------------------- */ .mapillary-wrap { position: absolute; bottom: 30px; @@ -3357,4 +3355,286 @@ img.tile-removing { .mly-wrapper.active { visibility: visible; + +/* Right-to-left localization settings */ + +/* sidebar */ +[dir='rtl'] #sidebar { + float: right; +} + +#sidebar .search-header .icon { + left: auto; + right: 10px; +} + +/* header */ +[dir='rtl'] .header h3 { + text-align: right; + padding: 20px 40px 20px 20px; +} + +[dir='rtl'] .entity-editor-pane .header button.preset-choose { + left: auto; + right: 0; +} + +[dir='rtl'] .entity-editor-pane .header button.preset-close, [dir='rtl'] .preset-list-pane .header button.preset-choose { + left: 0; + right: auto; +} + +[dir='rtl'] .map-data-control .layer-list button, [dir='rtl'] .background-control .layer-list button { + float: left; + border-left: none; + border-right: 1px solid #CCC; +} + +[dir='rtl'] .map-data-control .layer-list button:first-of-type, [dir='rtl'] .background-control .layer-list button:first-of-type { + border-radius: 3px 0 0 3px; +} + +/* preset form */ +[dir='rtl'] .form-label { + padding: 5px 10px 5px 0; +} + +[dir='rtl'] .form-label button { + border-left: none; + border-right: 1px solid #CCC; +} + +[dir='rtl'] .more-fields label { + padding: 5px 0 5px 10px; +} + +[dir='rtl'] .form-label-button-wrap { + text-align: left; +} + +[dir='rtl'] button.minor { + left: 0; + right: auto; +} + +[dir='rtl'] .form-field .localized-main { + padding-left: 10%; + padding-right: 10px; +} + +[dir='rtl'] .combobox-caret { + margin-left: 0; + margin-right: -30px; +} + +[dir='rtl'] .form-field .button-input-action { + margin-left: 0; + margin-right: -10%; +} + +[dir='rtl'] .icon.pre-text { + margin-left: 3px; + margin-right: 0; +} + +[dir='rtl'] .notice .zoom-to .icon { + margin-left: 10px; + margin-right: 0; +} + +[dir='rtl'] .preset-list-button .label { + text-align: right; + left: 0; + right: 60px; + border-left: none; + border-right: 1px solid rgba(0, 0, 0, .1); + border-radius: 3px 0 0 3px; +} + +[dir='rtl'] .preset-icon-frame { + left: auto; + right: 7px; +} + +[dir='rtl'] .preset-list-item button.tag-reference-button { + left: 0; + right: auto; + border-radius: 3px 0 0 3px; +} + +[dir='rtl'] .preset-list-button-wrap .preset-icon { + left: auto; + right: auto; +} + +[dir='rtl'] .preset-list-button-wrap .preset-icon-32 { + right: 13px; +} + +[dir='rtl'] .form-field .maxspeed-unit { + border-radius: 0 0 0 4px; +} + +[dir='rtl'] input[type="checkbox"], [dir='rtl'] input[type="radio"] { + float: right; + margin-left: 5px; + margin-right: 0; +} + +[dir='rtl'] .preset-input-wrap .col6 { + float: right; +} + +/* tags form */ +[dir='rtl'] .tag-row .key-wrap, [dir='rtl'] .tag-row .input-wrap-position { + float: right; +} + +[dir='rtl'] .tag-row input { + border-left: none; + border-right: 1px solid #CCC; +} + +[dir='rtl'] .tag-row:first-child input.key { + border-top-left-radius: 0; + border-top-right-radius: 4px; +} + +[dir='rtl'] .tag-row button { + left: 10%; + border-left-width: 1px; +} + +[dir='rtl'] .tag-row .tag-reference-button { + left: auto; + right: auto; + margin-right: 35px; + border-left-width: 1px; + border-right-width: 0; +} + +[dir='rtl'] .tag-row:first-child .tag-reference-button { + border-top-left-radius: 4px; + border-top-right-radius: 0; +} + +[dir='rtl'] .tag-row:last-child .tag-reference-button { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 0; +} + +/* map control buttons */ +[dir='rtl'] .map-controls { + left: 0; + right: auto; +} + +[dir='rtl'] .background-control button, [dir='rtl'] .zoombuttons button.zoom-in { + border-radius: 0 4px 0 0; +} + +[dir='rtl'] .help-control button, [dir='rtl'] .geolocate-control button { + border-radius: 0 0 4px 0; +} + +/* map control button overlays */ +[dir='rtl'] .map-overlay { + padding: 20px 20px 20px 50px; + left: 0; + right: auto !important; +} + +[dir='rtl'] .opacity-options { + left: 50px; + right: auto; +} + +[dir='rtl'] .hide-toggle { + padding-left: 0; + padding-right: 12px; +} + +[dir='rtl'] .hide-toggle:before { + left: auto; + right: 0; + border-left: none; + border-right: 8px solid #7092ff; +} + +[dir='rtl'] .hide-toggle.expanded:before { + border-left: 4px solid transparent; + border-right: 4px solid transparent; +} + +/* navbar */ +[dir='rtl'] #bar .spacer, [dir='rtl'] #bar .button-wrap, [dir='rtl'] #bar .button-wrap button { + float: right; +} + +[dir='rtl'] .add-point .tooltip { + left: inherit !important; +} + +[dir='rtl'] .button-wrap:last-of-type { + padding-left: 0; + padding-right: 10px; +} + +[dir='rtl'] button.save.has-count .count { + margin-left: auto; + margin-right: 8%; +} + +[dir='rtl'] button.save.has-count .count::before { + border-left: 6px solid rgba(255,255,255,.5); + border-right: none; + left: auto; + right: -6px; +} + +[dir='rtl'] .joined button { + border-left: 1px solid rgba(0,0,0,.5); + border-right: none; +} + +[dir='rtl'] .joined button:first-child { + border-radius: 0 4px 4px 0; +} + +[dir='rtl'] .joined button:last-child { + border-radius: 4px 0 0 4px; +} + +/* footer */ +[dir='rtl'] #scale-block { + float: right; + clear: right; +} + +[dir='rtl'] #info-block { + clear: left; +} + +[dir='rtl'] #about-list { + text-align: left; + clear: left; + margin-left: 10px; + margin-right: 0; +} + +[dir='rtl'] #about-list li { + float: left; + border-left: none; + border-right: 1px solid rgba(255,255,255,.5); + margin-left: 0; + margin-right: 5px; + padding: 5px 5px 5px 0; +} + +[dir='rtl'] #about-list li:last-child { + border-right: none; +} + +[dir='rtl'] #scale text { + text-anchor: end; } diff --git a/modules/ui/entity_editor.js b/modules/ui/entity_editor.js index 5e7ded85f..c6a7c2877 100644 --- a/modules/ui/entity_editor.js +++ b/modules/ui/entity_editor.js @@ -46,7 +46,7 @@ export function uiEntityEditor(context) { .attr('class', 'fl preset-reset preset-choose') .on('click', function() { dispatch.call('choose', this, activePreset); }) .append('span') - .html('◄'); + .html((iD.detect().textDirection === 'rtl') ? '►' : '◄'); enter .append('button') diff --git a/modules/ui/init.js b/modules/ui/init.js index c5d7f11fb..613cbde9f 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -73,8 +73,13 @@ export function uiInit(context) { content .append('div') .attr('id', 'map') + .attr('dir', 'auto') .call(map); + if (iD.detect().textDirection === 'rtl') { + d3.select('body').attr('dir', 'rtl'); + } + content .call(uiMapInMap(context)); @@ -150,6 +155,7 @@ export function uiInit(context) { about .append('div') .attr('id', 'attrib') + .attr('dir', 'ltr') .call(uiAttribution(context)); var footer = about diff --git a/modules/ui/preset_list.js b/modules/ui/preset_list.js index cf879143e..a5f609f1c 100644 --- a/modules/ui/preset_list.js +++ b/modules/ui/preset_list.js @@ -44,7 +44,7 @@ export function uiPresetList(context) { .attr('class', 'preset-choose') .on('click', function() { dispatch.call('choose', this, currentPreset); }) .append('span') - .html('►'); + .html((iD.detect().textDirection === 'rtl') ? '◄' : '►'); } else { messagewrap .append('button') From a9ee42bd9471675638f5b573ad5ae514338902d2 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Fri, 6 May 2016 11:44:22 -0400 Subject: [PATCH 2/7] undo and redo buttons --- modules/ui/background.js | 4 +++- modules/ui/preset.js | 4 +++- modules/ui/undo_redo.js | 17 ++++++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/modules/ui/background.js b/modules/ui/background.js index 5334ea955..8c2cbea91 100644 --- a/modules/ui/background.js +++ b/modules/ui/background.js @@ -497,7 +497,9 @@ export function uiBackground(context) { .attr('title', t('background.reset')) .attr('class', 'nudge-reset disabled') .on('click', resetOffset) - .call(svgIcon('#icon-undo')); + .call( + (iD.detect().textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') + ); context.map() .on('move.background-update', _.debounce(update, 1000)); diff --git a/modules/ui/preset.js b/modules/ui/preset.js index cb68ee169..e581950af 100644 --- a/modules/ui/preset.js +++ b/modules/ui/preset.js @@ -160,7 +160,9 @@ export function uiPreset(context) { wrap.append('button') .attr('class', 'modified-icon') .attr('tabindex', -1) - .call(svgIcon('#icon-undo')); + .call( + (iD.detect().textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') + ); // Update diff --git a/modules/ui/undo_redo.js b/modules/ui/undo_redo.js index ed2dd0643..86a217fa6 100644 --- a/modules/ui/undo_redo.js +++ b/modules/ui/undo_redo.js @@ -44,11 +44,18 @@ export function uiUndoRedo(context) { .on('click', function(d) { return d.action(); }) .call(tooltipBehavior); - buttons - .each(function(d) { - d3.select(this) - .call(svgIcon('#icon-' + d.id)); - }); + buttons.each(function(d) { + var iconName = d.id; + if (iD.detect().textDirection === 'rtl') { + if (iconName === 'undo') { + iconName = 'redo'; + } else if (iconName === 'redo') { + iconName = 'undo'; + } + } + d3.select(this) + .call(svgIcon('#icon-' + iconName)); + }); var keybinding = d3keybinding('undo') .on(commands[0].cmd, function() { d3.event.preventDefault(); commands[0].action(); }) From 6bc9e63fc3fd00c86a52cb1c827d32d4023e5547 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Fri, 6 May 2016 12:20:56 -0400 Subject: [PATCH 3/7] map controls and menus --- css/app.css | 4 ++++ modules/ui/background.js | 8 ++++---- modules/ui/geolocate.js | 3 ++- modules/ui/help.js | 2 +- modules/ui/map_data.js | 6 +++--- modules/ui/zoom.js | 2 +- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/css/app.css b/css/app.css index 5ad787b69..e1bd3e7f0 100644 --- a/css/app.css +++ b/css/app.css @@ -3537,6 +3537,10 @@ img.tile-removing { border-radius: 0 0 4px 0; } +[dir='rtl'] .geolocate-control button svg, [dir='rtl'] .list-item-gpx-browse svg { + transform: rotateY(180deg); +} + /* map control button overlays */ [dir='rtl'] .map-overlay { padding: 20px 20px 20px 50px; diff --git a/modules/ui/background.js b/modules/ui/background.js index 8c2cbea91..335bc19c8 100644 --- a/modules/ui/background.js +++ b/modules/ui/background.js @@ -150,7 +150,7 @@ export function uiBackground(context) { .attr('class', 'best') .call(tooltip() .title(t('background.best_imagery')) - .placement('left')) + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) .append('span') .html('★'); @@ -337,7 +337,7 @@ export function uiBackground(context) { var content = selection.append('div') .attr('class', 'fillL map-overlay col3 content hide'), tooltipBehavior = tooltip() - .placement('left') + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(uiTooltipHtml(t('background.description'), key)), button = selection.append('button') @@ -369,7 +369,7 @@ export function uiBackground(context) { .on('click.set-opacity', setOpacity) .html('
') .call(tooltip() - .placement('left')) + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) .append('div') .attr('class', 'opacity') .style('opacity', function(d) { return 1.25 - d; }); @@ -388,7 +388,7 @@ export function uiBackground(context) { .attr('class', 'layer-browse') .call(tooltip() .title(t('background.custom_button')) - .placement('left')) + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) .on('click', editCustom) .call(svgIcon('#icon-search')); diff --git a/modules/ui/geolocate.js b/modules/ui/geolocate.js index 61e4d7d8f..0ae5d7723 100644 --- a/modules/ui/geolocate.js +++ b/modules/ui/geolocate.js @@ -54,6 +54,7 @@ export function uiGeolocate(context) { .attr('title', t('geolocate.title')) .on('click', click) .call(svgIcon('#icon-geolocate', 'light')) - .call(tooltip().placement('left')); + .call(tooltip() + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')); }; } diff --git a/modules/ui/help.js b/modules/ui/help.js index 1961880f5..781d79747 100644 --- a/modules/ui/help.js +++ b/modules/ui/help.js @@ -113,7 +113,7 @@ export function uiHelp(context) { var pane = selection.append('div') .attr('class', 'help-wrap map-overlay fillL col5 content hide'), tooltipBehavior = tooltip() - .placement('left') + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(uiTooltipHtml(t('help.title'), key)), button = selection.append('button') diff --git a/modules/ui/map_data.js b/modules/ui/map_data.js index f5efc3192..3bf74cadf 100644 --- a/modules/ui/map_data.js +++ b/modules/ui/map_data.js @@ -216,7 +216,7 @@ export function uiMapData(context) { .attr('class', 'list-item-gpx-extent') .call(tooltip() .title(t('gpx.zoom')) - .placement('left')) + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) .on('click', function() { d3.event.preventDefault(); d3.event.stopPropagation(); @@ -229,7 +229,7 @@ export function uiMapData(context) { .attr('class', 'list-item-gpx-browse') .call(tooltip() .title(t('gpx.browse')) - .placement('left')) + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) .on('click', function() { d3.select(document.createElement('input')) .attr('type', 'file') @@ -388,7 +388,7 @@ export function uiMapData(context) { .append('div') .attr('class', 'fillL map-overlay col3 content hide'), tooltipBehavior = tooltip() - .placement('left') + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(uiTooltipHtml(t('map_data.description'), key)), button = selection diff --git a/modules/ui/zoom.js b/modules/ui/zoom.js index c8fe72ea0..88af3b7f0 100644 --- a/modules/ui/zoom.js +++ b/modules/ui/zoom.js @@ -57,7 +57,7 @@ export function uiZoom(context) { .attr('class', function(d) { return d.id; }) .on('click.editor', function(d) { d.action(); }) .call(tooltip() - .placement('left') + .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(function(d) { return uiTooltipHtml(d.title, d.key); From e208300ca5a88158450143b7fac12eb0cfa7f91c Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Fri, 6 May 2016 15:22:59 -0400 Subject: [PATCH 4/7] fix mouse position calculation on RTL layout --- css/app.css | 5 +++++ modules/util/util.js | 3 +++ 2 files changed, 8 insertions(+) diff --git a/css/app.css b/css/app.css index e1bd3e7f0..ddf5f2ea9 100644 --- a/css/app.css +++ b/css/app.css @@ -3384,6 +3384,11 @@ img.tile-removing { right: auto; } +[dir='rtl'] .preset-icon-fill-area { + left: auto; + right: 10px; +} + [dir='rtl'] .map-data-control .layer-list button, [dir='rtl'] .background-control .layer-list button { float: left; border-left: none; diff --git a/modules/util/util.js b/modules/util/util.js index 3178425a1..7154dca4b 100644 --- a/modules/util/util.js +++ b/modules/util/util.js @@ -174,6 +174,9 @@ export function utilFastMouse(container) { rectTop = rect.top, clientLeft = +container.clientLeft, clientTop = +container.clientTop; + if (iD.detect().textDirection === 'rtl') { + rectLeft = 0; + } return function(e) { return [ e.clientX - rectLeft - clientLeft, From 581bade5f3a8e678e5f4a5d6fed336b6bcee7d22 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Thu, 22 Sep 2016 14:20:00 -0400 Subject: [PATCH 5/7] update RTL detection --- css/app.css | 6 +++--- modules/ui/background.js | 12 ++++++------ modules/ui/entity_editor.js | 4 ++-- modules/ui/geolocate.js | 4 ++-- modules/ui/help.js | 4 ++-- modules/ui/init.js | 8 ++++---- modules/ui/map_data.js | 8 ++++---- modules/ui/preset.js | 4 ++-- modules/ui/preset_list.js | 4 ++-- modules/ui/undo_redo.js | 14 +++++++------- modules/ui/zoom.js | 4 ++-- modules/util/detect.js | 9 ++++++++- modules/util/locale.js | 11 +++++++++++ modules/util/util.js | 6 +++--- 14 files changed, 58 insertions(+), 40 deletions(-) diff --git a/css/app.css b/css/app.css index ddf5f2ea9..6c249f500 100644 --- a/css/app.css +++ b/css/app.css @@ -3355,15 +3355,15 @@ img.tile-removing { .mly-wrapper.active { visibility: visible; +} /* Right-to-left localization settings */ -/* sidebar */ [dir='rtl'] #sidebar { float: right; } -#sidebar .search-header .icon { +[dir='rtl'] #sidebar .search-header .icon { left: auto; right: 10px; } @@ -3542,7 +3542,7 @@ img.tile-removing { border-radius: 0 0 4px 0; } -[dir='rtl'] .geolocate-control button svg, [dir='rtl'] .list-item-gpx-browse svg { +[dir='rtl'] .list-item-gpx-browse svg { transform: rotateY(180deg); } diff --git a/modules/ui/background.js b/modules/ui/background.js index 335bc19c8..35a49f30b 100644 --- a/modules/ui/background.js +++ b/modules/ui/background.js @@ -1,7 +1,7 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { d3keybinding } from '../lib/d3.keybinding.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { rendererBackgroundSource } from '../renderer/index'; import { geoMetersToOffset, geoOffsetToMeters } from '../geo/index'; import { utilDetect } from '../util/detect'; @@ -150,7 +150,7 @@ export function uiBackground(context) { .attr('class', 'best') .call(tooltip() .title(t('background.best_imagery')) - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) + .placement((textDirection === 'rtl') ? 'right' : 'left')) .append('span') .html('★'); @@ -337,7 +337,7 @@ export function uiBackground(context) { var content = selection.append('div') .attr('class', 'fillL map-overlay col3 content hide'), tooltipBehavior = tooltip() - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') + .placement((textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(uiTooltipHtml(t('background.description'), key)), button = selection.append('button') @@ -369,7 +369,7 @@ export function uiBackground(context) { .on('click.set-opacity', setOpacity) .html('
') .call(tooltip() - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) + .placement((textDirection === 'rtl') ? 'right' : 'left')) .append('div') .attr('class', 'opacity') .style('opacity', function(d) { return 1.25 - d; }); @@ -388,7 +388,7 @@ export function uiBackground(context) { .attr('class', 'layer-browse') .call(tooltip() .title(t('background.custom_button')) - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) + .placement((textDirection === 'rtl') ? 'right' : 'left')) .on('click', editCustom) .call(svgIcon('#icon-search')); @@ -498,7 +498,7 @@ export function uiBackground(context) { .attr('class', 'nudge-reset disabled') .on('click', resetOffset) .call( - (iD.detect().textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') + (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') ); context.map() diff --git a/modules/ui/entity_editor.js b/modules/ui/entity_editor.js index c6a7c2877..a57dffab6 100644 --- a/modules/ui/entity_editor.js +++ b/modules/ui/entity_editor.js @@ -1,6 +1,6 @@ import * as d3 from 'd3'; import _ from 'lodash'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { tooltip } from '../util/tooltip'; import { actionChangeTags } from '../actions/index'; import { modeBrowse } from '../modes/index'; @@ -46,7 +46,7 @@ export function uiEntityEditor(context) { .attr('class', 'fl preset-reset preset-choose') .on('click', function() { dispatch.call('choose', this, activePreset); }) .append('span') - .html((iD.detect().textDirection === 'rtl') ? '►' : '◄'); + .html((textDirection === 'rtl') ? '►' : '◄'); enter .append('button') diff --git a/modules/ui/geolocate.js b/modules/ui/geolocate.js index 0ae5d7723..b552a7cf8 100644 --- a/modules/ui/geolocate.js +++ b/modules/ui/geolocate.js @@ -1,4 +1,4 @@ -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { tooltip } from '../util/tooltip'; import { modeBrowse } from '../modes/index'; import { geoExtent } from '../geo/index'; @@ -55,6 +55,6 @@ export function uiGeolocate(context) { .on('click', click) .call(svgIcon('#icon-geolocate', 'light')) .call(tooltip() - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')); + .placement((textDirection === 'rtl') ? 'right' : 'left')); }; } diff --git a/modules/ui/help.js b/modules/ui/help.js index 781d79747..10094e9a6 100644 --- a/modules/ui/help.js +++ b/modules/ui/help.js @@ -1,7 +1,7 @@ import * as d3 from 'd3'; import marked from 'marked'; import { d3keybinding } from '../lib/d3.keybinding.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { svgIcon } from '../svg/index'; import { uiIntro } from './intro/index'; import { uiTooltipHtml } from './tooltipHtml'; @@ -113,7 +113,7 @@ export function uiHelp(context) { var pane = selection.append('div') .attr('class', 'help-wrap map-overlay fillL col5 content hide'), tooltipBehavior = tooltip() - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') + .placement((textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(uiTooltipHtml(t('help.title'), key)), button = selection.append('button') diff --git a/modules/ui/init.js b/modules/ui/init.js index 613cbde9f..3613c01bb 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -1,6 +1,6 @@ import * as d3 from 'd3'; import { d3keybinding } from '../lib/d3.keybinding.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { tooltip } from '../util/tooltip'; import { utilDetect } from '../util/detect'; import { utilSetDimensions } from '../util/dimensions'; @@ -73,11 +73,11 @@ export function uiInit(context) { content .append('div') .attr('id', 'map') - .attr('dir', 'auto') + .attr('dir', 'ltr') .call(map); - if (iD.detect().textDirection === 'rtl') { - d3.select('body').attr('dir', 'rtl'); + if (textDirection === 'rtl') { + d3.select('body').attr('dir', 'rtl'); } content diff --git a/modules/ui/map_data.js b/modules/ui/map_data.js index 3bf74cadf..4193a24aa 100644 --- a/modules/ui/map_data.js +++ b/modules/ui/map_data.js @@ -1,7 +1,7 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { d3keybinding } from '../lib/d3.keybinding.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { svgIcon } from '../svg/index'; import { uiTooltipHtml } from './tooltipHtml'; import { tooltip } from '../util/tooltip'; @@ -216,7 +216,7 @@ export function uiMapData(context) { .attr('class', 'list-item-gpx-extent') .call(tooltip() .title(t('gpx.zoom')) - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) + .placement((textDirection === 'rtl') ? 'right' : 'left')) .on('click', function() { d3.event.preventDefault(); d3.event.stopPropagation(); @@ -229,7 +229,7 @@ export function uiMapData(context) { .attr('class', 'list-item-gpx-browse') .call(tooltip() .title(t('gpx.browse')) - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left')) + .placement((textDirection === 'rtl') ? 'right' : 'left')) .on('click', function() { d3.select(document.createElement('input')) .attr('type', 'file') @@ -388,7 +388,7 @@ export function uiMapData(context) { .append('div') .attr('class', 'fillL map-overlay col3 content hide'), tooltipBehavior = tooltip() - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') + .placement((textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(uiTooltipHtml(t('map_data.description'), key)), button = selection diff --git a/modules/ui/preset.js b/modules/ui/preset.js index e581950af..8bf2c1101 100644 --- a/modules/ui/preset.js +++ b/modules/ui/preset.js @@ -1,7 +1,7 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { d3combobox } from '../lib/d3.combobox.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { modeBrowse } from '../modes/index'; import { svgIcon } from '../svg/index'; import { uiDisclosure } from './disclosure'; @@ -161,7 +161,7 @@ export function uiPreset(context) { .attr('class', 'modified-icon') .attr('tabindex', -1) .call( - (iD.detect().textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') + (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo') ); diff --git a/modules/ui/preset_list.js b/modules/ui/preset_list.js index a5f609f1c..d411b83ec 100644 --- a/modules/ui/preset_list.js +++ b/modules/ui/preset_list.js @@ -1,7 +1,7 @@ import * as d3 from 'd3'; import { utilRebind } from '../util/rebind'; import { d3keybinding } from '../lib/d3.keybinding.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { actionChangePreset } from '../actions/index'; import { operationDelete } from '../operations/index'; import { modeBrowse } from '../modes/index'; @@ -44,7 +44,7 @@ export function uiPresetList(context) { .attr('class', 'preset-choose') .on('click', function() { dispatch.call('choose', this, currentPreset); }) .append('span') - .html((iD.detect().textDirection === 'rtl') ? '◄' : '►'); + .html((textDirection === 'rtl') ? '◄' : '►'); } else { messagewrap .append('button') diff --git a/modules/ui/undo_redo.js b/modules/ui/undo_redo.js index 86a217fa6..c0f4cdf8a 100644 --- a/modules/ui/undo_redo.js +++ b/modules/ui/undo_redo.js @@ -1,6 +1,6 @@ import * as d3 from 'd3'; import { d3keybinding } from '../lib/d3.keybinding.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { svgIcon } from '../svg/index'; import { uiCmd } from './cmd'; import { uiTooltipHtml } from './tooltipHtml'; @@ -46,12 +46,12 @@ export function uiUndoRedo(context) { buttons.each(function(d) { var iconName = d.id; - if (iD.detect().textDirection === 'rtl') { - if (iconName === 'undo') { - iconName = 'redo'; - } else if (iconName === 'redo') { - iconName = 'undo'; - } + if (textDirection === 'rtl') { + if (iconName === 'undo') { + iconName = 'redo'; + } else if (iconName === 'redo') { + iconName = 'undo'; + } } d3.select(this) .call(svgIcon('#icon-' + iconName)); diff --git a/modules/ui/zoom.js b/modules/ui/zoom.js index 88af3b7f0..ae0527693 100644 --- a/modules/ui/zoom.js +++ b/modules/ui/zoom.js @@ -1,7 +1,7 @@ import * as d3 from 'd3'; import _ from 'lodash'; import { d3keybinding } from '../lib/d3.keybinding.js'; -import { t } from '../util/locale'; +import { t, textDirection } from '../util/locale'; import { svgIcon } from '../svg/index'; import { uiCmd } from './cmd'; import { uiTooltipHtml } from './tooltipHtml'; @@ -57,7 +57,7 @@ export function uiZoom(context) { .attr('class', function(d) { return d.id; }) .on('click.editor', function(d) { d.action(); }) .call(tooltip() - .placement((iD.detect().textDirection === 'rtl') ? 'right' : 'left') + .placement((textDirection === 'rtl') ? 'right' : 'left') .html(true) .title(function(d) { return uiTooltipHtml(d.title, d.key); diff --git a/modules/util/detect.js b/modules/util/detect.js index ae6bc58e1..a208cf1b9 100644 --- a/modules/util/detect.js +++ b/modules/util/detect.js @@ -1,4 +1,4 @@ -import { currentLocale } from './locale'; +import { currentLocale, setTextDirection } from './locale'; export function utilDetect() { var detected = {}; @@ -64,6 +64,13 @@ export function utilDetect() { detected.locale = loadedLocale; } + if (['ar', 'fa', 'iw', 'dv'].indexOf(detected.locale.split('-')[0]) > -1 || window.location.href.indexOf('rtl-test-rtl') > -1) { + detected.textDirection = 'rtl'; + } else { + detected.textDirection = 'ltr'; + } + setTextDirection(detected.textDirection); + detected.host = window.location && (window.location.origin + window.location.pathname); detected.filedrop = (window.FileReader && 'ondrop' in window); diff --git a/modules/util/locale.js b/modules/util/locale.js index da0b65a1c..c8eef85d1 100644 --- a/modules/util/locale.js +++ b/modules/util/locale.js @@ -1,6 +1,7 @@ var translations = Object.create(null); export var currentLocale = 'en'; +export var textDirection = 'ltr'; export function setLocale(_) { if (translations[_] !== undefined) { @@ -47,3 +48,13 @@ export function t(s, o, loc) { return missing; } + +/** + * Given string 'ltr' or 'rtl', save that setting + * + * @param {string} s ltr or rtl + */ + +export function setTextDirection(dir) { + textDirection = dir; +} diff --git a/modules/util/util.js b/modules/util/util.js index 7154dca4b..27c1e9c90 100644 --- a/modules/util/util.js +++ b/modules/util/util.js @@ -1,6 +1,6 @@ import * as d3 from 'd3'; import _ from 'lodash'; -import { t } from './locale'; +import { t, textDirection } from './locale'; import { utilDetect } from './detect'; import { remove as removeDiacritics } from 'diacritics'; @@ -174,8 +174,8 @@ export function utilFastMouse(container) { rectTop = rect.top, clientLeft = +container.clientLeft, clientTop = +container.clientTop; - if (iD.detect().textDirection === 'rtl') { - rectLeft = 0; + if (textDirection === 'rtl') { + rectLeft = 0; } return function(e) { return [ From 35976a1fb60567237861c0022fd71870c28d880a Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Fri, 23 Sep 2016 12:49:02 -0400 Subject: [PATCH 6/7] increment/decrement control fix by Naoufel Razouane --- css/app.css | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/css/app.css b/css/app.css index 6c249f500..5b35b582c 100644 --- a/css/app.css +++ b/css/app.css @@ -3647,3 +3647,20 @@ img.tile-removing { [dir='rtl'] #scale text { text-anchor: end; } + +/* increment / decrement control - code by Naoufel Razouane */ + +[dir='rtl'] .spin-control{ + margin-left: 0; + margin-right: -20%; +} +[dir='rtl'] .spin-control button{ + border-left: 0; + border-right: 1px solid #CCC; +} +[dir='rtl'] .spin-control button.decrement{ + border-bottom-right-radius: 0; +} +[dir='rtl'] .spin-control button.increment{ + border-bottom-left-radius: 3px; +} From c22867c2790fd4b2c70fef5ccc250cfc601f3077 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Sun, 2 Oct 2016 19:45:45 -0400 Subject: [PATCH 7/7] search results and layer names --- css/app.css | 10 ++++++++++ modules/ui/background.js | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/css/app.css b/css/app.css index 5b35b582c..ac0a93847 100644 --- a/css/app.css +++ b/css/app.css @@ -3399,6 +3399,16 @@ img.tile-removing { border-radius: 3px 0 0 3px; } +/* search */ +[dir='rtl'] .feature-list-item .label { + text-align: right; +} + +[dir='rtl'] .feature-list-item .entity-name { + padding-left: 0; + padding-right: 10px; +} + /* preset form */ [dir='rtl'] .form-label { padding: 5px 10px 5px 0; diff --git a/modules/ui/background.js b/modules/ui/background.js index 35a49f30b..feb8db766 100644 --- a/modules/ui/background.js +++ b/modules/ui/background.js @@ -378,7 +378,8 @@ export function uiBackground(context) { /* background switcher */ var backgroundList = content.append('ul') - .attr('class', 'layer-list'); + .attr('class', 'layer-list') + .attr('dir', 'auto'); var custom = backgroundList.append('li') .attr('class', 'custom_layer')