0

this code displays the helper text whenever a user focuses on any of the input fields. My issue is I want to write the code having the same functionality but using the closure concept. Idk if this code already uses closure concept, if it does please tell me where and if it doesn't please tell me how do you do it using the closure concept.

var allInputs = document.querySelectorAll('.form-container p input:not([type="submit"])');

for (var i = 0; i < allInputs.length; i++) {
  var inputField = allInputs[i];
  var inputFieldId = inputField.id;
  var getInput = document.getElementById(inputFieldId);
  getInput.addEventListener('focus', helperNote, false);
}

function helperNote(e) {
  var helperNode = document.querySelector('.form-container #helperNote');
  var helperNote = document.createTextNode('Please input the ' + e.target.name);
  //console.dir (helperNote);
  helperNode.textContent = helperNote.data;
  helperNode.style.visibility = "visible";
}
<form method="post">
  <div class="form-container">
    <p>Fill The Form Below</p>
    <p id="helperNote">Helper note Appears Here</p>
    <p>
      <label>Email :</label>
      <input type="email" name="email" id="email">
    </p>
    <p>
      <label>Username :</label>
      <input type="text" name="username" id="username">
    </p>
    <p>
      <label>Name :</label>
      <input type="text" name="Name" id="Name">
    </p>
    <p>
      <label>Age :</label>
      <input type="number" name="age" id="age">
    </p>
    <p>
      <label>City :</label>
      <input type="text" name="City" id="City">
    </p>
    <p>
      <input type="submit" name="submit" value="sign-up">
    </p>
  </div>
</form>
4castle
  • 32,613
  • 11
  • 69
  • 106
  • 1
    You don't need to create a text node just to extract the string again. You can set `helperNode.textContent` to the value of your string directly. – 4castle Jul 27 '17 at 22:45

2 Answers2

2

Your code doesn't currently make use of any closures, but you could use one in order to replace your for loop with a forEach function that accepts a callback. This will eliminate your need for the e parameter, because you will have access to the getInput variable in the surrounding lexical scope. NodeList usually has a built-in forEach method, but it's not available on IE, so you could use one of these alternatives.

I noticed you had a lot of unnecessary code here, so I've removed it as well.

var forEach = function(array, callback, scope) {
  for (var i = 0; i < array.length; i++) {
    callback.call(scope, array[i], i, array);
  }
};

var inputs = document.querySelectorAll('input:not([type="submit"])');
var helperNote = document.getElementById('helperNote');

forEach(inputs, function(input) {
  input.addEventListener('focus', function() {
    helperNote.textContent = 'Please input the ' + input.name;
  });
});
label { display: block; margin: 5px 0; }
<form method="post">
  <p>Fill The Form Below</p>
  <p id="helperNote">Helper note appears here</p>
  <label>Email: <input type="email" name="email"></label>
  <label>Username: <input type="text" name="username"></label>
  <label>Name: <input type="text" name="name"></label>
  <label>Age: <input type="number" name="age"></label>
  <label>City: <input type="text" name="city"></label>
  <input type="submit" name="submit" value="Sign Up">
</form>
4castle
  • 32,613
  • 11
  • 69
  • 106
  • I did not know that IE didn't allow `forEach` on `NodeList`s. It doesn't do `Array.from()` either, so that sucks (as usual). – Fred Gandt Jul 27 '17 at 23:20
  • 1
    @FredGandt Yeah, one typical workaround I've seen is to use `[].slice.call(arrayLike)` in place of `Array.from()` – 4castle Jul 27 '17 at 23:23
  • You might also want to add a note about the _improper_ ` – Fred Gandt Jul 27 '17 at 23:24
1

focus on functionality

Rather than worrying about the technical nomenclature of the syntax, concentrate on the functionality.

Use forEach to iterate over the <input> elements, adding event listeners as it goes, that, when triggered, apply the desired change to the textContent of the #helperNote.

Take note in 4castle's answer of Internet Explorer's current lack of support for forEach() on a NodeList.
And I thank him for reminding me about [].slice.call(), which I've used below to transform the NodeList returned by querySelectorAll() into an Array which IE will allow forEach on (since it also doesn't currently support Array.from()).

I've added blur handling to reset the #helperNote when the inputs lose focus, and used some nifty CSS goodies for fun.

const helperNote = document.querySelector( "#helperNote" );

[].slice.call( // No thanks to Internet Explorer >.<
  document.querySelectorAll( "form input:not([type=submit])" )
).forEach( element => {
  element.addEventListener( "focus", () => {
    helperNote.setAttribute( "data-info", element.name );
  } );
  element.addEventListener( "blur", () => {
    helperNote.setAttribute( "data-info", "details" );
  } );
} );
label {
  display: table; /* block layout with inline qualities */
  margin: .5em 0;
}
#helperNote::before {
  content: "Please input your " attr( data-info );
}
#helperNote[data-info=details]::after {
  content: " below.";
}
<form method="post">
  <p id="helperNote" data-info="details"></p>
  <label>Email :<input type="email" name="email" id="email"></label>
  <label>Username :<input type="text" name="username" id="username"></label>
  <label>Name :<input type="text" name="Name" id="Name"></label>
  <label>Age :<input type="number" name="age" id="age"></label>
  <label>City :<input type="text" name="City" id="City"></label>
  <input type="submit" name="submit" value="sign-up">
</form>
Fred Gandt
  • 4,217
  • 2
  • 33
  • 41