I have from where you can add dynamic unlimited inputs in most pages i have over 500 inputs the bigest one have 1450 inputs.
When you type in any input i like to check for duplicate values in other inputs.
Atm i think to build my code like this
$('.request').keyup(function(){
const current_element = $(this)
$('.request').not(this).each(function(key, element){
if (current_element.val() == element.val()) {
console.log('error')
}
})
})
But this do not look very good to scan each time all elements. Is there any better way i can do this?
CodePudding user response:
Use input values as keys to let JS do the iterating for you. Construct a map object with your initial values (if any), then when an input changes you can check if the key already exists in your object. The values of the object could be arrays of elements with the same input value, to highlight each one as being in an error state until there is only one element in the array. Store the previous value on each input so that you know where to "move" it from on your map object.
I recommend you debounce the keyup
event, and also listen on change
for pastes, autofills, etc. Otherwise you're slowing down your code trying to make irrelevant matches before the user has finished typing.
This is an untested example but it should get you most of the way there:
(function() {
const inputs = new Map(),
previousValues = new Map();
$('.request').each(function() {
// populate maps
if (this.value) {
previousValues.set(this, this.value);
const same = inputs.get(this.value);
if (same) {
same.push(this);
}
else {
inputs.set(this.value, [this]);
}
}
}).on('keyup change', debounce(function() {
const previousValue = previousValues.get(this);
if (this.value) {
if (previousValue == this.value) {
return; // unchanged
}
previousValues.set(this, this.value);
}
else if (previousValue) {
previousValues.delete(this);
}
else {
return; // unchanged
}
const samePrevious = previousValue && inputs.get(previousValue),
sameCurrent = inputs.get(this.value);
if (samePrevious) {
if (samePrevious.includes(this)) { // should always exist
samePrevious.splice(samePrevious.indexOf(this), 1); // remove without creating new array
}
switch (samePrevious.length) {
case 0:
inputs.delete(previousValue);
break;
case 1:
// remove error condition from single remaining element in samePrevious
break;
}
}
let clearError = true;
if (sameCurrent) {
if (!sameCurrent.includes(this)) { // should never exist
sameCurrent.push(this);
}
if (sameCurrent.length > 1) {
clearError = false;
// set error condition on all elements in sameCurrent
}
}
if (clearError && currentHasError()) { // currentHasError() is any expression to get current element's status
// remove error condition from current element
}
}));
inputs.forEach(same, text) {
if (same.length > 1) {
// set error condition on the elements in same
}
});
})();