JS - Attach the same function to many html forms - javascript

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);
}
};

Related

Generate Dynamic Inputs with Unique Names in jQuery

In my HTML form, it's possible to add additional inputs dynamically by clicking a button. I've got this part to work, however I need each input to have a unique name.
This is my code so far,
<div class="control-group field_wrapper">
<label class="control-label"><strong> Phone Number 1</strong></label>
<input type="text" class="input-medium" name="phone_number[]">
<button class="btn btn-success add-number" type="button" title="Add">Add</button>
</div>
<div class="additionalNumber"></div>
My JS as below,
$(document).ready(function(){
var maxField = 10;
var addButton = $('.add-number');
var wrapper = $('.additionalNumber');
function fieldHTML(inputNumber) {
return `<div class="control-group field_wrapper">\
<label class="control-label"><strong> Phone Number ${inputNumber}</strong></label>\
<input type="text" class="input-medium" name="phone_number[${inputNumber}]">\
<button class="btn btn-danger remove" type="button">Remove</button>\
</div>`;
}
var x = 1;
$(addButton).on('click', function(e) {
if (x < maxField) {
x++;
$(wrapper).append(fieldHTML(x));
}
if (x >= maxField) {
alert('Limited to 10.');
}
});
$(wrapper).on('click', '.remove', function(e) {
e.preventDefault();
$(this).parents('.control-group').remove();
x--;
});
});
Using this code, I can get unique name for each input which are created by dynamically. But my problem is name[x] index not works properly when it is removing. That mean, just think I have added 3 input and delete second one and again I am adding new one, then it has same name twice. In this case, it is phone_number[3] for second input and phone_number[3] for thirt one also.
This is the fiddle from above code. Any help is appreciated.
You don't need to index the inputs for PHP either - 3x inputs named phone_number[] will automatically be indexed 0 - 2 on the back end:
<input type="text" name="phone_number[]">
<input type="text" name="phone_number[]">
<input type="text" name="phone_number[]">
[phone_number] => Array
(
[0] => a
[1] => b
[2] => c
)
That doesn't help with your plain text Phone Number n label though. And maybe you have your own reasons to want an input name index.
If you think about it, if you're going to allow deletions of any item in the list, and you need the results to be sequential, the only option is to renumber everything each time you make a change. You don't need to include any numbering when you add a new element, just regenerate all numbering.
Here's a working snippet doing that. My changes:
No need to pass the count x to fieldHTML(), we're going to renumber everything after you add the element;
Add a <span class='count'></span> in your label, which we can target and update;
Add a reNumber() function which will iterate over all inputs on the page and number them sequentially;
Call that function after any change;
Notes:
The 2 separate tests if (x < maxField) and if (x >= maxField) can be combined into a single if/else;
If you want to get rid of the duplication of your HTML block, you could give the first one an id like template, and then instead of duplicating that HTML in your JS, just copy the template, eg :
let $copy = $('#template').clone();
wrapper.append($copy);
wrapper and addButton are already jQuery objects, no need to wrap them with $() a second time to use them;
If you do want to number your input names, for consistency the first should probably be phone_number[1];
$(document).ready(function() {
var x = 1;
var maxField = 10;
var addButton = $('.add-number');
var wrapper = $('.additionalNumber');
function fieldHTML() {
return `<div class="control-group field_wrapper">\
<label class="control-label"><strong> Phone Number <span class='count'></span></strong></label>\
<input type="text" class="input-medium" name="phone_number[]">\
<button class="btn btn-danger remove" type="button">Remove</button>\
</div>`;
}
/**
* Iterate over all inputs and renumber sequentially
*/
function reNumber() {
let count;
wrapper.find('.field_wrapper').each(function (i) {
// .each() index is 0-based, and input #1 is already on the page,
// so extras start at #2
count = i + 2;
$('.count', $(this)).html(count);
// If you want to index your input names, but you can safely leave
// this out, PHP will index them anyway
$('input', $(this)).attr('name', 'phone_number[' + count + ']')
});
}
addButton.on('click', function(e) {
if (x < maxField) {
x++;
wrapper.append(fieldHTML());
reNumber();
} else {
alert('Limited to 10.');
}
});
wrapper.on('click', '.remove', function(e) {
e.preventDefault();
$(this).parents('.control-group').remove();
x--;
reNumber();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="control-group field_wrapper">
<label class="control-label"><strong> Phone Number 1</strong></label>
<input type="text" class="input-medium" name="phone_number[]">
<button class="btn btn-success add-number" type="button" title="Add">Add</button>
</div>
<div class="additionalNumber"></div>

How to dynamically keep track of user inputs in JavaScript?

Does anyone have any idea to dynamically keep track of user inputs in a form? I learned how to disable a button and if users want to enable it, they would just have to fill in the input fields. While this works, if a user decides to backspace and go back to a clear field, the button is still enabled. I wanted to get some insight or ideas to keep track of user inputs dynamically.
I'm a bit new to JS so I just wanted some ideas. Is it possible to use for loops/forEach methods to iterate through the input fields? Or what approach do you recommend on taking?
HTML:
<form class="container">
<input type="text" class="input" />
<input type="email" class="input" id="input" />
<button type="submit" id="submitButton" href="index.html" disabled>
Submit
</button>
</form>
JavaScript:
document.getElementById("input").addEventListener("keyup", function() {
var inputs = document.querySelectorAll("input");
if (inputs != "") {
document.getElementById("submitButton").removeAttribute("disabled");
} else if ((inputs = "")) {
document.getElementById("submitButton").setAttribute("disabled", null);
}
});
Here is the solution of your problem.
document.addEventListener("keyup", function() {
var inputs = document.querySelectorAll("input");
var emptyFillExists = false;
for (let index = 0; index < inputs.length; index++) {
if (inputs[index].value.length === 0) {
emptyFillExists = true;
break;
}
}
if (!emptyFillExists) {
document.getElementById("submitButton").removeAttribute("disabled");
} else {
document.getElementById("submitButton").setAttribute("disabled", null);
}
});
<form class="container">
<input type="text" class="input" />
<input type="email" class="input" />
<button type="submit" id="submitButton" href="index.html" disabled>
Submit
</button>
</form>
There are a few things wrong with your codes:
You assume inputs as strings. It isn't. It's an array.
You track keyup event for only 1 input. You should track keyup event for all inputs instead.
Here's what I'd suggest you do:
Add event listener keyup for the form.
Interate through each input and check.
function areInputsValid() {
// Iterate through every input and check its value
var inputs = document.querySelectorAll('input');
for (var i = 0; i < inputs.length; i++)
if (inputs[i].value == '')
return false;
return true;
}
// Get the form element
var form = document.getElementsByTagName('form')[0];
// Add event listener
form.addEventListener('keyup', function() {
// Are the inputs valid?
if (areInputsValid())
document.getElementById("submitButton").removeAttribute("disabled");
else
document.getElementById("submitButton").setAttribute("disabled", null);
})
EDIT: as charlietfl pointed out, there are bugs in my previous answer.

figuring out which onclick event youre using and sending that to a handler

To be honest i got my login/sign up form from online. I have dealt with a little bit of javascript but the one its using is a bit above my head. So what i'd like to do is figure out which onclick event im using and be able to send that to another function in my handler to log them in instead of signing them up. Is that possible? And if so where can i find information on how to do it?
<div class="cont_principal">
<div class="cont_centrar">
<div class="cont_login">
<form action="handlercreate.php" method="POST" enctype="multipart/form-data" >
<div class="cont_tabs_login">
<ul class='ul_tabs'>
<li class="active">SIGN IN<span class="linea_bajo_nom"></span></li>
<li>SIGN UP<span class="linea_bajo_nom"></span></li>
</ul>
</div>
<div class="cont_text_inputs">
<input value = "<?php echo isset($presets['display_name']) ? $presets['display_name'] : ''; ?>" type="text" class="input_form_sign " placeholder="DISPLAY NAME" id = "display_name" name="display_name" />
<input value = "<?php echo isset($presets['email']) ? $presets['email'] : ''; ?>"type="text" class="input_form_sign d_block active_inp" placeholder="EMAIL" id = "email" name="email"/>
<input type="password" class="input_form_sign d_block active_inp" placeholder="PASSWORD" id = "password" name="password" />
<input type="password" class="input_form_sign" placeholder="CONFIRM PASSWORD" id = "confirmpassword" name="confirmpassword" /><a href="#" class="link_forgot_pass d_block" >Forgot Password ?</a>
</div>
<div class="cont_btn">
<button class="btn_sign" type="submit" value="Submit">SIGN IN</button>
</div>
</form>
</div>
</div>
</div>
I want to be able to also pass that value to my handler so i can have it us that value to ignore certain calls.
JavaScript
function sign_up(){
var inputs = document.querySelectorAll('.input_form_sign');
document.querySelectorAll('.ul_tabs > li')[0].className="";
document.querySelectorAll('.ul_tabs > li')[1].className="active";
for(var i = 0; i < inputs.length ; i++ ) {
if(i == 2 ){
}else{
document.querySelectorAll('.input_form_sign')[i].className = "input_form_sign d_block";
}
}
setTimeout( function(){
for(var d = 0; d < inputs.length ; d++ ) {
document.querySelectorAll('.input_form_sign')[d].className = "input_form_sign d_block active_inp";
}
},100 );
document.querySelector('.link_forgot_pass').style.opacity = "0";
document.querySelector('.link_forgot_pass').style.top = "-5px";
document.querySelector('.btn_sign').innerHTML = "SIGN UP";
setTimeout(function(){
document.querySelector('.terms_and_cons').style.opacity = "1";
document.querySelector('.terms_and_cons').style.top = "5px";
},500);
setTimeout(function(){
document.querySelector('.link_forgot_pass').className = "link_forgot_pass d_none";
document.querySelector('.terms_and_cons').className = "terms_and_cons d_block";
},450);
}
function sign_in(){
var inputs = document.querySelectorAll('.input_form_sign');
document.querySelectorAll('.ul_tabs > li')[0].className = "active";
document.querySelectorAll('.ul_tabs > li')[1].className = "";
for(var i = 0; i < inputs.length ; i++ ) {
switch(i) {
case 1:
console.log(inputs[i].name);
break;
case 2:
console.log(inputs[i].name);
default:
document.querySelectorAll('.input_form_sign')[i].className = "input_form_sign d_block";
}
}
I don't know you experience with Javascript, so I will break down how I would handle this. Hopefully it works out for you.
First we need to grab your button from the DOM.
var buttonEventhandler = document.getElementsByClassName('btn_sign');
getElementsByClassName will grab every instance of the class
you pass it, and store it in an array. So from here we will
setup a handler for all buttons with that class. If you just want it on a single button, give it a special class or data attribute so you can find it.
for (var i = 0; i < buttonEventhandler.length; i++) {
buttonEventhandler[i].addEventListener('click', function(e) {
// you can stop the form from firing, unless your
// certain conditions are met. For now I will just use the event
if (e) {
e.preventDefault();
// Now that the default form event is canceled, do your thing...
e.target.innerHTML = 'TRY AGAIN';
}
});
}
Here's a fiddle demo: https://jsfiddle.net/tjz11mqg/9/
if you want to see the form function normally, just change the condition to !e.
// like this:
if (!e) {
Useful links if you want to learn more about how this works:
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
https://www.w3schools.com/jsref/event_preventdefault.asp
adding a note: I was writing this before seeing your JS, so possibly expect an update.
Henkers's code will work, but is not well-optimized for performance. With this code, the main difference is this:
signInButton.addEventListener('click', signInEventHandler);
https://jsfiddle.net/aaronr/tjz11mqg/34/
...where signInEventHandler is a function with a single parameter for the event object. Passing a function to the event listener allows the listener to have a special signature that makes it possible to remove and hopefully be optimized by the JavaScript engine:
signInButton.removeEventListener('click', signInEventHandler);
Another option, if you're already using jQuery, is to have 1 event handler that checks for the element class:
$('form').on('click', '.js-sign-in', signInEventHandler);
https://jsfiddle.net/aaronr/tjz11mqg/39/
NOTE: This is not as important, but it's good practice that, when you use an HTML class in JavaScript, prefix it by js- (such as js-sign-in). This way, when you're applying CSS, you don't accidentally change a class name that JavaScript requires, breaking functionality.
NOTE: addEventListener is not supported in IE10 and older (if that matters to you). Check its browser compatibility on this neat website: https://caniuse.com/#feat=addeventlistener

Dynamically adding HTML form fields based on a number specified by the user [duplicate]

This question already has answers here:
Dynamically creating a specific number of input form elements
(2 answers)
Closed 1 year ago.
I've a form field named Number of messages, and based on what number the user specifies, I want the exact number of text fields to be dynamically generated below to allow users to enter specified number of messages.
I have browsed through some examples where JQuery is used to generate dynamic form fields, but since I'm not acquainted with JQuery, those examples are a bit too complex for me to grasp. I do know the basics of JavaScript, and would really appreciate if I could find a solution to my query using JavaScript.
function addinputFields(){
var number = document.getElementById("member").value;
for (i=0;i<number;i++){
var input = document.createElement("input");
input.type = "text";
container.appendChild(input);
container.appendChild(document.createElement("br"));
}
}
and html code will be
Number of members:<input type="text" id="member" name="member" value=""><br />
<button id="btn" onclick="addinputFields()">Button</button>
<div id="container"/>
fiddle here
You can try something similar to this...
var wrapper_div = document.getElementById('input_set');
var btn = document.getElementById('btn');
btn.addEventListener('click', function() {
var n = document.getElementById("no_of_fields").value;
var fieldset = document.createElement('div'),
newInput;
for (var k = 0; k < n; k++) {
newInput = document.createElement('input');
newInput.value = '';
newInput.type = 'text';
newInput.placeholder = "Textfield no. " + k;
fieldset.appendChild(newInput);
fieldset.appendChild(document.createElement('br'));
}
wrapper_div.insertBefore(fieldset, this);
}, false);
No. of textfields :
<input id="no_of_fields" type="text" />
<div id="input_set">
<p>
<label for="my_input"></label>
</p>
<button id="btn" href="#">Add</button>
</div>
It is a simple task which is made simpler with jQuery. You need to first get the value from the input field for which you can use .val() or .value. Once you get the value, check if it is an integer. Now, simply use .append() function to dynamically add the elements.
HTML
<form id="myForm">
Number of Messages: <input id="msgs" type="text"> </input>
<div id="addmsg">
</div>
</form>
JAVASCRIPT
$("#msgs").on('change', function()
{
var num = this.value;
if(Math.floor(num) == num && $.isNumeric(num))
{
$("#addmsg").text('');
for(var i = 0; i < num; i++)
{
$("#addmsg").append("<input type='text'/><br/>");
}
}
});
Fiddle
Note, everytime the value in the input changes, I am first clearing the div by:
$("#addmsg").text('');
And then I loop and keep adding the input field. I hope this helps!

onclick for all buttons with a data attribute

I have three different boxes which all have a button inside.
I want to register an onclick event for every button with a specific data attribute.
I've started a jsfiddle, any suggestions?
http://jsfiddle.net/mwils/w6gofb30/
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
document.querySelectorAll("button[data-donation]")[i].onclick = console.log(buttons[i]);
}
function letsGo(init) {
var input = document.body.querySelector("input[name='amount']"),
amount = parseInt(input.value, 10) * 100,
url = "https://donate.shelter.org.uk/b?cid=152&freeamount=1&amount=";
if (input.value === '' || parseInt(input.value, 10) >= 0) {
window.location.href = url + init * 100;
} else {
window.location.href = url + amount;
}
}
<div class="shopping-item">
<p><span>£33</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£33" class="shopping-1-input">
<button data-donation="33" class="donate-button shopping-1-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£50</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£50" class="shopping-2-input">
<button data-donation="50" class="donate-button shopping-2-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£188</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£188" class="shopping-3-input">
<button data-donation="188" class="donate-button shopping-3-button">donate now</button>
</div>
While there are really many ways to do that i, most of the time, prefer a simple click delegation. I set that on elements that contain the buttons(could be the window or document.body itself).
To make it simple i show you that with a container first.
<div id="container">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
</div>
here is the js
document.getElementById('container').onclick=function(e){
if(e.target.nodeName=='BUTTON'){
alert(e.target.textContent);
}
}
What does this???
if i click on the container it checks if the target element is a button.
if yes it alerts the textContent of the button. simple right?
Doing so you avoid alot of extra variables.
In your case
document.onclick=function(e){
if(e.target.dataset['donation']){
alert(e.target.dataset['donation']);
}
}
shorter
document.onclick=function(e){
e=e.target.dataset; // reuse the variable e
!e['donation']||alert(e['donation']);
}
using
<button data-donation="33">donate now</button>
DEMO's
http://jsfiddle.net/j8xgqfmk/
Extra
button text followed by $ symbol done with css
http://jsfiddle.net/j8xgqfmk/1/
preceded by a £
http://jsfiddle.net/j8xgqfmk/2/
but returning the desidered value
Why?
No loops!!!
Only one event handler!!!!
Less variables!!!
Short code !!!
Faster then multiple complex eventhandlers.
other considerations:
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
document.querySelectorAll("button[data-donation]")[i].onclick=console.log(buttons[i]);
}
Should be written
var buttons=document.querySelectorAll('button[data-donation]'),
btnlength=buttons.length; //cache variables
for (var i = 0; i < btnlength; i++) { // var i
buttons[i].onclick=function(){ //buttons is already defined
console.log(this);
}
// and you need to pass a function to the onclick event
}
or even better
function handler(e){
console.log(this,e);
}
var btns=document.querySelectorAll('button[data-donation]'),
l=btns.length;
while(l--)btns[l].addEventListener('click',handler,false);
or the "Haters gonna hate" version
http://jsfiddle.net/Lbk1ueme/
var B=document.querySelectorAll('button[data-donation]'),
L=B.length,
I=0,
H=function(){console.log(this)};
for(;I<L;B[I++].onclick=H);
https://stackoverflow.com/a/21353032/2450730
if you have difficulties to understand that i can help you to write it based on your requests. For any other question just ask.
keep stuff simple
Loop through your element array (as you already are doing) and use addEventListener to bind the click event to each...
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(event) {
alert(this.getAttribute('data-donation')); // alert the value of data-donation attribute
});
}
<div class="shopping-item">
<p><span>£33</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£33" class="shopping-1-input">
<button data-donation="33" class="donate-button shopping-1-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£50</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£50" class="shopping-2-input">
<button data-donation="50" class="donate-button shopping-2-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£188</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£188" class="shopping-3-input">
<button data-donation="188" class="donate-button shopping-3-button">donate now</button>
The problem is you are not attaching events correctly to the element. You are assigning console.log and not a function to it. Seconds querySelectorAll is expensive. You should not keep looking things up in a loop. Create a variable and store the live html node collection it returns into it.
var btns = document.querySelectorAll("button[data-donation]");
for (var i=0; i<btns.length; i++) {
btns[i].onclick = function() {
console.log(this);
console.log(this.getAttribute("data-donation"));
}
}
function letsGo(init) {
var input = document.body.querySelector("input[name='amount']"),
amount = parseInt(input.value, 10) * 100,
url = "https://donate.shelter.org.uk/b?cid=152&freeamount=1&amount=";
if (input.value === '' || parseInt(input.value, 10) >= 0) {
window.location.href = url + init * 100;
} else {
window.location.href = url + amount;
}
}
<div class="shopping-item">
<p><span>£33</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£33" class="shopping-1-input">
<button data-donation="33" class="donate-button shopping-1-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£50</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£50" class="shopping-2-input">
<button data-donation="50" class="donate-button shopping-2-button">donate now</button>
</div>
<div class="shopping-item">
<p><span>£188</span> could help a family find and keep a home</p>
<input type="number" name="amount" placeholder="£188" class="shopping-3-input">
<button data-donation="188" class="donate-button shopping-3-button">donate now</button>
</div>
You've got the selector right already, i.e. var buttons = document.querySelectorAll("button[data-donation]") is pulling in all the buttons having data-donation, but there's no need to do another querySelectorAll inside your loop, you just need to reference each button in your result with buttons[i].
Your other mistake is setting onclick = console.log(), instead of onclick = function() { console.log() }. So all you need to change to get it working is:
var buttons = document.querySelectorAll("button[data-donation]");
for (i = 0; i < buttons.length; i++) {
var button = buttons[i];
buttons[i].onclick = function() { console.log(button) };
}
http://jsfiddle.net/w6gofb30/4/
document.querySelectorAll("button[data-donation]").every(function(e,i,a){
e.addEventListener("click", function(){
console.log(this);
console.log(this.getAttribute("data-donation"));
}, false);
});
but before this u need:
NodeList.prototype.every = function(f){
for(var k=0;k<this.length;k++)
f(this[k],k,this);
}
http://jsfiddle.net/sa0ezut7/

Categories

Resources