diff --git a/css/80_app.css b/css/80_app.css
index c2d0944b8..738d3a268 100644
--- a/css/80_app.css
+++ b/css/80_app.css
@@ -1536,7 +1536,11 @@ a.hide-toggle {
border-color: #f1f1f1;
}
}
-.form-field-button.colour-selector {
+input.colour-selector {
+ visibility: hidden;
+ position: absolute;
+}
+input.date-selector {
visibility: hidden;
position: absolute;
}
diff --git a/data/core.yaml b/data/core.yaml
index c2706f78b..ebe5892e4 100644
--- a/data/core.yaml
+++ b/data/core.yaml
@@ -784,6 +784,7 @@ en:
# abbreviation of inches
inch: in
max_length_reached: "This string is longer than the maximum length of {maxChars} characters. Anything exceeding that length will be truncated."
+ set_today: "Sets the value to today."
background:
title: Background
description: Background Settings
diff --git a/modules/ui/fields/index.js b/modules/ui/fields/index.js
index 73733044b..ba5cb0c34 100644
--- a/modules/ui/fields/index.js
+++ b/modules/ui/fields/index.js
@@ -63,6 +63,7 @@ export var uiFields = {
colour: uiFieldColour,
combo: uiFieldCombo,
cycleway: uiFieldDirectionalCombo,
+ date: uiFieldText,
defaultCheck: uiFieldDefaultCheck,
directionalCombo: uiFieldDirectionalCombo,
email: uiFieldEmail,
diff --git a/modules/ui/fields/input.js b/modules/ui/fields/input.js
index 92de39beb..028ba46cb 100644
--- a/modules/ui/fields/input.js
+++ b/modules/ui/fields/input.js
@@ -6,10 +6,11 @@ import * as countryCoder from '@ideditor/country-coder';
import { presetManager } from '../../presets';
import { fileFetcher } from '../../core/file_fetcher';
import { t, localizer } from '../../core/localizer';
-import { utilGetSetValue, utilNoAuto, utilRebind, utilTotalExtent } from '../../util';
+import { utilDetect, utilGetSetValue, utilNoAuto, utilRebind, utilTotalExtent } from '../../util';
import { svgIcon } from '../../svg/icon';
import { cardinal } from '../../osm/node';
import { uiLengthIndicator } from '..';
+import { uiTooltip } from '../tooltip';
export {
uiFieldText as uiFieldColour,
@@ -208,38 +209,44 @@ export function uiFieldText(field, context) {
input.attr('type', 'text');
updateColourPreview();
+ } else if (field.type === 'date') {
+ input.attr('type', 'text');
+
+ updateDateField();
}
}
- function isColourValid(colour) {
- if (!colour.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
- // OSM only supports hex or named colors
- return false;
- } else if (!CSS.supports('color', colour) || ['unset', 'inherit', 'initial', 'revert'].includes(colour)) {
- // see https://stackoverflow.com/a/68217760/1627467
- return false;
- }
- return true;
- }
+
function updateColourPreview() {
+ function isColourValid(colour) {
+ if (!colour.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
+ // OSM only supports hex or named colors
+ return false;
+ } else if (!CSS.supports('color', colour) || ['unset', 'inherit', 'initial', 'revert'].includes(colour)) {
+ // see https://stackoverflow.com/a/68217760/1627467
+ return false;
+ }
+ return true;
+ }
wrap.selectAll('.colour-preview')
.remove();
const colour = utilGetSetValue(input);
- if (!isColourValid(colour) && colour !== '') return;
+ if (!isColourValid(colour) && colour !== '') {
+ wrap.selectAll('input.colour-selector').remove();
+ wrap.selectAll('.form-field-button').remove();
+ return;
+ }
var colourSelector = wrap.selectAll('.colour-selector')
.data([0]);
- outlinkButton = wrap.selectAll('.colour-preview')
- .data([colour]);
colourSelector
.enter()
.append('input')
.attr('type', 'color')
- .attr('class', 'form-field-button colour-selector')
- .attr('value', colour)
+ .attr('class', 'colour-selector')
.on('input', _debounce(function(d3_event) {
d3_event.preventDefault();
var colour = this.value;
@@ -248,8 +255,12 @@ export function uiFieldText(field, context) {
change()();
updateColourPreview();
}, 100));
+ wrap.selectAll('input.colour-selector')
+ .attr('value', colour);
- outlinkButton = outlinkButton
+ var chooserButton = wrap.selectAll('.colour-preview')
+ .data([colour]);
+ chooserButton = chooserButton
.enter()
.append('div')
.attr('class', 'form-field-button colour-preview')
@@ -257,12 +268,83 @@ export function uiFieldText(field, context) {
.style('background-color', d => d)
.attr('class', 'colour-box');
if (colour === '') {
- outlinkButton = outlinkButton
+ chooserButton = chooserButton
.call(svgIcon('#iD-icon-edit'));
}
- outlinkButton
- .on('click', () => wrap.select('.colour-selector').node().click())
- .merge(outlinkButton);
+ chooserButton
+ .on('click', () => wrap.select('.colour-selector').node().showPicker());
+ }
+
+
+ function updateDateField() {
+ function isDateValid(date) {
+ return date.match(/^[0-9]{4}(-[0-9]{2}(-[0-9]{2})?)?$/);
+ }
+ wrap.selectAll('.date-preview') // todo: rename
+ .remove();
+
+ const date = utilGetSetValue(input);
+
+ const now = new Date();
+ const today = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString().split('T')[0];
+ if (field.key === 'check_date' && date !== today) {
+ wrap.selectAll('.date-set-today')
+ .data([0])
+ .enter()
+ .append('button')
+ .attr('class', 'form-field-button date-set-today')
+ .call(svgIcon('#fas-rotate'))
+ .call(uiTooltip().title(() => t.append('inspector.set_today')))
+ .on('click', () => {
+ utilGetSetValue(input, today);
+ change()();
+ updateDateField();
+ });
+ } else {
+ wrap.selectAll('.date-set-today').remove();
+ }
+
+ if (!isDateValid(date) && date !== '') {
+ wrap.selectAll('input.date-selector').remove();
+ wrap.selectAll('.date-calendar').remove();
+ return;
+ }
+
+ if (utilDetect().browser !== 'Safari') {
+ console.log(utilDetect());
+ // opening of the calendar pick is not yet supported in safari <= 16
+ // https://caniuse.com/mdn-api_htmlinputelement_showpicker_date_input
+
+ var dateSelector = wrap.selectAll('.date-selector')
+ .data([0]);
+
+ dateSelector
+ .enter()
+ .append('input')
+ .attr('type', 'date')
+ .attr('class', 'date-selector')
+ .on('input', _debounce(function(d3_event) {
+ d3_event.preventDefault();
+ var date = this.value;
+ if (!isDateValid(date)) return;
+ utilGetSetValue(input, this.value);
+ change()();
+ updateDateField();
+ }, 100));
+ wrap.selectAll('input.date-selector')
+ .attr('value', date);
+
+ var calendarButton = wrap.selectAll('.date-calendar')
+ .data([date]);
+ calendarButton = calendarButton
+ .enter()
+ .append('button')
+ .attr('class', 'form-field-button date-calendar')
+ .call(svgIcon('#fas-calendar-days'));
+
+ calendarButton
+ .on('click', () => wrap.select('.date-selector').node().showPicker());
+ }
}
@@ -362,7 +444,9 @@ export function uiFieldText(field, context) {
if (field.type === 'tel') updatePhonePlaceholder();
- if (field.key.split(':').includes('colour')) updateColourPreview();
+ if (field.type === 'colour') updateColourPreview();
+
+ if (field.type === 'date') updateDateField();
if (outlinkButton && !outlinkButton.empty()) {
var disabled = !validIdentifierValueForLink();
diff --git a/scripts/build_data.js b/scripts/build_data.js
index 3d794fe4d..cf1f50b10 100644
--- a/scripts/build_data.js
+++ b/scripts/build_data.js
@@ -64,7 +64,9 @@ function buildData() {
'fas-i-cursor',
'fas-lock',
'fas-th-list',
- 'fas-user-cog'
+ 'fas-user-cog',
+ 'fas-calendar-days',
+ 'fas-rotate'
]);
// add icons for QA integrations
readQAIssueIcons(faIcons);
diff --git a/svg/fontawesome/fas-calendar-days.svg b/svg/fontawesome/fas-calendar-days.svg
new file mode 100644
index 000000000..e9183c509
--- /dev/null
+++ b/svg/fontawesome/fas-calendar-days.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/svg/fontawesome/fas-rotate.svg b/svg/fontawesome/fas-rotate.svg
new file mode 100644
index 000000000..f3712bfbe
--- /dev/null
+++ b/svg/fontawesome/fas-rotate.svg
@@ -0,0 +1 @@
+
\ No newline at end of file