From 34cdab91979d4df96bb9be6dfe9ac0057d4c36a3 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Mon, 27 Nov 2017 17:13:57 -0500 Subject: [PATCH] uiDisclosure now handles expanded state in localStorage Now all the places that use a uiDisclosure won't have to do that --- modules/ui/background_offset.js | 16 +--- modules/ui/commit.js | 1 - modules/ui/disclosure.js | 48 +++++++----- modules/ui/preset_editor.js | 10 +-- modules/ui/raw_member_editor.js | 24 +++--- modules/ui/raw_membership_editor.js | 53 ++++++------- modules/ui/raw_tag_editor.js | 114 ++++++++++++++-------------- 7 files changed, 124 insertions(+), 142 deletions(-) diff --git a/modules/ui/background_offset.js b/modules/ui/background_offset.js index 0d9c1f683..295557de2 100644 --- a/modules/ui/background_offset.js +++ b/modules/ui/background_offset.js @@ -11,7 +11,6 @@ import { uiDisclosure } from './disclosure'; export function uiBackgroundOffset(context) { - var expandedPreference = (context.storage('background_offset.expanded') !== 'false'); var directions = [ ['right', [0.5, 0]], ['top', [0, -0.5]], @@ -153,11 +152,7 @@ export function uiBackgroundOffset(context) { .append('div') .attr('class', 'nudge-inner-rect') .append('input') - .on('change', inputOffset) - .on('mousedown', function() { - if (d3_event.button !== 0) return; - d3_event.stopPropagation(); - }); + .on('change', inputOffset); containerEnter .append('div') @@ -188,17 +183,10 @@ export function uiBackgroundOffset(context) { function backgroundOffset(selection) { selection - .call(uiDisclosure() + .call(uiDisclosure(context, 'background_offset', false) .title(t('background.fix_misalignment')) - .expanded(expandedPreference) - .on('toggled', toggled) .content(render) ); - - function toggled(expanded) { - expandedPreference = expanded; - context.storage('background_offset.expanded', expanded); - } } diff --git a/modules/ui/commit.js b/modules/ui/commit.js index 52696ca30..e7d3837f5 100644 --- a/modules/ui/commit.js +++ b/modules/ui/commit.js @@ -269,7 +269,6 @@ export function uiCommit(context) { updateChangeset({ review_requested: (rr ? 'yes' : undefined) }); var expanded = !tagSection.selectAll('a.hide-toggle.expanded').empty(); - tagSection .call(rawTagEditor .expanded(expanded) diff --git a/modules/ui/disclosure.js b/modules/ui/disclosure.js index 82ee9f0b4..9d84c02f8 100644 --- a/modules/ui/disclosure.js +++ b/modules/ui/disclosure.js @@ -4,11 +4,13 @@ import { utilRebind } from '../util/rebind'; import { uiToggle } from './toggle'; -export function uiDisclosure() { +export function uiDisclosure(context, key, expandedDefault) { var dispatch = d3_dispatch('toggled'), - title, - expanded = false, - content = function () {}; + _preference = (context.storage('disclosure.' + key + '.expanded')), + _expanded = (_preference === null ? !!expandedDefault : (_preference === 'true')), + _title, + _updatePreference = true, + _content = function () {}; var disclosure = function(selection) { @@ -22,9 +24,9 @@ export function uiDisclosure() { .merge(hideToggle); hideToggle - .text(title) + .text(_title) .on('click', toggle) - .classed('expanded', expanded); + .classed('expanded', _expanded); var wrap = selection.selectAll('div') @@ -35,36 +37,46 @@ export function uiDisclosure() { .merge(wrap); wrap - .classed('hide', !expanded) - .call(content); + .classed('hide', !_expanded) + .call(_content); function toggle() { - expanded = !expanded; - hideToggle.classed('expanded', expanded); - wrap.call(uiToggle(expanded)); - dispatch.call('toggled', this, expanded); + _expanded = !_expanded; + if (_updatePreference) { + context.storage('disclosure.' + key + '.expanded', _expanded); + } + hideToggle.classed('expanded', _expanded); + wrap.call(uiToggle(_expanded)); + dispatch.call('toggled', this, _expanded); } }; disclosure.title = function(_) { - if (!arguments.length) return title; - title = _; + if (!arguments.length) return _title; + _title = _; return disclosure; }; disclosure.expanded = function(_) { - if (!arguments.length) return expanded; - expanded = _; + if (!arguments.length) return _expanded; + _expanded = _; + return disclosure; + }; + + + disclosure.updatePreference = function(_) { + if (!arguments.length) return _updatePreference; + _updatePreference = _; return disclosure; }; disclosure.content = function(_) { - if (!arguments.length) return content; - content = _; + if (!arguments.length) return _content; + _content = _; return disclosure; }; diff --git a/modules/ui/preset_editor.js b/modules/ui/preset_editor.js index 9944c8c97..602278507 100644 --- a/modules/ui/preset_editor.js +++ b/modules/ui/preset_editor.js @@ -16,7 +16,6 @@ import { utilRebind } from '../util'; export function uiPresetEditor(context) { var dispatch = d3_dispatch('change'), formFields = uiFormFields(context), - expandedPreference = (context.storage('preset_fields.expanded') !== 'false'), state, fieldsArr, preset, @@ -25,17 +24,10 @@ export function uiPresetEditor(context) { function presetEditor(selection) { - selection.call(uiDisclosure() + selection.call(uiDisclosure(context, 'preset_fields', true) .title(t('inspector.all_fields')) - .expanded(expandedPreference) - .on('toggled', toggled) .content(render) ); - - function toggled(expanded) { - expandedPreference = expanded; - context.storage('preset_fields.expanded', expanded); - } } diff --git a/modules/ui/raw_member_editor.js b/modules/ui/raw_member_editor.js index 73c7de159..e8e47b058 100644 --- a/modules/ui/raw_member_editor.js +++ b/modules/ui/raw_member_editor.js @@ -20,8 +20,8 @@ import { export function uiRawMemberEditor(context) { - var id, - taginfo = services.taginfo; + var taginfo = services.taginfo, + _entityID; function selectMember(d) { @@ -53,7 +53,7 @@ export function uiRawMemberEditor(context) { function rawMemberEditor(selection) { - var entity = context.entity(id), + var entity = context.entity(_entityID), memberships = []; entity.members.slice(0, 1000).forEach(function(member, index) { @@ -68,21 +68,17 @@ export function uiRawMemberEditor(context) { }); var gt = entity.members.length > 1000 ? '>' : ''; - selection.call(uiDisclosure() + selection.call(uiDisclosure(context, 'raw_member_editor', true) .title(t('inspector.all_members') + ' (' + gt + memberships.length + ')') .expanded(true) - .on('toggled', toggled) + .updatePreference(false) + .on('toggled', function(expanded) { + if (expanded) { selection.node().parentNode.scrollTop += 200; } + }) .content(content) ); - function toggled(expanded) { - if (expanded) { - selection.node().parentNode.scrollTop += 200; - } - } - - function content(wrap) { var list = wrap.selectAll('.member-list') .data([0]); @@ -201,8 +197,8 @@ export function uiRawMemberEditor(context) { rawMemberEditor.entityID = function(_) { - if (!arguments.length) return id; - id = _; + if (!arguments.length) return _entityID; + _entityID = _; return rawMemberEditor; }; diff --git a/modules/ui/raw_membership_editor.js b/modules/ui/raw_membership_editor.js index 21952ab08..9b67c79d6 100644 --- a/modules/ui/raw_membership_editor.js +++ b/modules/ui/raw_membership_editor.js @@ -28,7 +28,8 @@ import { utilDisplayName, utilNoAuto } from '../util'; export function uiRawMembershipEditor(context) { var taginfo = services.taginfo, - id, showBlank; + _entityID, + _showBlank; function selectRelation(d) { @@ -47,11 +48,13 @@ export function uiRawMembershipEditor(context) { function addMembership(d, role) { - showBlank = false; + _showBlank = false; + + var member = { id: _entityID, type: context.entity(_entityID).type, role: role }; if (d.relation) { context.perform( - actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }), + actionAddMember(d.relation.id, member), t('operations.add_member.annotation') ); @@ -59,7 +62,7 @@ export function uiRawMembershipEditor(context) { var relation = osmRelation(); context.perform( actionAddEntity(relation), - actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }), + actionAddMember(relation.id, member), t('operations.add.annotation.relation') ); @@ -77,15 +80,12 @@ export function uiRawMembershipEditor(context) { function relations(q) { - var newRelation = { - relation: null, - value: t('inspector.new_relation') - }, - result = [], - graph = context.graph(); + var newRelation = { relation: null, value: t('inspector.new_relation') }; + var result = []; + var graph = context.graph(); context.intersects(context.extent()).forEach(function(entity) { - if (entity.type !== 'relation' || entity.id === id) + if (entity.type !== 'relation' || entity.id === _entityID) return; var matched = context.presets().match(entity, graph), @@ -96,10 +96,7 @@ export function uiRawMembershipEditor(context) { if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1) return; - result.push({ - relation: entity, - value: value - }); + result.push({ relation: entity, value: value }); }); result.sort(function(a, b) { @@ -124,7 +121,7 @@ export function uiRawMembershipEditor(context) { function rawMembershipEditor(selection) { - var entity = context.entity(id), + var entity = context.entity(_entityID), parents = context.graph().parentRelations(entity), memberships = []; @@ -137,21 +134,17 @@ export function uiRawMembershipEditor(context) { }); var gt = parents.length > 1000 ? '>' : ''; - selection.call(uiDisclosure() + selection.call(uiDisclosure(context, 'raw_membership_editor', true) .title(t('inspector.all_relations') + ' (' + gt + memberships.length + ')') .expanded(true) - .on('toggled', toggled) + .updatePreference(false) + .on('toggled', function(expanded) { + if (expanded) { selection.node().parentNode.scrollTop += 200; } + }) .content(content) ); - function toggled(expanded) { - if (expanded) { - selection.node().parentNode.scrollTop += 200; - } - } - - function content(wrap) { var list = wrap.selectAll('.member-list') .data([0]); @@ -218,7 +211,7 @@ export function uiRawMembershipEditor(context) { var newrow = list.selectAll('.member-row-new') - .data(showBlank ? [0] : []); + .data(_showBlank ? [0] : []); newrow.exit() .remove(); @@ -272,7 +265,7 @@ export function uiRawMembershipEditor(context) { addrel .call(svgIcon('#icon-plus', 'light')) .on('click', function() { - showBlank = true; + _showBlank = true; content(wrap); list.selectAll('.member-entity-input').node().focus(); }); @@ -308,7 +301,7 @@ export function uiRawMembershipEditor(context) { taginfo.roles({ debounce: true, rtype: rtype || '', - geometry: context.geometry(id), + geometry: context.geometry(_entityID), query: role }, function(err, data) { if (!err) callback(sort(role, data)); @@ -328,8 +321,8 @@ export function uiRawMembershipEditor(context) { rawMembershipEditor.entityID = function(_) { - if (!arguments.length) return id; - id = _; + if (!arguments.length) return _entityID; + _entityID = _; return rawMembershipEditor; }; diff --git a/modules/ui/raw_tag_editor.js b/modules/ui/raw_tag_editor.js index e3cf7b6e4..9e5bccc70 100644 --- a/modules/ui/raw_tag_editor.js +++ b/modules/ui/raw_tag_editor.js @@ -25,34 +25,36 @@ import { export function uiRawTagEditor(context) { var taginfo = services.taginfo, dispatch = d3_dispatch('change'), - expandedPreference = (context.storage('raw_tag_editor.expanded') === 'true'), - expandedCurrent = expandedPreference, - updatePreference = true, - readOnlyTags = [], - showBlank = false, - newRow, - state, - preset, - tags, - id; + _readOnlyTags = [], + _showBlank = false, + _updatePreference = true, + _expanded = false, + _newRow, + _state, + _preset, + _tags, + _entityID; function rawTagEditor(selection) { - var count = Object.keys(tags).filter(function(d) { return d; }).length; + var count = Object.keys(_tags).filter(function(d) { return d; }).length; - selection.call(uiDisclosure() + var disclosure = uiDisclosure(context, 'raw_tag_editor', false) .title(t('inspector.all_tags') + ' (' + count + ')') - .expanded(expandedCurrent) .on('toggled', toggled) - .content(content) - ); + .updatePreference(_updatePreference) + .content(content); + + // Sometimes we want to force the raw_tag_editor to be opened/closed.. + // When undefined, uiDisclosure will use the user's stored preference. + if (_expanded !== undefined) { + disclosure.expanded(_expanded); + } + + selection.call(disclosure); function toggled(expanded) { - expandedCurrent = expanded; - if (updatePreference) { - expandedPreference = expanded; - context.storage('raw_tag_editor.expanded', expanded); - } + _expanded = expanded; if (expanded) { selection.node().parentNode.scrollTop += 200; } @@ -61,14 +63,14 @@ export function uiRawTagEditor(context) { function content(wrap) { - var entries = _map(tags, function(v, k) { + var entries = _map(_tags, function(v, k) { return { key: k, value: v }; }); - if (!entries.length || showBlank) { - showBlank = false; + if (!entries.length || _showBlank) { + _showBlank = false; entries.push({key: '', value: ''}); - newRow = ''; + _newRow = ''; } var list = wrap.selectAll('.tag-list') @@ -138,8 +140,8 @@ export function uiRawTagEditor(context) { items = items .merge(enter) .sort(function(a, b) { - return (a.key === newRow && b.key !== newRow) ? 1 - : (a.key !== newRow && b.key === newRow) ? -1 + return (a.key === _newRow && b.key !== _newRow) ? 1 + : (a.key !== _newRow && b.key === _newRow) ? -1 : d3_ascending(a.key, b.key); }); @@ -149,11 +151,11 @@ export function uiRawTagEditor(context) { key = row.select('input.key'), // propagate bound data to child value = row.select('input.value'); // propagate bound data to child - if (id && taginfo) { + if (_entityID && taginfo) { bindTypeahead(key, value); } - var isRelation = (id && context.entity(id).type === 'relation'), + var isRelation = (_entityID && context.entity(_entityID).type === 'relation'), reference; if (isRelation && tag.key === 'type') { @@ -162,7 +164,7 @@ export function uiRawTagEditor(context) { reference = uiTagReference({ key: tag.key, value: tag.value }, context); } - if (state === 'hover') { + if (_state === 'hover') { reference.showing(false); } @@ -187,8 +189,8 @@ export function uiRawTagEditor(context) { function isReadOnly(d) { - for (var i = 0; i < readOnlyTags.length; i++) { - if (d.key.match(readOnlyTags[i]) !== null) { + for (var i = 0; i < _readOnlyTags.length; i++) { + if (d.key.match(_readOnlyTags[i]) !== null) { return true; } } @@ -206,7 +208,7 @@ export function uiRawTagEditor(context) { function bindTypeahead(key, value) { if (isReadOnly({ key: key })) return; - var geometry = context.geometry(id); + var geometry = context.geometry(_entityID); key.call(d3_combobox() .container(context.container()) @@ -275,7 +277,7 @@ export function uiRawTagEditor(context) { var match = kNew.match(/^(.*?)(?:_(\d+))?$/), base = match[1], suffix = +(match[2] || 1); - while (tags[kNew]) { // rename key if already in use + while (_tags[kNew]) { // rename key if already in use kNew = base + '_' + suffix++; } } @@ -284,8 +286,8 @@ export function uiRawTagEditor(context) { d.key = kNew; // Maintain DOM identity through the subsequent update. - if (newRow === kOld) { // see if this row is still a new row - newRow = ((d.value === '' || kNew === '') ? kNew : undefined); + if (_newRow === kOld) { // see if this row is still a new row + _newRow = ((d.value === '' || kNew === '') ? kNew : undefined); } this.value = kNew; @@ -298,8 +300,8 @@ export function uiRawTagEditor(context) { var tag = {}; tag[d.key] = this.value; - if (newRow === d.key && d.key !== '' && d.value !== '') { // not a new row anymore - newRow = undefined; + if (_newRow === d.key && d.key !== '' && d.value !== '') { // not a new row anymore + _newRow = undefined; } dispatch.call('change', this, tag); @@ -320,7 +322,7 @@ export function uiRawTagEditor(context) { // handler. Without the setTimeout, the call to `content` would // wipe out the pending value change. setTimeout(function() { - showBlank = true; + _showBlank = true; content(wrap); list.selectAll('li:last-child input.key').node().focus(); }, 0); @@ -329,51 +331,51 @@ export function uiRawTagEditor(context) { rawTagEditor.state = function(_) { - if (!arguments.length) return state; - state = _; + if (!arguments.length) return _state; + _state = _; return rawTagEditor; }; rawTagEditor.preset = function(_) { - if (!arguments.length) return preset; - preset = _; - if (preset.isFallback()) { - expandedCurrent = true; - updatePreference = false; + if (!arguments.length) return _preset; + _preset = _; + if (_preset.isFallback()) { + _expanded = true; + _updatePreference = false; } else { - expandedCurrent = expandedPreference; - updatePreference = true; + _expanded = undefined; + _updatePreference = true; } return rawTagEditor; }; rawTagEditor.tags = function(_) { - if (!arguments.length) return tags; - tags = _; + if (!arguments.length) return _tags; + _tags = _; return rawTagEditor; }; rawTagEditor.entityID = function(_) { - if (!arguments.length) return id; - id = _; + if (!arguments.length) return _entityID; + _entityID = _; return rawTagEditor; }; rawTagEditor.expanded = function(_) { - if (!arguments.length) return expandedCurrent; - expandedCurrent = _; - updatePreference = false; + if (!arguments.length) return _expanded; + _expanded = _; + _updatePreference = false; return rawTagEditor; }; rawTagEditor.readOnlyTags = function(_) { - if (!arguments.length) return readOnlyTags; - readOnlyTags = _; + if (!arguments.length) return _readOnlyTags; + _readOnlyTags = _; return rawTagEditor; };