I am trying to use javascript to find duplicate values in form elements (input boxes and select drop downs) based on class. This is what I have, but it is not working. Is there a better way to do this? I am new to javascript and saw this as a solution on a different post.
EDIT: Only the inner functions are not called. If I break them out, they get called. Why is this?
<%# taglib prefix="s" uri="/struts-tags"%>
<s:include value="Header.jsp">
<s:param name="pageScript">
<script type="text/javascript">
function checkForDuplicates() {
var hasDuplicates = false;
$('.class_name').each(function () {
var inputsWithSameValue = $(this).val();
hasDuplicates = $('.class_name').not(this).filter(function () {
return $(this).val() === inputsWithSameValue;
}).length > 0;
if (hasDuplicates){
alert("cannot have duplicates")
}
});
}
</script>
</s:param>
</s:include>
<div id="container-content">
<div id="content">
<s:form action="someAction" theme="simple" method="get" id="theForm">
<s:textfield theme="simple" class="class_name"/>
<s:textfield theme="simple" class="class_name" />
<s:select headerKey="" headerValue="Select Value"
list="values" listKey="value" class="class_name" size="1"/>
<s:submit action="" value="Save" onclick="return checkForDuplicates()"/>
</s:form>
<%-- end content --%>
</div>
<%-- end container-content --%>
</div>
<s:include value="Footer.jsp" />
I am importing these:
<script src="scripts/jquery-1.4-min.js"></script>
<script src="scripts/jquery.maskedinput.min.js" type="text/javascript"></script>
<script src="scripts/jquery.supertextarea.min.js" type="text/javascript"></script>
What is the problem? I put a breakpoint inside the first innerfunction after the .each, but it never goes in there.
Thanks
This is based on ROX's answer, however, i think we can check if the next element's input is inside the array without the need of a second function.
function checkDuplicates() {
// get all input elements
var $elems = $('.class_name');
// we store the inputs value inside this array
var values = [];
// return this
var isDuplicated = false;
// loop through elements
$elems.each(function () {
//If value is empty then move to the next iteration.
if(!this.value) return true;
//If the stored array has this value, break from the each method
if(values.indexOf(this.value) !== -1) {
isDuplicated = true;
return false;
}
// store the value
values.push(this.value);
});
return isDuplicated;
}
You might want to check if the input is empty somewhere in your code but that's up to you.
Edit : https://jsfiddle.net/65ss1cxj/
Your could make your function much better, there is no need to loop all over your elements inside your first loop.
Just store your all inputs values into an array, then make that array unique values, and compare the length of them.
// a function to make an array values unique
// http://stackoverflow.com/a/840849/3971911
function eliminateDuplicates(arr) {
var i,
len=arr.length,
out=[],
obj={};
for (i=0;i<len;i++) {
obj[arr[i]]=0;
}
for (i in obj) {
out.push(i);
}
return out;
}
function checkDuplicates() {
// get all input elements
var $elems = $('.class_name');
// we store the inputs value inside this array
var values = [];
// loop through elements
$elems.each(function () {
// if the value is empty, just pass it
if (this.value == '') {
return true;
}
// store the value
values.push(this.value);
});
// make the values array unique
var uniqueValues = eliminateDuplicates(values);
// return false if the unique array length is not equal to the original array
return uniqueValues.length == values.length;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form>
<div><input type="text" class="class_name" /></div>
<div><input type="text" class="class_name" /></div>
<div><input type="text" class="class_name" /></div>
<div><input type="text" class="class_name" /></div>
<input type="submit" value="Go" onclick="return checkDuplicates()" />
</form>
Related
var array = [];
$('input').click(function(){
var value = this.value;
if (array.indexOf(value) > -1) {
array.splice(array.indexOf(value));
$(this).next('span').html('');
return false;
}
array.push(value);
$(this).next('span').html(array.indexOf(value));
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type='button' value="x">
<span></span>
</div>
<div>
<input type='button' value="y">
<span></span>
</div>
In my Script here, I insert the index in the next span after input, So when you click x you get 0 and When you click y you get 1 and viceversa, The problem is When I click again on x which has index = 0,
What I expect is for the span of y to change to 0 instead of 1 since the key place changed after removing x index,
But that doesn't happen and the span stays 1 But if clicked it again, It changes to 0, How do I fix this problem?
EDIT: Added jQuery tag
Here's my go at updating everything using JQuery.
Something to note is that the splice function actually takes more arguments than just the index. If you don't supply the length parameter, it will delete everything in the array after the index.
var array = [];
$('input').click(function(){
var value = this.value
var result = true;
var i = array.indexOf(value);
if (i > -1) {
array.splice(i, 1);
result = false;
} else {
array.push(value);
}
updateSpans();
return result;
})
function updateSpans(){
$("input").each( function(){
var i = array.indexOf(this.value);
var newHTML = i;
if (i == -1){
newHTML = "";
}
$(this).next('span').html(newHTML);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type='button' value="x">
<span></span>
</div>
<div>
<input type='button' value="y">
<span></span>
</div>
You should give an ID to span elements to relate the buttons value with span elements, than you should only delete the element from array and not break the function.
Each time you click the button the content of span elements will be delete and created again, for each element that exist in array.
var array = [];
$('input').click(function(){
var value = this.value;
if (array.indexOf(value) > -1) {
array.splice(array.indexOf(value),1);
}else{
array.push(value);
}
$('span').html('');
$.each(array, function(i, item){
$('#'+item).html(array.indexOf(item));
});
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type='button' value="x">
<span id="x"></span>
<input type='button' value="y">
<span id="y"></span>
I created an outside function called 'updateDisplays' that will dynamically populate the spans as your array list changes...
// Make array[] global so that it can change across all the code
var array = [];
// bind all input elements (TODO: narrow input to specific type
// and/or class name) to a click event
$('input').click(function(){
// get the value of the input button
var value = this.value;
// test if the input's value already exists in the global
// array[]
var i = array.indexOf(value);
// if the element does already exist in the array[]...
if (i > -1) {
// remove it
array.splice(i, 1);
}else{
// if it is not in the array, add it
array.push(value);
}
// update the display output...
updateDisplays(array);
})
function updateDisplays(array){
// cycle through each button that exists on the page
$('input[type="button"]').each( function(){
// find if the value of the button exists in the array[]
var index = array.indexOf( $(this).attr('value') );
// ternary condition to set the value for 'output'
// if the index is less than zero -- the value does not
// exist in the array; so the string value is empty
// if the index is greater than or equal to zero --
// the value does exist in the array, so the string value
// is the text conversion of the index number
var output = (index < 0 )? '' : index.toString();
// ^not totaly nessecary to convert a number to a string
// in JavaScript/HTML -- it's just a nice coding convention
// to follow.
// update the neighboring span of the button with 'output'
$(this).next('span').html( output );
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<input type='button' value="w">
<span></span>
</div>
<div>
<input type='button' value="x">
<span></span>
</div>
<div>
<input type='button' value="y">
<span></span>
</div>
<div>
<input type='button' value="z">
<span></span>
</div>
I am trying to make an e-commerce-like webpage (for practice) wherein a click on any of the buttons would update the cart value by the number (quantity) specified on the input element.
So far, I was only able to update the cart from the first form because when I try to assign the function on every form using a loop, the cart updates for a millisecond then returns to zero. I assume its because of the scope.
I know there's an easier way to do this without manually assigning the function for every document.forms[n]
JS
window.onload = function()
{
var getForm = document.forms[0];
var numItems = 0;
getForm.onsubmit = function(event)
{
event.preventDefault();
var getInput = getForm.elements["num-item"].value;
if(parseInt(getInput))
{
numItems = numItems + parseInt(getInput);
var getCart = document.getElementById("item-count");
getCart.innerHTML = numItems;
getForm.reset();
}
else
{
alert("Please enter a valid number");
}
}
HTML
Cart:
<div class="basket">
<p><i class="fa fa-shopping-basket"></i></p>
<p id="item-count">0</p>
</div>
HTML Form: For brevity, I'm only posting 1 form example, but in reality, I have 6 other forms that are exactly the same.
<div class="buy-config">
<form class="buy-form" name="buy-form">
<label>Quantity:</label>
<input type="text" class="num-item" />
<button class="buy-btn">Add to Cart</button>
</form>
</div>
Loop through all of the forms by querying the selector (using whatever method you prefer, depending on performance requirements and markup flexibility -- I've used getElementsByClassName) and executing a for loop.
Inside the loop, bind a function to the "submit" event using addEventListener. You can define the function in-line (as I've done), or define the function elsewhere, assign it to a variable, and reference the variable when binding to the event.
Within the event listener function, you will refer to the form that was submitted as this.
On top of the changes described above, I've made some minor changes to your code:
Your previous version was overwriting the contents of the cart each time. This may have been on purpose, depending on whether you have one "basket" for each item or one overall (this wasn't clear in the question). So, rather than initialize numItems to zero, I've initialized it to the current number of items in the cart.
Consider using input type="number" HTML form elements. They're supported by nearly every browser and only accept digits -- they also have up/down arrows and can be set with the scroll wheel. On browsers that don't support them, they fall back to a basic text input.
var forms = document.getElementsByClassName("buy-form");
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener("submit", function(event) {
event.preventDefault();
var numItems = parseInt(document.getElementById("item-count").innerHTML);
var getInput = this.getElementsByClassName("num-item")[0].value;
if (parseInt(getInput)) {
numItems = numItems + parseInt(getInput);
var getCart = document.getElementById("item-count");
getCart.innerHTML = numItems;
this.reset();
} else {
alert("Please enter a valid number");
}
});
}
<div class="basket">
<p><i class="fa fa-shopping-basket"></i></p>
<p id="item-count">0</p>
</div>
<div class="buy-config">
<form class="buy-form" name="buy-form">
<label>Quantity:</label>
<input type="number" class="num-item" />
<button class="buy-btn">Add to Cart</button>
</form>
</div>
<div class="buy-config">
<form class="buy-form" name="buy-form">
<label>Quantity:</label>
<input type="number" class="num-item" />
<button class="buy-btn">Add to Cart</button>
</form>
</div>
<div class="buy-config">
<form class="buy-form" name="buy-form">
<label>Quantity:</label>
<input type="number" class="num-item" />
<button class="buy-btn">Add to Cart</button>
</form>
</div>
You can use the jQuery selector.
<script src="http://code.jquery.com/jquery-1.12.0.min.js"></script>
<script>
$(document).ready(function() {
$('.buy-btn').click(function(){
$(this).parent('form').submit();
});
});
</script>
<form class="buy-form">
<label>Quantity:</label>
<input type="text" class="num-item" />
<button class="buy-btn">Add to Cart</button>
</form>
The code above will setup a function for each HTML elements that has the css class buy-btn.
You can select anything using parent, children, prev, next or find function from jQuery.
Of course this is just a basic exemple I'm showing here, and again some simple example could be :
$('.buy-btn').click(function(){
$(this).parent('form').submit();
//var itemCount = $('#item-count').html();
//itemCount++;
//$('#item-count').html(itemCount);
var numItem = $(this).prev('.num-item').val();
$('#item-count').html(numItem);
});
Unfortunately, you're going to have to loop through the elements in your JavaScript and assign the function to each, however you can do it a bit simpler with some querySelector methods thrown in:
window.onload = function() {
var getCart = document.getElementById('item-count');
var forms = document.querySelectorAll('.buy-form');
var numItems = 0;
var isNum = function(n) {
return(!isNaN(parseFloat(n)) && isFinite(n));
};
var handler = function(e) {
(e || event).preventDefault();
var getInput = this.querySelector('.num-item').value;
if(isNum(getInput)) {
numItems += parseInt(getInput);
getCart.innerHTML = numItems;
this.reset();
} else {
alert("Please enter a valid number");
}
};
for(var i = 0, len = forms.length; i < len; i++) {
forms[i].addEventListener('submit', handler);
}
};
I am working on javascript.
Consider two textboxes tb1 and tb2 respectively
The value present in tb1 should be copied in tb2 based on a condition. If the condition is true nothing needs to be copied. If the condition is false the value in tb1 should also be initialised to tb2. Is it possible..
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<div>
<span>tb1:</span>
<input id="tb1" type="text" value="TextBox Value 1"/>
</div>
<div>
<span>tb2:</span>
<input id="tb2" type="text" value="TextBox Value 2"/>
</div>
<input type="button" onclick="exchange()" value="Exchange">
<script type="text/javascript">
function exchange(){
var tb1 = document.getElementById('tb1');
var tb2 = document.getElementById('tb2');
var condition = function(){
return true;
};
if(condition()){
var buf = tb1.value;
tb1.value = tb2.value;
tb2.value = buf;
}
}
</script>
</body>
</html>
Here's a function that can do what you need:
function compareAndCopy() {
var tb1 = document.getElementById("tb1");
var tb2 = document.getElementById("tb2");
if (tb1.value == "hey") {
tb2.value = tb1.value;
} else {
alert("No match");
}
}
//Add a handler
document.getElementById("tb1").onblur = compareAndCopy;
It is currently checking if tb1 equals hey on blur.
Working demo: http://jsfiddle.net/4L5pE/
yes, this is possible. You need to define when you want it to happen. onkeypress, or onblur of first text box you can call a function that validates your condition and then copies the values.
tb1.onblur(function(){ if(condition) tb2.value = tb1.value }
the code above will not work, its just a pseudo.
i have code it can be sum two textbox values using javascript but problem is that when i entered amount into recamt textbox value and javascript count again and again recamt textbox values it should be count only one time recamt textbox value not again and again?
<script type="text/javascript">
function B(){
document.getElementById('advance').value
=(parseFloat(document.getElementById('advance').value))+
(parseFloat(document.getElementById('recamt').value));
return false;
}
</script>
<input class="input_field2" type="text" readonly name="advance"
id="advance" value="50" onfocus="return B(0);" /><br />
<input class="input_field2" type="text" name="recamt" id="recamt">
You could keep a property on the read-only text field to keep the old value:
function B()
{
var adv = document.getElementById('advance'),
rec = document.getElementById('recamt');
if (typeof adv.oldvalue === 'undefined') {
adv.oldvalue = parseFloat(adv.value); // keep old value
}
adv.value = adv.oldvalue + parseFloat(rec.value));
rec.value = '';
return false;
}
You're calling the sum function every time the readonly input is focused using the new value. If you only want it to add to the original value, you need to store it somewhere.
HTML:
<input type="text" id="advance" readonly="readonly" value="50" /><br />
<input type="text" id="recamt">
JS:
var advanceBox = document.getElementById('advance');
var originalValue = advanceBox.value;
advanceBox.onclick = function() {
this.value = parseFloat(originalValue) +
parseFloat(document.getElementById('recamt').value);
return false;
};
http://jsfiddle.net/hQbhq/
Notes:
You should bind your handlers in javascript, not HTML.
The javascript would need to exist after the HTML on the page, or inside of a window.load handler, otherwise it will not be able to find advanceBox.
I am using a default value script (jquery.defaultvalue.js) to add default text to various input fields on a form:
<script type='text/javascript'>
jQuery(function($) {
$("#name, #email, #organisation, #position").defaultvalue("Name", "Email", "Organisation", "Position");
});
</script>
The form looks like this:
<form method="post" name="booking" action="bookingengine.php">
<p><input type="text" name="name[]" id="name">
<input type="text" name="email[]" id="email">
<input type="text" name="organisation[]" id="organisation">
<input type="text" name="position[]" id="position">
<span class="remove">Remove</span></p>
<p><span class="add">Add person</span><br /><br /><input type="submit" name="submit" id="submit" value="Submit" class="submit-button" /></p>
</form>
I am also using a script so that users can dynamically add (clone) rows to the form:
<script>
$(document).ready(function() {
$(".add").click(function() {
var x = $("form > p:first-child").clone(true).insertBefore("form > p:last-child");
x.find('input').each(function() { this.value = ''; });
return false;
});
$(".remove").click(function() {
$(this).parent().remove();
});
});
</script>
So, when the page loads there is one row with the default values. The user would then start adding information to the inputs. I am wondering if there is a way of having the default values show up in subsequent rows that are added as well.
You can see the form in action here.
Thanks,
Nick
Just call .defaultValue this once the new row is created. The below assumes the format of the columns is precticable/remains the same.
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
x.find('input:not(:submit)').defaultvalue("Name", "Email", "Organisation", "Position");
return false;
});
You should remove ids from the input fields because once these are cloned, the ids, classes, everything about the elements are cloned. So you'll basically end up with multiple elements in the DOM with the same id -- not good.
A better "set defaults"
Personally I would remove the "set defaults plugin" if it's used purely on the site for this purpose. It can easily be re-created with the below and this is more efficient because it doesn't care about ordering of input elements.
var defaults = {
'name[]': 'Name',
'email[]': 'Email',
'organisation[]': 'Organisation',
'position[]': 'Position'
};
var setDefaults = function(inputElements)
{
$(inputElements).each(function() {
var d = defaults[this.name];
if (d && d.length)
{
this.value = d;
$(this).data('isDefault', true);
}
});
};
Then you can simply do (once page is loaded):
setDefaults(jQuery('form[name=booking] input'));
And once a row is added:
$(".add").click(function() {
var x = $("form > p:first-child");
x.clone(true).insertBefore("form > p:last-child");
setDefaults(x.find('input')); // <-- let the magic begin
return false;
});
For the toggling of default values you can simply delegate events and with the help of setDefault
// Toggles
$('form[name=booking]').delegate('input', {
'focus': function() {
if ($(this).data('isDefault'))
$(this).val('').removeData('isDefault');
},
'blur': function() {
if (!this.value.length) setDefaults(this);
}
});
Fiddle: http://jsfiddle.net/garreh/zEmhS/3/ (shows correct toggling of default values)
Okey, first of all; ids must be unique so change your ids to classes if you intend to have more then one of them.
and then in your add function before your "return false":
var
inputs = x.getElementsByTagName('input'),
defaults = ["Name", "Email", "Organisation", "Position"];
for(var i in inputs){
if(typeof inputs[i] == 'object'){
$(inputs[i]).defaultvalue(defaults[i]);
}
}