Hi guys I am trying to loop through 2 arrays , one array handles button Ids , the other handles the text. However it does not seem to be able to iterate through the text array. When I try to window.alert the value , it returns undefined.
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
$(buttonIdArray[i]).click(function() {
window.alert(textArray[i])
})
}
}
<button id ='one'>one</button>
<button id ='two'>two</button>
Because of the different scope in the .click() context you need to get your text from textArray before, like this:
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
const text = textArray[i]
$(buttonIdArray[i]).click(function() {
window.alert(text)
})
}
}
buttonDetails()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='one'>one</button>
<button id='two'>two</button>
You can use index() of jQuery.(like below)
var buttonIdArray = ['#one','#two'];
var textArray=['this is button one','this is button two'];
for (var i =0; i<buttonIdArray.length;i++)
{
$(buttonIdArray[i]).click(function(){
console.log(textArray[$(this).index()-1]);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id ='one'>1</button>
<button id ='two'>2</button>
This is how I would do it.
var textArray=["this is button 1","this is button 2"];
$('.myButtons').click(function(){
var index = $(this).index();
alert(textArray[index]);
});
<button class='myButtons' id="one">
Button 1
</button>
<button class='myButtons' id="two">
Button2
</button>
JS fiddle here
Or like this...
$('.myButtons').click(function(){
alert($(this).data('text'));
});
<button class='myButtons' id="one" data-text="this is my text">
Button 1
</button>
<button class='myButtons' id="two" data-text="this is my text 2">
Button2
</button>
Or like this...
var buttonArray =[
{id:'#one',text:"this is button1"},
{id:'#two',text:"this is button2"}
];
for (var i = 0; i < buttonArray.length; i++) {
var index = i;
$(buttonArray[index].id).click(function() {
alert(buttonArray[index].text);
});
}
Js Fiddle 2
Or Like this...
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
var text = textArray[i]
$(buttonIdArray[i]).click(function() {
window.alert(text)
})
}
}
buttonDetails()
There is probably a better way to do it than this, but this is how I solved your issue.
var buttonIdArray = ['#one', '#two']
var textArray = ['this is button one', 'this is button two']
function buttonDetails() {
for (var i = 0; i < buttonIdArray.length; i++) {
$(buttonIdArray[i]).attr('textArrayIndex', i)
}
}
$('button').click( function() {
window.alert(textArray[$(this).attr('textArrayIndex')]);
})
buttonDetails();
Basically, you can't have an event listener within a loop. It doesn't work.
JSFiddle
Related
Note: I know there may be ways to do this in other languages but I have only learned javascript.
I have an array of objects (food items in this case, each item has a name property). I have this code in a for loop that makes buttons for each item in the array (if the first item in the array has a name of cake then cake's button is called cake, if the item is called fries then the buttons name is fries). I want the user to be able to click the button for each item only once, and when that button is clicked, I want to display a list of each item clicked. The reason why I have var click = item[i].name is because I want each button to have the name of the item. This code makes a button for item in the array but it does not list the items clicked on. Here is my code:
HTML
<html>
<head>
</head>
<body>
<p id="likes">Likes: </p>
</body>
</html>
JAVASCRIPT
var items=[
{
name:"cake",
price:12
},
{
name:"fries",
price:10
},
{
name:"apple",
price:11
}
];
window.onload = function() {
for (var i = 0; i < items.length; i++) {
var btnItems = document.createElement("button");
btnItems.id = "btnItems";
btnItems.innerHTML = "Items";
var clicks = items[i].name;
btnItems.onclick = function () {
el.disabled = true;
clicks += items[i].name + i;
document.getElementById("clicks").innerHTML = "Items Clicked" + clicks;
}
}
Style your view as you wish but this should answer your problem
var items = [{
name: "cake",
price: 12
},
{
name: "fries",
price: 10
},
{
name: "apple",
price: 11
}
];
for (let i = 0; i < items.length; i++) {
const btn = document.createElement("button");
btn.id = "btnItems";
btn.textContent = items[i].name;
btn.onclick = function(el) {
// disable your button immediately upon click
el.target.disabled = true;
// create list element and assign value
const li = document.createElement('li');
li.textContent = items[i].name
// append list element to your <ul> list
document.getElementById('list-section').appendChild(li);
}
// append button to the DOM
document.body.appendChild(btn)
}
<ul id="list-section">
</ul>
HTML code:
I created a div to append the buttons in it.
<html>
<head>
</head>
<body>
<p id="likes">Likes: </p>
<p id="clicks"></p>
<div id="btn-container">
</div>
</body>
</html
>
Js code:
var items=[
{
name:"cake",
price:12
},
{
name:"fries",
price:10
},
{
name:"apple",
price:11
}
];
for (var i = 0; i < items.length; i++) {
var btnItems = document.createElement("button");
btnItems.id = "btnItems"+i;
var clicks = items[i].name;
btnItems.innerHTML = clicks;
document.getElementById("btn-container").appendChild(btnItems);
console.log(btnItems);
btnItems.addEventListener('click',function (el) {
alert('here');
el.disabled = true;
clicks += items[i].name + i;
document.getElementById("clicks").innerHTML = "Items Clicked" + clicks;
});
}
As you have not provided a reproducible example I cannot test this, however, you should be able to use something like this. Please take note of the comments and amend where necessary.
window.onload = function() {
for (var i = 0; i < items.length; i++) {
var btnItem = document.createElement("button");
const name = item[i].name;
// Set the button id
btnItem.id = `btnItem-${name}`;
// Set the button text to the item name
btnItem.innerHTML = name
btnItem.addEventListener('click', function (event) {
event.target.disabled = true;
// Do whatever you want here, e.g. add "name" to a list
}
}
}
I want change color title on click it.
I write next:
window.onload = function () {
var color = document.getElementById('input-color');
var elems = document.querySelectorAll('.title');
function chancheColor(){
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener('click', function () {
color.click();
color.addEventListener('change', function () {
var name = this.value;
for (var i = 0; i < elems.length; i++) {
elems[i].style.color = name;
}
});
});
}
}
chancheColor();
};
<input id="input-color" type="color">
<p class="title">First</p>
<p class="title">First</p>
<p class="title">First</p>
I simulate a click on
color.click();
Is it true?
Now my function сhange the color for all titles
beacause I have a second cycle for (var i = 0; i < elems.length; i++)
I don't know, how get the current value of the title which was clicked.
And generally how is it possible to transfer a parameter in function if it is caused like this?
color.addEventListener('change', function () {});
you are attaching event handler to color multiple times in for loop, no need for that. and the loop inside event handler is not required, you just have to change the color of clicked 'p' for that you can save the clicked p and changed its color inside change event handler of input-color, something like this:
window.onload = function () {
var color = document.getElementById('input-color');
var elems = document.querySelectorAll('.title');
var currentElem;
function chancheColor(){
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener('click', function () {
currentElem = this;
color.click();
});
}
}
color.addEventListener('change', function () {
var name = this.value;
currentElem.style.color = name;
});
chancheColor();
};
<input id="input-color" type="color">
<p class="title">First</p>
<p class="title">First</p>
<p class="title">First</p>
At each click at elems[i] you are attaching an additional change event handler to color.
Move change event attachment outside of for loop.
And generally how is it possible to transfer a parameter in function
if it is caused like this?
You can use Element.dataset to set the clicked element .dataset property to true and set siblings .dataset to false, use .querySelector() with attribute selector ".title[data-clicked=true]" to select only the element which was clicked within change handler.
window.onload = function() {
var color = document.getElementById('input-color');
var elems = document.querySelectorAll('.title');
function chancheColor() {
for (var i = 0; i < elems.length; i++) {
elems[i].addEventListener('click', function() {
for (var j = 0; j < elems.length; j++) {
elems[j].dataset.clicked = false;
}
this.dataset.clicked = true;
color.click();
});
}
}
color.addEventListener('change', function() {
var clicked = document.querySelector(".title[data-clicked=true]");
if (clicked) {
console.clear();
clicked.style.color = this.value;
}
else {
console.log("Click a .title element to change the elements' color");
}
});
chancheColor();
};
<input id="input-color" type="color">
<p class="title">First</p>
<p class="title">First</p>
<p class="title">First</p>
How to get rid of jQuery's ".index()" here? All I am looking for is a native way to get the index of the button clicked, see source code below (works perfectly but I really couldn't find any Vanilla-JS solution for this and I don't want to use jQuery for such a small task). Thanks.
function navButtonClick(ev) {
var buttonIndex = $(ev.currentTarget).index(); /* How to get rid of jQuery? */
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i=0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
The HTML part looks like this:
<nav id="navigation" role="navigation">
<button type="button"> <em>Navi tab 1</em> </button>
<button type="button"> Navi tab 2 </button>
<button type="button"> Navi tab 3 </button>
<button type="button"> Navi tab 4 </button>
</nav>
<div id="output"></div>
You can do it like this:
function navButtonClick(ev) {
var buttonIndex = Array.prototype.indexOf.call(this.parentElement.children, this);
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i=0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
Check the snippet below:
function navButtonClick(ev) {
var buttonIndex = Array.prototype.indexOf.call(this.parentElement.children, this);
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i = 0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
<nav id="navigation" role="navigation">
<button type="button"> <em>Navi tab 1</em>
</button>
<button type="button">Navi tab 2</button>
<button type="button">Navi tab 3</button>
<button type="button">Navi tab 4</button>
</nav>
<div id="output"></div>
You can do this in two different ways. First, pass the index of the buttons to the corresponding function while adding the event listeners:
function navButtonClick(buttonIndex) {
document.getElementById("output").innerHTML = buttonIndex;
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i = 0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick.bind(null, i));
}
}
startTemplate();
JSFiddle
Second, create a function which will dynamically check the index of the element:
function navButtonClick() {
document.getElementById("output").innerHTML = getIndex(this);
}
function getIndex(elm) {
var parent = elm.parentElement;
for (var i = 0; i < parent.children.length; i++) {
if (parent.children[i].isEqualNode(elm)) {
return i;
}
}
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i = 0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick);
}
}
startTemplate();
JSFiddle
<script>
function navButtonClick(index) {
return function (ev) {
document.getElementById("output").innerHTML = index;
}
}
function startTemplate() {
var i;
var navItems = document.querySelectorAll("#navigation button");
for (i=0; i < navItems.length; i++) {
navItems[i].addEventListener("click", navButtonClick(i));
}
}
document.addEventListener("DOMContentLoaded", startTemplate);
</script>
Hope, it works :)
Anyway, only for buttons (I need closest in chrome even for them).
document.addEventListener('click', function (event) {
var target = event.target, nodes, i;
if (target.closest) {
target = target.closest('button');
}
if (target && target.tagName === 'BUTTON') {
nodes = target.parentElement.children;
for (i=0; nodes[i]!==target; ++i);
document.querySelector("output").textContent = i;
}
})
<nav id="navigation" role="navigation">
<button type="button"> <em>Navi tab 1</em> </button>
<button type="button"> Navi tab 2 </button>
<button type="button"> Navi tab 3 </button>
<button type="button"> Navi tab 4 </button>
</nav>
<output></output>
ES6-style answer:
const indexOf = element => Array.from(element.parentNode.children).indexOf(element)
const buttonIndex = indexOf(event.currentTarget)
I'm trying to select items from a Select list and generate a Radio list.
Let's say I have these options in a list:
abc
dab
I want to print them in a radio list like this:
(radiobutton1) abc
(radiobutton2) dab
But right now I am just getting a result like this:
(radiobutton1)(radiobutton2) abc dab
Here is my code:
HTML
<radio id = MyRadio multiple></radio>
<label id = MyLabel multiple></label>
and Javascript:
function btn2Click() {
var SelectedItems = document.getElementById("MyList");
var i;
for (i = 0; i < SelectedItems.length; i++)
{
if(SelectedItems.options[i].selected)
{
var RadioSelect = document.createElement("INPUT");
RadioSelect.setAttribute("type", "radio");
var RadioText = document.createTextNode(SelectedItems.options[i].text+'\n');
RadioSelect.appendChild(RadioText);
document.getElementById("MyRadio").appendChild(RadioSelect);
document.getElementById("MyLabel").appendChild(RadioText);
}
}
}
something like this? http://jsfiddle.net/swm53ran/101/
<div class="radioButtons">
Place Radio Buttons Here
<br/>
</div>
$(document).ready(function() {
var list = ['dog', 'cat', 'fish'];
var html = "<input type='radio'/>";
for (var i = 0; i < list.length; i++) {
$('.radioButtons').append(html + list[i] + '<br/>');
}
});
Labels work with the for attribute. The for attribute needs to refer to the id of the radio input.
if(SelectedItems.options[i].selected)
{
var RadioSelect = document.createElement("INPUT");
RadioSelect.setAttribute("type", "radio");
var RadioText = document.createTextNode(SelectedItems.options[i].text+'\n');
document.getElementById("MyRadio").appendChild(RadioSelect);
document.getElementById("MyLabel").appendChild(RadioText);
}
Change the label html to:
<label id="MyLabel" for="MyRadio" multiple></label>
HTML
<div id="myRadioButtons" />
JS
var html='';
$.each(['apply', 'pear', 'peach', 'lime'], function (i, v){
html += "<input type='radio'/>" + v + '<br/>';
});
$('#myRadioButtons').append(html);
DEMO
I would like for jQuery to dyanmically create a list of checkboxes based on the class/data present in divs. Essentially these checkboxes will filter through the products so that clicking a checkbox will show the products containing that tag in their div while avoiding any duplicate checkboxes.
Sample:
<div class="Shoes" data-size="Small" data-color="Black">
<h3>Nike</h3>
</div>
<div class="Belts" data-size="Medium" data-color="Black">
<h3>Belt</h3>
</div>
<div class="Shirt" data-size="Large" data-color="Blue">
<h3>Polo</h3>
</div>
<div class="Socks" data-size="Small" data-color="White">
<h3>Generic Socks</h3>
</div>
Expected output
Class Type
Shoes
Belts
Shirt
Socks
Size
Small
Medium
Large
Color
Black
White
Blue
Each checkbox needs to be able to hide/show the item.
JsFIDDLE
The code I have so far is from searching around/previous answers, however it is only creating 1 checkbox type which is for "class" and not creating multiple ones.
Try
jQuery(function ($) {
function createCheckboxes($els, attr) {
var props = {};
$els.each(function () {
props[$(this).attr(attr)] = true;
});
return $.map(props, function (val, key) {
var $chk = $('<input />', {
type: 'checkbox',
value: key
})
return $('<label />', {
text: key
}).append($chk)
})
}
$('span').append(createCheckboxes($('div'), 'class'))
$('span').append(createCheckboxes($('div'), 'data-size'))
$('span').append(createCheckboxes($('div'), 'data-color'))
});
Demo: Fiddle
Try this http://jsfiddle.net/LzmTA/1/
HTML
<div class="Shoes" data-size="Small" data-color="Black">
<h3>Nike</h3>
</div>
<div class="Belts" data-size="Medium" data-color="Black">
<h3>Belt</h3>
</div>
<div class="Shirt" data-size="Large" data-color="Blue">
<h3>Polo</h3>
</div>
<div class="Socks" data-size="Small" data-color="White">
<h3>Generic Socks</h3>
</div>
Javascript
$(document).ready(function(){
var goods = {};
var divs = $('div');
for(var i = 0; i < divs.length; i++){
var attributes = divs[i].attributes;
var item = {};
for(var j = 0; j < attributes.length; j++){
var attrName = attributes[j].name;
if(!goods[attrName]){
goods[attrName] = {};
}
goods[attrName][attributes[j].value] = 1;
}
}
printAttributes(goods);
console.log(goods);
});
function printAttributes(goods){
for(var group in goods){
var groupTitle = $('<h3>').text(group);
$('span').append(groupTitle);
for(var item in goods[group]){
console.log(item);
var sp = $('<label>').text(item);
var chk = $('<input>').attr('type', 'checkbox').attr('value', item).attr('attr', group);
chk.bind('change', function(){
filterGoods();
});
$('span').append(chk).append(sp);
}
}
}
function filterGoods(){
var separator = '|';
var chks = $('input[type=checkbox]:checked');
var filter = [];
//get filter
for(var i = 0; i < chks.length; i++){
var item = $(chks[i]).attr('attr') + separator + $(chks[i]).val();
filter.push(item);
}
//do filter
var hasAttr = false;
var divs = $('div');
for(var i = 0; i < divs.length; i++){
hasAttr = false;
for(var j = 0; j < filter.length; j++){
var filterParts = filter[j].split(separator);
if($(divs[i]).attr(filterParts[0]) == filterParts[1]){
hasAttr = true;
continue;
}
}
hasAttr ? $(divs[i]).show() : $(divs[i]).hide();
}
console.log(filter);
}