I am trying to use JQuery to update a data attribute after clicking on a button.
Please take a look at what I have tried below.
When I click on the div with class previous-wrapper, the whole block is well updated, and the data-nb-attribute get the correct value.
But, when I click on this div for the second time, data-nb-attribute gets the value NaN..
Is there another way to dynamically update and retrieve the value of this attribute?
$(function(){
$(document).on('click','.previous-wrapper',function(){
var get_nb = $(this).find('.previous');
get_nb = get_nb.data("nb");
get_nb = parseInt(get_nb)
//Dom to update
arr_left = $('<i/>', {
className: 'fa-solid fa-arrow-left'
});
previous = $('<div/>', {
className: 'previous',
'data-nb': get_nb-5,
html: "Previous"
});
//Question 2. How to append previous to arrow_left
$(".previous-wrapper").html(previous);
});
});
.previous-wrapper{
cursor: pointer;
background:red;
width:100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="previous-wrapper">
<i class="fa-solid fa-arrow-left"></i>
<span class="previous" data-nb="100">Previous</span>
</div>
I would also like to know how to add multiple DOM created by JQuery.
You're overwriting the HTML with an invalid attribute of "classname" instead of "class", which means on the second interation $('.previous') won't match anything.
Corrected version of your code:
$(document).on('click', '.previous-wrapper', function() {
var get_nb = $(this).find('.previous');
get_nb = get_nb.data("nb");
get_nb = parseInt(get_nb)
//Dom to update
arr_left = $('<i/>', {
class: 'fa-solid fa-arrow-left'
});
previous = $('<div/>', {
class: 'previous',
'data-nb': get_nb - 5,
html: "Previous"
});
// including both elements at once:
$(".previous-wrapper").html([arr_left, previous]);
console.log($('.previous-wrapper').html())
});
.previous-wrapper {
cursor: pointer;
background: red;
width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="previous-wrapper">
<i class="fa-solid fa-arrow-left"></i>
<span class="previous" data-nb="100">Previous</span>
</div>
It would be much, much simpler, however, to simply update the one attribute you want to update, instead of rewriting all the HTML every click:
$(document).on('click', '.previous-wrapper', function() {
let el = $(this).find('.previous')
// update the data attribute using .attr() instead of .data() because jQuery handles .data internally; it's not reflected in the DOM
el.attr('data-nb', Number(el.attr('data-nb')) - 5);
console.log($('.previous-wrapper').html())
});
.previous-wrapper {
cursor: pointer;
background: red;
width: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="previous-wrapper">
<i class="fa-solid fa-arrow-left"></i>
<span class="previous" data-nb="100">Previous</span>
</div>
Related
This question already has answers here:
Add click event on div tag using JavaScript
(6 answers)
Closed 5 years ago.
I have a <div> that I have formatted very carefully to look nice, and I need to make it have the functionality of a button. How would I go about doing this?
You can give that div tag a onclick function as follows.
function myfns() {
console.log("Clicked")
}
<div id="btn" onclick="myfns()">Click</div>
First recommendation is to use a <button> instead. You can style that however you want as well. If that is not an option for some reason, you'll have to do a few different things to create a proper button out of a div element (to ensure that it works with keyboard and screen readers).
Add click handler. Eg btn.addEventListener('click', clickHandler);
Add enter key handler. Eg btn.addEventListener('keyup', keyHandler);
Add button role. role="button"
Add it to tab order: tabindex="0"
var buttons = document.querySelectorAll('.btn');
buttons.forEach(function (btn) {
btn.addEventListener('click', function(e) {
console.log('clicked');
});
btn.addEventListener('keyup', function(e) {
if (e.key === 'Enter') {
console.log('keyup');
}
});
});
.btn {
display: inline-block;
background: #eee;
border: 1px solid #aaa;
padding: 6px;
cursor: pointer;
}
<div class="btn" role="button" tabindex="0">My Button</div>
<div class="btn" role="button" tabindex="0">My Button</div>
<div class="btn" role="button" tabindex="0">My Button</div>
document.getElementByID("#divID").addEventListenet('click',()=>{
//write your logic
})
handle all button event similarly
e.g. doubleclick etc
Like if you have div
<div class="demo" >
....
</div>
And If you are using javascript
document.getElementsByClassName('demo')[0]
.addEventListener('click', function (event) {
// do something
});
using jquery u can do like
$(".demo").click(function(){
//do something
});
What I'm looking to do is remove the parenting div by ID after the button is clicked, to avoid closing all divs with the same class. In my actual code, the user is able to append multiple divs to the screen on button click, and each is assigned it's own ID. Each has a boostrap button up top that should close the parent div only instead of having to create 12 separate functions (the limit of div placement for the user).
HTML
<div class='some classes' id='box1'>
<span class='btn btn-primary'>Close this div</span>
</div>
<div class='some classes' id='box2'>
<span class='btn btn-primary'>Close this div</span>
</div>
CSS
#box {
width:200px;
height:200px;
background:black;
}
JS
$(document).ready(function(){
$('.btn').on('click',function(){
var getParentID = $('.btn').parent().attr('id');
$(getParentID).remove();
});
});
This is essentially all I was working with to try to get it to function. Any help is much appreciated!
Use $(this) instead of $('.btn') since you want to target the specific element
var getParentID = $(this).parent().attr('id');
Once the id is available use jquery id selector to target the element
$(document).ready(function() {
$('.btn').on('click', function() {
var getParentID = $(this).parent().attr('id');
$("#" + getParentID).remove();
});
});
#box {
width: 200px;
height: 200px;
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='some classes' id='box1'>
<span class='btn btn-primary'>Close this div</span>
</div>
<div class='some classes' id='box2'>
<span class='btn btn-primary'>Close this div</span>
</div>
Note: The answer is specific to your question.Alternatively the parent div can be removed even without getting it's id
What you want to do is to skip the jQuery and do it in pure javascript.
var parent = child.parentElement;
parent.parentElement.removeChild(parent);
Initially my div (with the button inside) is hidden, when I press a button I make 10 clones of that div.
I want to be able to use each of the buttons seperatly (they all have the same attributes and class). At the moment I cannot use the any of the buttons.
<div class="search-result">
<h3>Titel(year)</h3>
<button class="btn btn-warning btnFavorite">Favorite</button>
<button id="btnArkiv" class="btn btn-warning btnFAvorite">Arkiv</button>
</div>
$(".btnFavorite").on("click", function(){
alert("hej");
var input = $("#search").val();
saveFavorite(favoriteMovie);
});
Method to clone the div x times.
for(movie in search){
console.log(search[movie].Title);
favoriteMovie = search[movie].Title;
$(".search-result:first").clone().appendTo(".search").find('h3').text(search[movie].Title);
$('#your_element').attr('id','the_new_id');
}
I've replaced the input elements with actual buttons and delegated the event to the body, so that newly inserted movie buttons automatically use the same event handler. The div cloning function can also use some updates, but it should work and that's not the question. :)
You might have to update any function that uses the value as well, since it's a data-value attribute now. Hope it helps.
PS: I don't usually use jQuery, so untested and there might be syntax errors.
<div class="search-result">
<h3>Titel(year)</h3>
<button data-value="Favoritfilm" class="btn btn-warning btnFavorite">buttonText</button>
<button id="btnArkiv" data-value="Arkiv" class="btn btn-warning">buttonText</button>
</div>
$("body").on("click", ".btnFavorite", function() {
alert("hej");
var input = $("#search").val();
saveFavorite(favoriteMovie);
});
It seems that you are using click event without using the right ID.
$(".btnFavorite") here you need to use the right ID, which is related to the button you are going to activate. In this case "btnArkiv".
var movieList = [
{
'ID': 1,
'title': 'Movie 1',
'year': 1988
},
{
'ID': 2,
'title': 'Movie 2',
'year': 2017
}
];
$(".btnFavorite").on("click", function(){
alert("hej");
var input = $("#search").val();
saveFavorite(favoriteMovie);
});
$(".btnAdd").click(function() {
for(index in movieList){
$(".list").append("<div class='search-result' data-id=" + movieList[index].ID + "><h3>" + movieList[index].title + " (" + movieList[index].year + ")</h3><button class='btn btn-warning btnFavorite' data-action='favoritize-id-" + movieList[index].ID + "'>Favorite Movie " + movieList[index].ID + "</button></div>");
}
});
.search-result {
background-color: #EEE;
padding: 20px;
margin: 15px 0;
}
.search-result h3 {
display: inline-block;
}
.search-result button {
display: inline-block;
margin: 0 0 0 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="btn btn-warning btnAdd">Show Movie List</button>
<div class="list"></div>
According to the docs for .on this is why you are finding that only your first set of buttons work after cloning the result 10 times:
Event handlers are bound only to the currently selected elements; they must exist at the time your code makes the call to .on(). To ensure the elements are present and can be selected, place scripts after the elements in the HTML markup or perform event binding inside a document ready handler. Alternatively, use delegated events to attach event handlers.
You can read more about it here: http://api.jquery.com/on/.
Since there isn't much information to go on, one way you can make all of your buttons use the same event handler is by using event delegation as CBroe mentioned in the comments.
Check out the snippet I have here with all the buttons working.
$(".search").on("click", function(e) {
if ($(e.target).hasClass('btnFavorite')) {
alert('hej');
}
});
for (var i = 0; i < 10; i++) {
$(".search-result:first").clone().appendTo(".search");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="search">
<div class="search-result">
<h3>Titel(year)</h3>
<input type="submit" value="Favoritfilm" class="btn btn-warning btnFavorite">
<input id="btnArkiv" type="submit" value="Arkiv" class="btn btn-warning">
</div>
</div>
In the snippet, I put a listener on the parent container and then check that the clicked target is the correct button before alerting.
I have a form where I am cloning the initial input fields as a template to allow the user to add as many options as they need to. Adding new fields works fine, but when attempting to remove them, the first one works as expected but all generated fields cannot be removed.
My knowledge of JS is very poor but I would assume that setting it to remove the parent should be the correct operation.
<script type="text/javascript">
$(function()
{
var template = $('#inventoryItems .inventory:first').clone(),
inventoryCount = 1;
var addInventory = function()
{
inventoryCount++;
var inventory = template.clone().find(':input').each(function()
{
var newId = this.id.substring(0, this.id.length-1) + inventoryCount;
$(this).prev().attr('for', newId); // update label for (assume prev sib is label)
this.name = this.id = newId; // update id and name (assume the same)
}).end() // back to .attendee
.attr('id', 'inv' + inventoryCount) // update attendee id
.appendTo('#inventoryItems > fieldset'); // add to fieldset
};
$('.btnAddInventory').click(addInventory); // attach event
});
$(function()
{
var removeInventory = function()
{
$(this).parent().remove();
};
$('.btnRemoveInventory').click(removeInventory); // attach event
});
</script>
HTML:
<div id="inventoryItems" class="inventoryItems" style="margin:0; padding:0;">
<fieldset style="width:62%; float:left; margin-left: 19%;">
<label>Inventory</label>
<div id="inv1" class="inventory">
<select name="invItem1" style="width:92%;">
<?php
$invItem_values = array("id", "name");
display_options_list($dp_conn, $invItem_values, "inventory", "id");
?>
</select>
<input class="btnRemoveInventory" type="button" style="background: url(images/icn_trash.png) no-repeat; cursor:pointer; border: none;">
</div>
</fieldset><div class="clear"></div>
<!-- Add Inventory Button -->
<div style="width:62%; margin:0; padding:0; float: right; margin-right: 19%">
<input class="btnAddInventory" type="button" value="Add Item" style="float: right;">
</div><div class="clear"></div>
</div>
Attaching events via click() (or any other shortcut event handler) only works with elements which are available on load of the page. Instead, because you are appending elements dynamically, you need to use a delegated event handler. Change this:
$('.btnRemoveInventory').click(removeInventory)
To this:
$('#inventoryItems').on('click', '.btnRemoveInventory', removeInventory)
This is attaching the event to the nearest static element, #inventoryItems, and then filters the events raised to see if the target matches .btnRemoveInventory.
i have the following code that i was hoping would allow me to click a button and add another box to the page but inj stread it just resets the page every time i click one of the buttons
<style>
div.box
{
width: 50px;
height: 50px;
background-image: url("Images/smallBox.jpg");
}
div.largeBox
{
width: 100px;
height: 100px;
background-image: url("Images/largeBox.jpg");
}
</style>
<script type="text/javascript">
$(function () {
setupDragging();
});
function setupDragging() {
$(".box").draggable({ snap: true });
$(".largeBox").draggable({ snap: true });
}
function addSmallBox() {
var boxArea = document.getElementById('boxArea');
var newBox = document.createElement('div');
newBox.setAttribute('class', 'box');
boxArea.appendChild(newBox);
setupDragging();
}
function addLargeBox() {
var boxArea = document.getElementById('boxArea');
var newBox = document.createElement('div');
newBox.setAttribute('class', 'largeBox');
boxArea.appendChild(newBox);
setupDragging();
}
</script>
<form>
<button onclick="addSmallBox();">small box</button>
<button onclick="addLargeBox();">large box</button>
</form>
<div id="boxArea">
</div>
please can somebody let me know what i am doing wrong and how i can achieve what i want.
ANSWER:
just an update on the final result
<style>
div.box
{
width: 50px;
height: 50px;
background-image: url("../Images/smallBox.jpg");
position: absolute;
}
div.largeBox
{
width: 100px;
height: 100px;
background-image: url("../Images/largeBox.jpg");
position: absolute;
}
</style>
<script type="text/javascript">
$(function () {
setupDragging();
$('.addBox').click(function(e){
if($(this).hasClass('smallBox')) addSmallBox();
else if($(this).hasClass('largeBox')) addLargeBox();
e.preventDefault();
})
});
function setupDragging() {
$(".box").draggable({ snap: true });
$(".largeBox").draggable({ snap: true });
}
function addSmallBox() {
$('<div>', { class: 'box' }).appendTo('#boxArea')
setupDragging();
}
function addLargeBox() {
$('<div>', { class: 'largeBox' }).appendTo('#boxArea')
setupDragging();
}
</script>
<form>
<button class='addBox smallBox'>small box</button>
<button class='addBox largeBox'>large box</button>
</form>
<div id="boxArea">
</div>
i made use of several of the answers below and this was the final result but went down the html5 route in the end.
First of all, since you are using jQuery, if I were you, I would not use the onclick attribute in your button. Instead, add an event listener like so:
$('button').click(function(){
addLargeBox();
return false;
});
OR
$('button').click(function(e){
addLargeBox();
e.preventDefault();
});
Both of which will prevent the user's browser from following the link but will execute the JavaScript as you want.
Also, since you require two different functions to be executed depending on which button is clicked, you should probably add a class or id to differentiate the two.
Your markup would then look like this:
<button class="add-box">small box</button>
<button class="add-box large-box">large box</button>
And your JavaScript would be:
$('.add-box').click(function(){
if ($(this).hasClass('large-box')) addLargeBox();
else addSmallBox();
return false;
});
The button tag you are using is a HTML5 version of a form submit button which causes a page refresh.
Change the buttons to:
<input type="button" onclick="addSmallBox();" value="small box" />
Or put return false at the bottom of each of your javascript functions.
Couple of things:
Always separate JS from code (that means lose the onclick attributes and bind them in javascript instead.)
The form is still being submitted; have your functions return false/preventDefault (jQuery) to avoid this.
Some hints:
Since you're already using jQuery, why not build html elements with it? ($('<div>',{class:'box'}).appendTo('#boxArea') for instance)
You have to return false from the click event to prevent the default browser behavior of following the link.
I'm not sure why just by glancing at the code, but perhaps you could try retrieving the boxArea.InnerHTML, appending the appropriate HTML string to it, and setting the boxArea.InnerHTML to the result.
Something like:
boxArea.InnerHTML = boxArea.InnerHTML + "<div class='largeBox'></div>";