0

In createInput(), will return the dynamically created text inputs, each character from the string were assigned into data-str attr.

the outcome I need is to disable the input and assign a class "green" if data-str and input value matches then focus the next input, add a class "red" if it returns false...

The code below will only detect changes on first input.

Additional question: What would be the condition to apply when all inputs found a match?

str = 'hello'

function createInput(s) {
  var splitStr = s.split("");
  var inputs = "";
  
  for (var i in splitStr) {
    inputs = inputs + '<input id="gwInput" type="text" data-str="' + splitStr[i] + '" autocomplete="off" maxlength="1"></input>';
  }
  
  return inputs
}
$(document).on("input", "#gwInput", function() {
  $this = $("#gwInput")
  inputValue = $this.val();
  stringValue = $this.data("str");
  
  if (stringValue === inputValue) {
    $this.prop("disabled", true).addClass("green").removeClass("red").next().focus()
  } else {
    $this.addClass("red")
  }
});

$('.container').html(createInput(str))
input {
  display: inline-block;
  text-align: center;
  width: 30px;
  height: 30px;
  border: 1px solid #aaa;
  padding: 5px;
  margin: 2px;
  outline: 0
}

.green { border: 1px solid green; }
.red { border: 1px solid red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" />
88willr
  • 148
  • 1
  • 9
  • 2
    Id's have to be **unique** – Andreas Nov 11 '20 at 07:44
  • use `createElement()` instead of building it from a string, so that you have a DOM element, and so you can attach to it a event listener (https://developer.mozilla.org/it/docs/Web/API/Document/createElement) – Alberto Sinigaglia Nov 11 '20 at 07:44
  • 2
    Don't use `for...in...` for arrays -> [Why is using “for…in” for array iteration a bad idea?](https://stackoverflow.com/questions/500504/why-is-using-for-in-for-array-iteration-a-bad-idea) – Andreas Nov 11 '20 at 07:44

2 Answers2

2

You should change to use class for the inputs. In your current code, you used id, so the event handler will only apply for one input only.

var str = 'hello',
    strLen = str.length,
    matched = 0;

function createInput(s) {
    var splitStr = s.split("");
    var inputs = "";
    for (var i in splitStr) {
        inputs = inputs + '<input class="gwInput" type="text" data-str="' + splitStr[i] + '" autocomplete="off" maxlength="1"></input>';
    }
    return inputs
}
$(document).on("input", ".gwInput", function() {
    inputValue = $(this).val();
    stringValue = $(this).data("str");
    if (stringValue === inputValue) {
        $(this).prop("disabled", true).removeClass("red").addClass("green").next().focus();
        matched++;
    } else {
        $(this).addClass("red")
    }
   
    if (matched === strLen) {
        $('#message').show();
    }
});
$('.container').html(createInput(str))
 input{
  display: inline-block;
  text-align: center;
  width: 30px;
  height: 30px;
  border: 1px solid #aaa;
  padding: 5px;
  margin: 2px;
  outline:0
}
.green {
  border: 1px solid green;
}
.red {
  border: 1px solid red;
}
#message {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container"></div>
<div id="message">Success</div>

Update additional question. Because you disabled the inputs after it matched, so we can use an easy way to achieve it. Just need to define an iterator and compare it with the string length.

James Dinh
  • 181
  • 6
1

You are using the same value in ID attribute for multiple elements. So you need to replace

id="gwInput" with class="gwInput"

and

$this = $("#gwInput") with $this = $(this)

Also, you can use spread operator and Array.map() to iterate over the string and map it to input elements.

str = 'hello'

function createInput(s) {
  return [...s].map(letter => '<input class="gwInput" type="text" data-str="' + letter + '" autocomplete="off" maxlength="1"></input>').join("") 
}

$(document).on("input", ".gwInput", function() {
  $this = $(this)
  inputValue = $this.val();
  stringValue = $this.data("str");
  
  if (stringValue === inputValue) {
    $this.prop("disabled", true).addClass("green").next().focus()
  } else {
    $this.addClass("red")
  }
});

$('.container').html(createInput(str))
input {
  display: inline-block;
  text-align: center;
  width: 30px;
  height: 30px;
  border: 1px solid #aaa;
  padding: 5px;
  margin: 2px;
  outline: 0
}

.green { border: 1px solid green; }
.red { border: 1px solid red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" />
Harun Yilmaz
  • 8,281
  • 3
  • 24
  • 35