Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 159 additions & 8 deletions modules/ui/fields/textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ import {
utilRebind
} from '../../util';
import { uiLengthIndicator } from '..';
import { svgIcon } from '../../svg/icon'; // ← ADDED


export function uiFieldTextarea(field, context) {
var dispatch = d3_dispatch('change');
var input = d3_select(null);
var wrap = d3_select(null); // ← ADDED
var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue())
.silent(field.usage === 'changeset' && field.key === 'comment');
var _tags;


function textarea(selection) {
var wrap = selection.selectAll('.form-field-input-wrap')
wrap = selection.selectAll('.form-field-input-wrap')
.data([0]);

wrap = wrap.enter()
Expand All @@ -32,19 +34,28 @@ export function uiFieldTextarea(field, context) {
.data([0]);

input = input.enter()
.append('textarea')
.append('textarea')
.attr('dir', 'auto')
.attr('id', field.domId)
.call(utilNoAuto)
.on('input', change(true))
.on('blur', change())
.on('change', change())
.on('input', function () {
change(true)();
updatePatternValidation(); // ← ADDED
})
.on('blur', function () {
change()();
updatePatternValidation(); // ← ADDED
})
.on('change', function () {
change()();
updatePatternValidation(); // ← ADDED
})
.merge(input);

wrap.call(_lengthIndicator);

function change(onInput) {
return function() {
return function () {

var val = utilGetSetValue(input);
if (!onInput) val = context.cleanTagValue(val);
Expand All @@ -60,7 +71,50 @@ export function uiFieldTextarea(field, context) {
}


textarea.tags = function(tags) {
// ============================
// INLINE REGEX VALIDATION (FIX)
// ============================
function updatePatternValidation() {
if (!field.pattern || !wrap || wrap.empty()) return;

const value = utilGetSetValue(input).trim();

if (!value) {
wrap.selectAll('.form-field-pattern-info').remove();
return;
}

let isInvalid = false;
try {
const regex = new RegExp(field.pattern);
isInvalid = !regex.test(value);
} catch {
// invalid regex → fail silently
return;
}

const info = wrap.selectAll('.form-field-pattern-info')
.data(isInvalid ? [0] : []);

const enter = info.enter()
.append('div')
.attr('class', 'form-field-pattern-info');

enter
.append('span')
.call(svgIcon('#iD-icon-info'));

enter
.append('span')
.attr('class', 'form-field-pattern-info-text')
.text(t('inspector.invalid_format'));

info.exit().remove();
}
// ============================


textarea.tags = function (tags) {
_tags = tags;

var isMixed = Array.isArray(tags[field.key]);
Expand All @@ -73,13 +127,110 @@ export function uiFieldTextarea(field, context) {
if (!isMixed) {
_lengthIndicator.update(tags[field.key]);
}

updatePatternValidation(); // ← ADDED (initial render)
};


textarea.focus = function() {
textarea.focus = function () {
input.node().focus();
};


return utilRebind(textarea, dispatch, 'on');
}










// import { dispatch as d3_dispatch } from 'd3-dispatch';
// import { select as d3_select } from 'd3-selection';

// import { t } from '../../core/localizer';
// import {
// utilGetSetValue,
// utilNoAuto,
// utilRebind
// } from '../../util';
// import { uiLengthIndicator } from '..';


// export function uiFieldTextarea(field, context) {
// var dispatch = d3_dispatch('change');
// var input = d3_select(null);
// var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue())
// .silent(field.usage === 'changeset' && field.key === 'comment');
// var _tags;


// function textarea(selection) {
// var wrap = selection.selectAll('.form-field-input-wrap')
// .data([0]);

// wrap = wrap.enter()
// .append('div')
// .attr('class', 'form-field-input-wrap form-field-input-' + field.type)
// .style('position', 'relative')
// .merge(wrap);

// input = wrap.selectAll('textarea')
// .data([0]);

// input = input.enter()
// .append('textarea')
// .attr('dir', 'auto')
// .attr('id', field.domId)
// .call(utilNoAuto)
// .on('input', change(true))
// .on('blur', change())
// .on('change', change())
// .merge(input);

// wrap.call(_lengthIndicator);

// function change(onInput) {
// return function() {

// var val = utilGetSetValue(input);
// if (!onInput) val = context.cleanTagValue(val);

// // don't override multiple values with blank string
// if (!val && Array.isArray(_tags[field.key])) return;

// var t = {};
// t[field.key] = val || undefined;
// dispatch.call('change', this, t, onInput);
// };
// }
// }


// textarea.tags = function(tags) {
// _tags = tags;

// var isMixed = Array.isArray(tags[field.key]);

// utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '')
// .attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined)
// .attr('placeholder', isMixed ? t('inspector.multiple_values') : (field.placeholder() || t('inspector.unknown')))
// .classed('mixed', isMixed);

// if (!isMixed) {
// _lengthIndicator.update(tags[field.key]);
// }
// };


// textarea.focus = function() {
// input.node().focus();
// };


// return utilRebind(textarea, dispatch, 'on');
// }
Comment on lines +152 to +236
Copy link

Copilot AI Dec 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire block of commented-out code (lines 152-236) appears to be legacy code that duplicates the implementation above. Commented-out code should be removed from the codebase as it adds clutter and can be recovered from version control if needed.

Suggested change
// import { dispatch as d3_dispatch } from 'd3-dispatch';
// import { select as d3_select } from 'd3-selection';
// import { t } from '../../core/localizer';
// import {
// utilGetSetValue,
// utilNoAuto,
// utilRebind
// } from '../../util';
// import { uiLengthIndicator } from '..';
// export function uiFieldTextarea(field, context) {
// var dispatch = d3_dispatch('change');
// var input = d3_select(null);
// var _lengthIndicator = uiLengthIndicator(context.maxCharsForTagValue())
// .silent(field.usage === 'changeset' && field.key === 'comment');
// var _tags;
// function textarea(selection) {
// var wrap = selection.selectAll('.form-field-input-wrap')
// .data([0]);
// wrap = wrap.enter()
// .append('div')
// .attr('class', 'form-field-input-wrap form-field-input-' + field.type)
// .style('position', 'relative')
// .merge(wrap);
// input = wrap.selectAll('textarea')
// .data([0]);
// input = input.enter()
// .append('textarea')
// .attr('dir', 'auto')
// .attr('id', field.domId)
// .call(utilNoAuto)
// .on('input', change(true))
// .on('blur', change())
// .on('change', change())
// .merge(input);
// wrap.call(_lengthIndicator);
// function change(onInput) {
// return function() {
// var val = utilGetSetValue(input);
// if (!onInput) val = context.cleanTagValue(val);
// // don't override multiple values with blank string
// if (!val && Array.isArray(_tags[field.key])) return;
// var t = {};
// t[field.key] = val || undefined;
// dispatch.call('change', this, t, onInput);
// };
// }
// }
// textarea.tags = function(tags) {
// _tags = tags;
// var isMixed = Array.isArray(tags[field.key]);
// utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '')
// .attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined)
// .attr('placeholder', isMixed ? t('inspector.multiple_values') : (field.placeholder() || t('inspector.unknown')))
// .classed('mixed', isMixed);
// if (!isMixed) {
// _lengthIndicator.update(tags[field.key]);
// }
// };
// textarea.focus = function() {
// input.node().focus();
// };
// return utilRebind(textarea, dispatch, 'on');
// }

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shyam-123pandey LLM is right - why you added bunch of dead code?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for previous reference but now i will clear