Adding dynamic second class Jquery - javascript

I'm trying to add a second class to a group of buttons using a for loop in jQuery, with the second class set to the number of the current iterator(i). The first class for each button is assigned to "users". I want each button to have a dynamic second class so that when clicked, I can use its second class as an index to access a particular key in an object.
The problem I'm having is that each button has its second class set to 0. "users" is an array with length 4, so the buttons should have as their second class 0,1,2,3 in order.
$(document).ready(function(){
for(var i = 0; i < users.length; i++) {
var $currentUser = $('<button class="users '+ i +'"></button>');
$currentUser.text(users[i]);
$currentUser.appendTo('.userList');
}
$(".users").click(function() {
alert($(".users").attr('class').split());
// Alert returns "users 0" for each button.
});
});
The alert at the bottom is just a placeholder for now to check that the classes are set correctly. Thanks!

change code to below . change $(".users") to $(this) when you click on element.
$(".users").attr('class') always return all button element.
$(".users").click(function() {
alert($(this).attr('class').split());
});

When you use a getter method like .attr('class') on a set of elements, it will return the value of the first element in the set. when you say $('.users') it will return all elements with the class users.
In your case you want to have reference to the clicked button, which is available in the click handler as this so you can
$(document).ready(function() {
var users = ['u1', 'u2', 'u3']
for (var i = 0; i < users.length; i++) {
var $currentUser = $('<button class="users ' + i + '"></button>');
$currentUser.text(users[i]);
$currentUser.appendTo('.userList');
}
$(".users").click(function() {
alert(this.className.split(/\s+/));
alert(this.classList); //for ie 10+
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="userList"></div>

Related

How to remove a class form from the previous and the next sibling label of the currently active label with javascript

I have a function to add a class civil-active to the label that is clicked. When the next label is clicked the class is added to it too, naturally. But I want the class civil-active to be there only on the clicked label and get it removed from its previous and next sibling if present.
the code that is adding the class is
js
var labels = document.getElementsByTagName("label");
for (let i = 0; i < labels.length; i++) {
labels[i].addEventListener("click", addclass);
}
function addclass(event) {
event.target.classList.add("civil-active");
}
Please suggest me what should I do
In the event handler, find the element having the class and remove it.
function addclass(event) {
// Those lines will remove the class on the element that has it (if there is one)
let active = document.querySelector(".civil-active")
if(active){
active.classList.remove("civil-active");
}
event.target.classList.add("civil-active");
}

Apply eventlistener to multiple elements based on their IDs

I have two buttons defined with their IDs : but-toggle, but-close for show hide a panel :
<button id="but-toggle">Panel</button>
<div id="main-panel" style="display:none">
<button id="but-close">X</button>
<!-- some panel data -->
</div>
Now i have a JS function which toggle the panel (show/hide) assigned to but-toggle as following :
(function(){document.getElementById("but-toggle").addEventListener("click",function(){
var pan = document.getElementById("main-panel");
if(pan.style.display==="inline-block")
{pan.style.display="none"}
else
{pan.style.display="inline-block"}
});})();
My question is how to use the same function for both buttons without writing two func, one for each.
I want a solution for elements based on their ids, since the classes are differents and can't use getElementByClass for this
Thanks
You can use document.querySelector to get a list of elements from a list of IDs:
function toggleFn() {
const pan = document.getElementById("main-panel");
if(pan.style.display === "inline-block") {
pan.style.display = "none";
} else {
pan.style.display = "inline-block";
}
}
document.querySelector("#Id1, #Id2")
.forEach(elem => elem.addEventListener(toggleFn);
You can use the below to get all buttons
var btns=document.getElementsByTagName('button');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
//code
});
}
(OR)
if you use input tag with type button
document.querySelectorAll("input[type=button]");
(OR)
Based on multiple IDs
document.querySelectorAll('#id1, #id2, #id3');
then you can add eventListener

Using Jquery to dynamically create Divs with Buttons that have a function to close the div

So I am trying to create new divs of a fruit, but I am added an X to help call a special function that will delete it. My only problems is when I dynamically create my div+span I end up with problems when I try to use the onclick function
Here is my HTML code
<html>
<div id="listContents">
</div>
</html>
Also below is my script code
list = ["apple", "strawberry", "banana"]
for(var i = 0; i < list.length; i++){
$("#listContents").append('<div>' + list[i] + '<span class="picker" id="close" onclick="removeFruit(list[i].toString())"> (X)</span></div>');
}
function removeFruit(fruit){
console.log("Here is the fruit you selected");
}
Obviously I want to be able to delete these when the X button is clicked but right now I am having trouble getting the onclick function to work correctly. Also here is a jsfiddle I quickly made
You are creating an span with id close for each item in your list. Ids should be unique throughout the whole document. Since you are not using the id attribute, I suggest you delete it.
Also, you are appending an onclick event in all your span items. I would use event delegation.
Furthermore, since you are converting the elements in your array into HTML elements, you could use map method to do the transformation and generate all the HTML for your items.
Lastly, you can add a data attribute to account for the item index. You can then read that attribute using jQuery data method.
Having that into account, the code could look like:
var list = ["apple", "strawberry", "banana"];
var $list = $("#listContents");
$list.on('click', '.picker', function(ev) {
var idx = $(ev.target).data('idx');
removeFruit(list[idx]);
});
$list.append(list.map(function(item, idx) {
return '<div>' + item + '<span class="picker" data-idx="' + idx + '"> (X)</span></div>';
}).join(''));
function removeFruit(fruit) {
console.log("Here is the fruit you selected");
}
Similar to what others are saying, id should be reserved for only one-time use.
Also, when you are dynamically creating the items you give each onClick the string "removeFruit(list[i].toString())" so it is not actually looking for a function called removeFruit but instead it has the actual string "removeFruit".
When creating the html you could instead give each item a fruitName attribute equal to the fruit name like so.
list = ["apple", "strawberry", "banana"]
for (var i = 0; i < list.length; i++) {
$("#listContents").append('<div>' + list[i] + '<span class="picker" fruitName='+ list[i] + '>(X)</span></div>');
}
and then we can target these using a click listener rather than an onClick and use what fruitName is equal to by using the $(this).attr('fruitName').
$("#listContents").on('click', '.picker', function(e) {
removeFruit($(this).attr('fruitName'))
})
function removeFruit(fruit) {
console.log('You clicked ' + fruit);
}
$(this) will reffer to whichever span you clicked on and the .attr() will look for the fruitName and find what it is equal to.
you could add the id while you are doing the map.
["apple", "strawberry", "banana"].map(x => {
$("#listContents").append(`<div id="${x}">
${x}
<span
class="picker"
onclick="(() => document.getElementById('${x}').remove())()">
(X)
</span>
</div>`)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="listContents">

Need JQuery or JavaScript to use .contains() with && logic

I am attempting to build a simple narrow by filter using given key word buttons on an otherwise static list of items.
The buttons are in an unordered list and when selected get the class ".selected-tag-button" added to them.
The items are divs with class ".item" and get class ".included-item" when they are active. Inside the div is another UL with list items that contain key words that match the text node on the buttons.
Right now it is working, except, instead of using "buttonName" which contains only the key word for the clicked button, I would like to use "buttonArray" which contains an array of all the selected key words.
I assume I will need some kind of function, but I am not sure where to start. If more than one are selected I want the result to be limited to only items that contain ALL of the selected key words. All of the solutions I have been able to figure out will return the divs that contain ANY of the key words in the array.
$(document).ready(function() {
$("li.tag-button").on("click", function() {
// Toggle button
$(this).toggleClass("selected-tag-button");
// Remove included-item class from all items
$(".item" ).removeClass("included-item");
// Pass the button text into variable
var buttonName = $(this).text().slice(2);
// Create array with button text for all active buttons
var buttonArray = $(".selected-tag-button").map(function() {
return $(this).text().slice(2);
}).get();
console.log(buttonArray);
// Add included-item class to divs containing the button text
$('li:contains("' + buttonName + '")').parents().parents().addClass("included-item");
// If all buttons are inactive, add included-item class to all items
if ($(".selected-tag-button").length == 0 ) {
$(".item" ).addClass("included-item");
}
});
});
Consider this fiddle:
http://jsfiddle.net/6qavvth8/
for(i=0; i<buttonArray.length;i++){
contains += ':contains("' + buttonArray[i] + '")';
}
$('ul' + contains).parents().addClass("included-item");
Loop through your button array to build your jquery selector and keep adding :contains()
Slight modification of #bingo's solution. Works perfectly, thanks.
$(document).ready(function() {
$("li.tag-button").on("click", function() {
// Toggle button
$(this).toggleClass("selected-tag-button");
// Remove included-item class from all items
$(".item" ).removeClass("included-item");
// Create array with button text for all active buttons
var buttonArray = $(".selected-tag-button").map(function() {
return $(this).text().slice(2);
}).get();
// Add included-item class to divs containing the button text
var contains = "";
for(i = 0; i < buttonArray.length; i++){
contains += ':contains("' + buttonArray[i] + '")';
}
$('ul' + contains).parents().addClass("included-item");
// If all buttons are inactive, add included-item class to all items
if ($(".selected-tag-button").length == 0 ) {
$(".item" ).addClass("included-item");
}
});
});

Creating a click function from a select element

I'm having some trouble creating a JavaScript function using an select element and id link. The function should depend on the selected option/value of the select dropdon.
What I want to do, is call an event function when the select dropdown is clicked, then apply a class to the appropriate id.
The html is this:
<select class="select-trigger" >
<option value="value1">Value1</option>
<option value="Value2">Value2</option>
<option value="Value3">Value3</option>
</select>
And the elements to get a class added:
<div id="value1"></div>
<div id="value2"></div>
<div id="value3"></div>
And my function so far (almost working):
var trigger = document.querySelectorAll('.trigger');
for (var i =0; i < trigger.length; i++) {
var btn = trigger[i];
btn.addEventListener('click', function () {
var id = this.options[this.selectedIndex].value;
document.querySelector('#' + id).classList.toggle('active');
}, false);
}
I think the trouble I'm having is that I'm calling the function using click event listener. I guess I would need to use an onchange function instead?
Also I only want a single div to have an "active" class at any given time. At the moment, the function is adding the class but not removing it when another is selected.
Here's a fiddle http://jsfiddle.net/2Rcjt/1/
Note - I don't want to put any inline onclick JS in my markup.
You can save the last selected option (div) into some property of the select. Then each time user change the option, just toggle class on the last selected option to make it inactive. Code:
var trigger = document.querySelectorAll('.trigger');
for(var i = 0; i < trigger.length; i++){
trigger[i].onchange = function(){
if(this.lastOption) this.lastOption.classList.toggle('active');
this.lastOption = document.getElementById(this.value);
this.lastOption.classList.toggle('active');
};
trigger[i].onchange();
}
Demo.

Categories