1

I have a form with lots of input elements and there's nothing telling the user which fields are required. The problem is that I don't have access to its HTML code.

So I'm writing this JavaScript:

var allInputs = document.querySelectorAll("input");  
var newItem = document.createElement("LI");  
var textnode = document.createTextNode("(*)");  
newItem.appendChild(textnode);  
for (var i = 0; i < allInputs.length; i++) {  
        if(allInputs[i].hasAttribute('required') == true){  
          allInputs[i].parentNode.insertBefore(newItem, allInputs[i]);  
        }  
}  

Result: it adds (*) before the last input only. I've tried running this code on the browser console line by line, and I've noticed that it adds the text on a input and erases the previous one.

I'm not a web developer and I'm using examples I found on the internet, so this is tricky for me :/

cela
  • 2,352
  • 3
  • 21
  • 43

4 Answers4

2

You are actually adding the element next to each input. But since you are referencing the same newItem it just moves the element from one location to the next instead of creating a new element at that location.

Use cloneNode() to make a new copy of your element that you can place at each location.

allInputs[i].parentNode.insertBefore(newItem.cloneNode(true), allInputs[i]);  
Patrick Evans
  • 41,991
  • 6
  • 74
  • 87
0

You're creating a new li only once, before the loop starts, so every time you insertBefore you're removing the li from its previous location and putting it in the new location.

If the new element only has one child node, and that child node is a text node, it's less verbose to simply assign to textContent.

Create a new li on each iteration instead:

const allInputs = document.querySelectorAll("input");
for (let i = 0; i < allInputs.length; i++) {  
  if(allInputs[i].hasAttribute('required') == true){  
    const newItem = document.createElement("LI");  
    newItem.textContent = '(*)';
    allInputs[i].parentNode.insertBefore(newItem, allInputs[i]);
  }  
}  
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0
function addAsterisk(node){ 
    var newItem = document.createElement("LI");  
    var textnode = document.createTextNode("(*)");  
    newItem.appendChild(textnode);
    node.parentNode.insertBefore(newItem, node);
}

var allInputs = document.querySelectorAll("input"); 

for (var i = 0; i < allInputs.length; i++) {  
        if(allInputs[i].hasAttribute('required') == true){
          addAsterisk(allInputs[i]);
        }  
} 
jancha
  • 4,916
  • 1
  • 24
  • 39
0

I don't know where you want to place your mark, but adding it in a <li> will make the mark appear on a new line.

Personally I would add the mark on the side of the input, like this:

const allInputs = document.querySelectorAll("input[required]");
const addMark = x => x.parentNode.appendChild(document.createTextNode("*"));
[...allInputs].forEach(addMark);
<ul>
<li><label>First name <input required/></label>
<li><label>Second name <input/></label>
<li><label>Email<input type="email" required/></label>
<li><label>Information <input/></label>
</ul>
Jorjon
  • 5,316
  • 1
  • 41
  • 58