0

I have a DOM in which I want to prevent users from entering duplicate entries in html text input.

The above DOM is not in user's control. It is coming through php.

At this moment, I am focussing only on name="code[]".

This is what I have tried:

$(function(){

$('input[name^="code"]').change(function() {

    var $current = $(this);

    $('input[name^="code"]').each(function() {
        if ($(this).val() == $current.val())
        {
            alert('Duplicate code Found!');
        }

    });
  });
});

Problem Statement:

I am wondering what changes I should make in javascript code above so that when a duplicate code is entered, alert message "Duplicate code Found" should come up.

flash
  • 1,455
  • 11
  • 61
  • 132
  • https://stackoverflow.com/questions/9229645/remove-duplicate-values-from-js-array – Banzay Mar 13 '20 at 20:19
  • @Banzay I don't have to remove it. I have to display an alert message if duplicate code is entered in html input box. – flash Mar 13 '20 at 20:21

2 Answers2

1

you need to add an eventlistener to each item, not an eventlistener for all. Then count inputs with same value, if there's more than 1, it's a duplicate.

Also ignore not-filled inputs.

Check following snippet:

$('input[name*="code"]').each(function() { 
  $(this).change(function(){ 
    let value = $(this).val();
    let count = 0;
    $('input[name*="code"]').each(function() { 
      if ($(this).val() != '' && $(this).val() == value) {
        count++;
        if (count > 1) alert('duplicate');
      }
    });
  });
  $(this).addClass('e');
});


$('#createInput').on('click', function(){
  let newInput = document.createElement("input");
  newInput.name = 'code[]';
  newInput.type = 'text';
  newInput.className = 'whatever';
  $('#inputGroup').append(newInput);
  // repeat the eventlistener again:
    $('input[name*="code"]:not(.e').each(function() { 
      $(this).change(function(){ 
        let value = $(this).val();
        let count = 0;
        $('input[name*="code"]').each(function() { 
          if ($(this).val() != '' && $(this).val() == value) {
            count++;
            if (count > 1) alert('duplicate');
          }
        });
      });
      $(this).addClass('e');
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="inputGroup">
  <input name="code-1" type="text" class="whatever">
  <input name="code-2" type="text" class="whatever2">
  <input name="code-3" type="text" class="whatever3">
</div>
<input type="button" id="createInput" value="Add input">

Edit: now works with dynamically created elements. The class 'e' works as flag to not insert 2 event listeners to the same node element, otherwise they will run in cascade, provoking unwanted behaviour.

JoelBonetR
  • 1,551
  • 1
  • 15
  • 21
  • Hi Joel, the code looks good. I am trying to implement your logic in the fiddle here https://jsfiddle.net/xouL47ez/ but it doesn't seem to work. – flash Mar 15 '20 at 02:33
  • The [fiddle](https://jsfiddle.net/xouL47ez/) working in a way that when you hit + button then it gives you an option to add entries into the input box. – flash Mar 15 '20 at 04:06
  • i am wondering if you can give me some pointers what changes I need to make in the fiddle. – flash Mar 15 '20 at 04:12
  • Set a class to inputs after adding the event listener, so you can add the same javascript i wrote when input:not(.class) right after adding a new input. Don't know if i explained it well – JoelBonetR Mar 15 '20 at 09:26
  • I have already setup a class to inputs with the class ="code" and class="en-desc" both for the html and script. The script is adding a new row. I am wondering if you can give some pointer in the fiddle. – flash Mar 15 '20 at 15:05
  • Also, the DOM code which I have mentioned in the question is not complete. The complete code is inside the fiddle jsfiddle.net/xouL47ez – flash Mar 15 '20 at 15:23
  • just edited it, i was trying to not to use the computer for a sunday, hope it can help you understanding the workaround, aske me if you don't understand something, regards – JoelBonetR Mar 16 '20 at 06:36
  • Hi, I hope all is well. I have a similar question in which I don't want code to remain empty. This is what I have tried but it doesn't seem to work. https://jsfiddle.net/x8e714rn/9/. – flash Mar 18 '20 at 23:29
  • To prevent empty inputs you should test each on form submit, there's no point on doing it while another event as you may block user workflow. Simply do $('#inputid').val().length < 1 ? alert('error') : console.log($(this).val() + ' is ok'); – JoelBonetR Mar 18 '20 at 23:33
0

You can use something like this, that converts the jQuery object to an Array to map the values and find duplicates. I added an option to add a style to the duplicated inputs, so the user knows which ones are duplicated.

function checkDuplicates(){
  var codes = $('input[name^="code"]').toArray().map(function(element){
    return element.value;
  })
  var duplicates = codes.some(function(element, index, self){
   return element && codes.indexOf(element) !== index;
  });
  return duplicates;
}

function flagDuplicates(){
  var inputs = $('input[name^="code"]').toArray();
  var codes = inputs.map(function(element){
    return element.value;
  });
  var duplicates = 0;
  codes.forEach(function(element, index){
    var duplicate = element && codes.indexOf(element) !== index;
    if(duplicate){
     inputs[index].style.backgroundColor = "red";
        inputs[codes.indexOf(element)].style.backgroundColor = "red";
        duplicates++
    }
  });
  return duplicates;
}

$('input[name^="code"]').on("change", function(){
 //var duplicates = checkDuplicates(); // use this if you only need to show if there are duplicates, but not highlight which ones
  var duplicates = flagDuplicates(); // use this to flag duplicates
 if(duplicates){
   alert(duplicates+" duplicate code(s)");
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input name="code-1" type="text">
<input name="code-2" type="text">
<input name="code-3" type="text">
SuperIRis
  • 423
  • 5
  • 9