Here is my Javascript code:
function validspan() {
var data = document.querySelector('.keyword-input').value;
var nodes = document.querySelectorAll('.keywords-list span');
var str = Array.prototype.map.call(nodes, function(node) {
return node.textContent;
}).filter(a => !!a).join(",");
var arr = str.split(',');
for (var k = 0; k < arr.length; k++) {
if (data == arr[k]) {
alert("Don't Enter Same Skill");
let list = document.querySelector('.keywords-list');
let array = arr[k].indexOf(data);
list.removeChild(list.childNodes[array]);
return true;
} else {
alert('different values');
return false;
}
}
}
and html code where runtime spans create
<input type="text" class="keyword-input with-border #error('name') is-invalid #enderror" name="skills" placeholder="Add Skills">
<div class="invalid-feedback" style="color: red;font-size: 20px"></div>
<button type="button" class="keyword-input-button ripple-effect" onclick="validspan()"><i class="icon-material-outline-add" ></i></button>
</div>
<div class="keywords-list">
<!-- keywords go here -->
</div>
If value match then delete index but in this my code only 0 index
check and delete 0 idex. my requirment is when same value any index
then delete index
i guess you are looking for something like this?
(() => {
const btnEl = document.querySelector('#add_skill');
const inputEl = document.querySelector('#skills');
const resultsEl = document.querySelector('#keywords-list');
const arr = [];
arr.add = function(val) {
this.push(val);
resultsEl.innerHTML = arr.map(item => `<span>${val}</span>`).join('');
};
btnEl.addEventListener('click', (e) => {
let val = inputEl.value;
if (!val) {
console.error(`A value is required`);
return;
}
if (arr.includes(val)) {
console.error(`Don't Enter Same Skill`);
return;
}
arr.add(val);
});
})();
<input type="text" class="keyword-input with-border #error('name') is-invalid #enderror" id="skills" name="skills" placeholder="Add Skills">
<div class="invalid-feedback" style="color: red;font-size: 20px"></div>
<button type="button" id="add_skill" class="keyword-input-button ripple-effect"><i class="icon-material-outline-add" ></i>Add</button>
</div>
<div class="keywords-list" id="keywords-list">
<!-- keywords go here -->
</div>
in your for loop, you are terminating the execution directly and breaking from it by using the return keyword in both the if statement and the else statement, so basically what your code is doing is just testing the first index (0) and omitting all the other indexes!
you need to remove the return statements and then continue editing your code to handle other cases!
you can understand better about return inside a for loop with the answers in this question : question
hope that helped!
Related
I have this code where I want to add text to the select box when calling a function via clicking an input button.
I want the select box to have a default text when the page is loaded and no value is added to the array. And I want this text to vanish but I could still add many values from the input box and make them show on the select box.
So I made the input and select box with the following:
let num = document.querySelector('input#numtxt')
let lista = document.querySelector('select#seltxt')
let res = document.querySelector('div#res')
let valores = []
function adicionar() {
if (isNumero(num.value) && !inLista(num.value, valores)) {
lista.options[0] = null //
valores.push(Number(num.value))
let item = document.createElement('option')
item.text = `Valor ${num.value} adicionado.`
lista.appendChild(item)
} else {
window.alert('Valor inválido ou já existe!')
}
}
<div>
<p>TYpe a number between 1 and 100: <input type="number" name="num1" id="numtxt">
<input type="button" value="Adicionar" onclick="adicionar()"></p>
</div>
<div>
<p>
<select name="sel1" id="seltxt" size="10">
<option>Type a number above!</option>
</select>
</p>
<p><input type="button" value="End" onclick="finalizar()"></p>
</div>
I've tried a lot of commands with boxvar.options[0] = null and boxvar.remove(0)but they all kept removing the first value which I need for the program.
Any sugestions?
let num = document.querySelector('input#numtxt')
let lista = document.querySelector('select#seltxt')
let res = document.querySelector('div#res')
let valores = []
function adicionar() {
if (isNumero(num.value) && !inLista(num.value, valores)) {
if(!valores.length) {
// If there are no values on list, delete whatever is inside of select
lista.innerHTML = ''
}
valores.push(Number(num.value))
let item = document.createElement('option')
item.text = `Valor ${num.value} adicionado.`
lista.appendChild(item)
} else {
window.alert('Valor inválido ou já existe!')
}
}
This is slightly verbose for clarity - if we add a data attribute we can filter on that and remove it if it exists. We can also filter by values and not add if the new one exists (it could be a data attribute if you do not want to set the value.
let lista = document.querySelector('#seltxt');
let res = document.querySelector('#res');
let valores = [];
function adicionar() {
let num = document.querySelector('#numtxt');
let opts = [...lista.options].filter((element, index) => {
return element.dataset.default == "default";
});
console.log(opts);
if (opts.length) {
opts[0].remove();
}
let newValue = Number(num.value);
// now if it already exists, don't add it
let matchOpt = [...lista.options].filter((element, index) => {
return element.value == newValue;
});
// we already have it so jump back out
if (matchOpt.length) {
return;
}
valores.push(newValue);
let item = document.createElement('option');
item.text = `Valor ${num.value} adicionado.`;
item.value = newValue;
lista.appendChild(item);
}
<div>
<p>Type a number between 1 and 100: <input type="number" name="num1" id="numtxt">
<input type="button" value="Adicionar" onclick="adicionar()"></p>
</div>
<div>
<p>
<select name="sel1" id="seltxt" size="10">
<option data-default="default">Type a number above!</option>
</select>
</p>
<p><input type="button" value="End" onclick="finalizar()"></p>
</div>
I have an script that prints each letter of an string and how many times it is printed, but it is not working properly, it overrides the last letter.
For example: when you type in the textarea "assist" it should print the following:
a: 1
s: 3
i: 1
t: 1
But it only prints:
t: 1
How to print properly the string?
function ex44() {
let string = document.getElementById("sarc4").value
string = string.toLowerCase();
const count = {}
string.split("").forEach(ch => {
if (!count[ch]) {
count[ch] = 1
return
}
count[ch]++
})
for (const key in count) {
document.getElementById("result4").innerHTML = `${key} : ${count[key]}`
}
}
<label for="sarcina4"> Enter text</label>
<br>
<textarea name="sarcina4" id="sarc4" cols="60" rows="5"></textarea>
<br>
<button onclick="ex44()">Afisare</button>
<p id="result4"></p>
document.getElementById("result4").innerHTML = `${key} : ${count[key]}`
Will override the innerHTML.
Consider 'adding' the content using appendChild or insertAdjacentHTML:
Is it possible to append to innerHTML without destroying descendants' event listeners?
const res = document.getElementById("result4");
for (const key in count) {
res.insertAdjacentHTML('beforeend', `<p>${key} : ${count[key]}</p>`);
}
function ex44() {
let string = document.getElementById("sarc4").value
string = string.toLowerCase();
const count = {}
string.split("").forEach(ch => {
if (!count[ch]) {
count[ch] = 1
return
}
count[ch]++
})
const res = document.getElementById("result4");
for (const key in count) {
res.insertAdjacentHTML('beforeend', `<p>${key} : ${count[key]}</p>`);
}
}
<label for="sarcina4"> Enter text</label>
<br>
<textarea name="sarcina4" id="sarc4" cols="60" rows="5"></textarea>
<br>
<button onclick="ex44()">Afisare</button>
<p id="result4"></p>
Note: I've wrapped the ${key} : ${count[key]} inside a <p></p> tag so we see each letter on a separate row
Another option is to create an output string by using map and join like so:
const output = Object.keys(count).map((key) => `<p>${key} : ${count[key]}</p>`);
document.getElementById("result4").innerHTML = output.join('');
function ex44() {
const input = document.getElementById("sarc4").value.toLowerCase();
const count = {}
input.split("").forEach(ch => {
if (!count[ch]) {
count[ch] = 1;
} else {
count[ch]++
}
});
const output = Object.keys(count).map((key) => `<p>${key} : ${count[key]}</p>`);
document.getElementById("result4").innerHTML = output.join('');
}
<label for="sarcina4"> Enter text</label>
<br>
<textarea name="sarcina4" id="sarc4" cols="60" rows="5">test</textarea>
<br>
<button onclick="ex44()">Afisare</button>
<p id="result4"></p>
You should use Object.keys(count) to foreach. And currently, you are overwriting the result's HTML on loop. So I use a newHtml variable to save it and set it into innerHTML outside loop.
function ex44() {
let string = document.getElementById("sarc4").value
string = string.toLowerCase();
const count = {}
string.split("").forEach(ch => {
if (!count[ch]) {
count[ch] = 1
return
}
count[ch]++
})
var newHtml = '';
for (const key of Object.keys(count)) {
newHtml += `${key} : ${count[key]} <br/>`
}
document.getElementById("result4").innerHTML = newHtml;
}
<label for="sarcina4"> Enter text</label>
<br>
<textarea name="sarcina4" id="sarc4" cols="60" rows="5"></textarea>
<br>
<button onclick="ex44()">Afisare</button>
<p id="result4"></p>
Move the document.getElementById("result4").innerHTML outside the loop.
You are rewritting the innerHTML of the element with id result4 each time the loop is executing. You can update the innerHTML by appending the new striing with existing by using below to get the issue fixed.
document.getElementById("result4").innerHTML += `${key} : ${count[key]}`
The above implementation cannot be considered as a good implementation even though it's fixes your problem. Accessing DOM elements directly from script is always costly. If it's inside a loop a loop it's definitely more costly.
Instead of accessing the DOM element multiple time from a loop, you could create the template string inside the loop and assign the innerHTML only once as below. This will be better in terms of performance.
function ex44() {
let string = document.getElementById("sarc4").value
string = string.toLowerCase();
let template = '';
const count = {}
string.split("").forEach(ch => {
if (!count[ch]) {
count[ch] = 1
return
}
count[ch]++
})
for (const key in count) {
template += `${key} : ${count[key]}`
}
document.getElementById("result4").innerHTML = template;
}
<label for="sarcina4"> Enter text</label>
<br>
<textarea name="sarcina4" id="sarc4" cols="60" rows="5"></textarea>
<br>
<button onclick="ex44()">Afisare</button>
<p id="result4"></p>
Cache your elements, and then use textContent to update the element text using string concatenation.
const sarc4 = document.getElementById('sarc4');
const result4 = document.getElementById('result4');
function ex44() {
string = sarc4.value.toLowerCase();
const count = {};
string.split("").forEach(ch => {
if (!count[ch]) {
count[ch] = 1;
return;
}
count[ch]++
});
let result = '';
for (const key in count) {
result += `${key}:${count[key]} `;
}
result4.textContent = result;
}
<label for="sarcina4"> Enter text</label>
<br>
<textarea name="sarcina4" id="sarc4" cols="60" rows="5"></textarea>
<br>
<button onclick="ex44()">Afisare</button>
<p id="result4"></p>
EDIT: I have updated the code with the answers.
I have a increment function that is working fine. However:
1. I would like to set some limits based on the total number available in one of the span. For example, 10. So the incrementing can't be more than 10. #DONE
Another issue is that I am planning to have multiple rows and before I save I want to make sure if we count the increments in every row it should not be more than 10 as well. If it decrease the total number (span) dynamically would be nice.
I'm adding rows dynamically with the ADD button, how can I add news rows that actually work with the current functions? Mine rows just clone the first one and the increment function is disabled.
document.addEventListener('DOMContentLoaded', async function() {
document.querySelector('#addlocationdest').addEventListener('click', add);
});
function add() {
var x = 1;
var container = document.getElementById('destination');
var detail = document.getElementById('row');
var clone = detail.cloneNode(true);
clone.id = "destination" + x;
x++;
container.appendChild(clone);
}
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
for (let row of document.querySelectorAll("form .row")) {
let input = row.querySelector("input");
row.querySelector(".increment").addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
row.querySelector(".decrement").addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
}
});
<div id="location" class="hide">
<div class="title">Transfer details</div><br>
<div class="line padded-s">Total Quantity: <span>10</span></div>
<br>
<form>
<label>New Total Quantity at this location: <span id="totalqty">10</span></label>
<br>
<div id="destination">
<div id="row" class="row">
<button type="button" class="decrement">-</button>
<input type="text" class="quantity" value="0" readonly/>
<button type="button" class="increment">+</button>
<a>Location: </a>
<input type="text" class="location" value="0" readonly/>
</div>
</div>
</form>
<label>Total being transfer: <p id="total-sum"></p></label>
<br>
<button type="button" id="addlocationdest">ADD</button>
<button type="button" id="removelocationdest">REMOVE</button>
</div>
Prologue
As long as the total quantity is fixed at the beginning of the script-execution, this works. Otherwise, it would be best to save the actual allowed total quantity as an attribute, and observe it using a MutationObserver. That way you can update your max. value in your code dynamically, when the total quantity-attribute changes. You can define custom attributes by naming them "data-*" where "*" is a custom name.
Solution for your problem
You are using the same ID on multiple elements. What you meant were classes, so change id="increment" to class="increment", and the same for decrement.
Since we don't want to input something with the buttons, but add listener to them, I'd say it is better to actually use <button>. In forms, buttons act as type="submit", which we don't want, so we need to change it to type="button".
Since the rows and the total quantity actually belong together, it is wiser to place them together into one <form>-element. However, you can still group the buttons and inputs as a row together using <div>.
Now regarding the in-/decrementing of the row's values and the total quantity:
Save the allowed total quantity in a variable
Add event-listener to the corresponding buttons
If action is valid, change row's value
Update total quantity number to totalQuantity - getSumOfRows()
To add new rows dynamically, we create and setup such an element, and append it to the form. See the appendNewRow()-function below.
Sidenote
I have added the readonly attribute to the input-fields so that you cannot enter numbers via keyboard.
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
function updateTotalQuantity() {
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
}
function appendNewRow() {
let row = document.createElement("div");
row.classList.add("row");
let child;
// input.quantity
let input = document.createElement("input");
input.classList.add("quantity");
input.value = "0";
input.setAttribute("readonly", "");
input.setAttribute("type", "text");
row.append(input);
// button.increment
child = document.createElement("button");
child.classList.add("increment");
child.innerHTML = "+";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
updateTotalQuantity();
});
row.append(child);
// button.increment
child = document.createElement("button");
child.classList.add("decrement");
child.innerHTML = "-";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
updateTotalQuantity();
});
row.append(child);
// button.remove-row
child = document.createElement("button");
child.classList.add("remove-row");
child.innerHTML = "Remove";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
row.remove();
updateTotalQuantity();
});
row.append(child);
document.querySelector("form .rows").append(row);
}
document.querySelector("form .add-row").addEventListener("click", () => appendNewRow());
appendNewRow();
});
<form>
<label>Total Quantity: <span id="totalqty">10</span></label>
<br>
<div class="rows">
</div>
<button type="button" class="add-row">Add new row</button>
</form>
QuerySelector only selects the first occurrence so you haven't really added a listener to the second "row". You should use querySelectorAll but, instead of unique ids, use classes.
<input class="increment" type="button" value="+" />
Now you can use document.querySelectorAll(".increment") to get all elements in an array.
You can traverse in the DOM by using parentElement. By knowing which button you clicked, you can traverse up to the form element and then select the first child - which is an input. A more dynamic way would be to use querySelector to select the input, in case the HTML change in the future. Anyway, that's how you can know which input to manipulate based on where the buttons are in the DOM.
I added two global variables, totalSum and maxSum. maxSum is fetched from your span element (which I assigned an unique id to). totalSum makes sure that all inputs combined doesn't exceed maxSum.
You had some duplicate code, so I refactored it into a new method: changeValue.
In all, I think the code speaks for itself.
Oh, this code doesn't take into account that the user can change the value inside the input. I will leave that for you to figure out with an "oninput" listener on each text input.
var totalSum = 0; // 3
var maxSum = 0
var totalSumElement = null;
document.addEventListener('DOMContentLoaded', async function() {
totalSumElement = document.getElementById('total-sum');
maxSum = document.getElementById('max-sum').innerText;
var incrementElements = document.querySelectorAll('.increment'); // 1
var decrementElements = document.querySelectorAll('.decrement');
addListener('click', incrementElements, incrementValue);
addListener('click', decrementElements, decrementValue);
});
function addListener(type, elementArr, func) {
for (element of elementArr) {
element.addEventListener(type, func);
}
}
function withinRange(newValue) {
var maxReached = newValue > maxSum; // 3
var zeroReached = newValue < 0;
return !maxReached && !zeroReached;
}
function changeValue(event, change) { // 4
if (withinRange(totalSum + change)) {
let parent = event.currentTarget.parentElement; // 2
let input = parent.children[0];
let value = parseInt(input.value) || 0;
if (withinRange(value + change)) {
input.value = value + change;
totalSum = totalSum + change;
}
}
totalSumElement.textContent = `Total: ${totalSum}`;
}
function incrementValue(event) {
changeValue(event, 1);
}
function decrementValue(event) {
changeValue(event, -1);
}
#totalqty {
padding-bottom: 1rem;
}
<div id="totalqty" class="line padded-s">Total Quantity: <span id="max-sum">10</span></div>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<p id="total-sum"></p>
I'm trying to pass an array to an input field in a chat. The array passed is after meeting certain conditions.
For example in this code below, the array comes from a loop over another div element.
So when the user selects an option, based on the selection, the array is passed as an answer.
This is my code below;
<select name="result" id="result" dataquestion="Click on the button below to know your answer.">
<option value="my result">Yes</option>
<option value="no result">No</option>
</select>
<div data-fork="result">
<div data-case="my result" id="responses">
<input type="text" data-answer="[]">
</div>
<div data-case="no result" id="response">
<input name="thought" data-answer="[]">
</div>
</div>
<div id="target">i love a cat</div>
<script type="text/javascript">
var array1 = []
//var array1 = ["i love a cat"]
$("#target").each(function() {
array1.push($(this).html());
});
var array2 = ["bat", "cat", "dog"];
function getMatch(a, b) {
var matches = [];
var response = "You got it right"
for ( var i = 0; i < a.length; i++ ) {
for ( var e = 0; e < b.length; e++ ) {
//if ( a[i] === b[e] ) matches.push( a[i] );
if ( a[i] === b[e] ) matches.push(response);
}
}
return Array.from(new Set(matches));
}
document.getElementById("target").innerHTML = getMatch(array1, array2);
</script>
SO in this js snippet, instead of passing the value to id=#target, it goes to the 'data-answer="[]"'.
Is there a way to achieve this?
Kind regards
How can I make a form so they cannot repeat the same values in the Input?
I tried a way like:
var text1 = document.getElementById('num1').value;
var text2 = document.getElementById('num1').value;
var textform = [text1,text2];
if (
text1 == text2 ||
text2 == text1
) {
alert("repeated numbers");
return false;
}
But this is gets me into two troubles:
- If I put no value, it will say: Repated Numbers
- If I want to make this for 100 form values, it takes a lot of code
You could give all of your text elements the same class, and grab their values by class name to simplify building the array of text values.
<input type="text" class="checkDupe" id="input1" />
<input type="text" class="checkDupe" id="input2" />
Then grab their values in javascript
var checkDupes = document.getElementsByClassName('checkDupe');
var textArray = [];
for(var i = 0; i < checkDupes.length; i++){
textArray.push(checkDupes[i].value);
}
Now that we have an array of values that they entered, check to see if any of them repeat by sorting the array, and seeing if any two elements side-by-side are the same.
textArray.sort();
var dupes = false;
for(var i = 0; i < textArray.length; i++){
if(textArray[i] === textArray[i + 1]) dupes = true;
}
If we find any duplicates, let the user know.
if(dupes) alert('Repeated numbers!');
You could do something like this:
var text1 = document.getElementById('num1').value;
var text2 = document.getElementById('num2').value;
var textform = [text1, text2];
var seen = {};
textform.forEach(function(value) {
if (seen[value]) {
alert('Bad!');
}
seen[value] = true;
});
In the code above, we loop over each value in the array. The first time we encounter it, we push it into a map. Next time (if) we hit that value, it will exist in the map and it will tell us we've seen it before.
If you give all the input's a common class then you quickly loop through them.
The HTML:
<input type="text" name="num1" class="this that number"></input>
<input type="text" name="num2" class="this number"></input>
<input type="text" name="num3" class="that number"></input>
<input type="text" name="num4" class="number"></input>
<input type="text" name="num5" class=""></input> <!-- we don't want to check this one -->
<input type="text" name="num6" class="number that this"></input>
<input type="text" name="num7" class="this that number"></input>
The JavaScript:
// get all the inputs that have the class numbers
var ins = document.querySelectorAll("input.numbers");
// a tracker to track
var tracker = {};
// loop through all the inputs
for(var i = 0, numIns = ins.length; i < numIns; ++i)
{
// get the value of the input
var inValue = ins[i].value.trim();
// skip if there is no value
if(!inValue) continue;
// if the value is already tracked then let the user know they are a bad person
// and stop
if(tracker[inValue])
{
alert("You are a bad person!");
return;
}
// track the value
tracker[inValue] = true;
}
You could also enhance this to let the user know which inputs have duplicate values:
// get all the inputs that have the class numbers
var ins = document.querySelectorAll("input.numbers");
// a tracker to track
var tracker = {};
// loop through all the inputs
for(var i = 0, numIns = ins.length; i < numIns; ++i)
{
// get the value of the input
var inValue = ins[i].value.trim();
// skip if there is no value
if(!inValue) continue;
// if the value is already tracked then error them
if(tracker[inValue])
{
// mark the current input as error
ins[i].className += " error";
// mark the first found instance as an error
ins[tracker[inValue]].className += " error";
}
// save the index so we can get to it later if a duplicate is found
tracker[inValue] = i;
}
Here's a way of doing it that automatically picks up all the text inputs in your document and validates based on what you're looking for. Would be simple enough to expose the valid value and make this the validation handler (or part of one) that handles a form submission.
<meta charset="UTF-8">
<input id="num1" type="text" value="foobar1">
<input id="num2" type="text" value="foobar2">
<input id="num3" type="text" value="foobar3">
<input id="num4" type="text" value="foobar4">
<input id="num5" type="text" value="foobar5">
<button onClick="checkValues();">Validate</button>
<script>
function checkValues() {
var inputs = document.getElementsByTagName('input');
arrInputs = Array.prototype.slice.call(inputs);
var valid = true;
var valueStore = {};
arrInputs.forEach(function(input) {
if (input.type == 'text') {
var value = input.value.toUpperCase();
if (valueStore[value]) {
valid = false;
} else {
valueStore[value] = true;
}
}
});
if (valid) {
alert('Valid: No matching values');
} else {
alert('Invalid: Matching values found!');
}
}
</script>
With jquery you can iterate directly over the inputs.
<form>
<input type="text" >
<input type="text" >
<input type="text" >
<input type="text" >
<input type="text" >
<input type="text" >
<button>
TEST
</button>
</form>
function checkValues(){
var used = {};
var ok = true;
$('form input[type="text"]').each(function(){
var value = $(this).val();
if(value !== ""){
if(used[value] === true){
ok = false;
return false;
}
used[value] = true;
}
});
return ok;
}
$('button').click(function(event){
event.preventDefault();
if(!checkValues()){
alert("repeated numbers");
};
});
https://jsfiddle.net/8mafLu1c/1/
Presumably the inputs are in a form. You can access all form controls via the form's elements collection. The following will check the value of all controls, not just inputs, but can easily be restricted to certain types.
If you want to include radio buttons and checkboxes, check that they're checked before testing their value.
function noDupeValues(form) {
var values = Object.create(null);
return [].every.call(form.elements, function(control){
if (control.value in values && control.value != '') return false;
else return values[control.value] = true;
});
}
<form id="f0" onsubmit="return noDupeValues(this);">
<input name="inp0">
<input name="inp0">
<input name="inp0">
<button>Submit</button>
</form>
For old browsers like IE 8 you'll need a polyfill for every.
You can simply get all inputs iterate them twice to check if they are equals
var inputs = document.getElementsByTagName('input');
for (i = 0; i < inputs.length; i++) {
for (j = i + 1; j < inputs.length; j++) {
if (inputs[i].value === inputs[j].value) {
console.log('value of input: ' + i + ' equals input: ' + j);
}
}
}
<input value="56" />
<input value="12" />
<input value="54" />
<input value="55" />
<input value="12" />