I'm trying to read an attribute in my JavaScript-Function, so I can then further call a DELETE via AJAX with this attribute, but I already fail with retrieving the attribute by, what appears to me as, random. (jQuery version used for that is 3.2.1)
The "button" to start that chain (also already tried without the href and with href="#"):
UPDATE: Since it appeared as a comment, I indeed have something within the a-tag
<a class="btn btn-light delete-record" href="" data-id="5c25f547d42" title="Delete">
<i class="fa fa-trash"></i>
</a>
My JavaScript:
$(document).ready(function(){
$('.delete-record').on('click', function(e){
$target = $(e.target);
var id = $target.attr('data-id');
if(confirm('Entry with ID ' + id){
//AJAX
}
});
});
During testing with the confirm, I found out that my ID is sometimes set to undefined. Sadly I have no clue how this sometimes works and shows me the ID, and sometimes not.
Is there a solution to make this work with every click and not only about 24 out of the 42?
The issue is that when you click the icon inside the hyperlink, that the event bubbles up to the click handler. Inside the click handler, event.target will then refer to the icon element, which does not have the data-id attribute.
So the solution is to either:
1) Move the click event onto the icon and then make sure the hyperlink does not have any padding or other CSS styles that make the <a> clickable without also clicking the <i>.
2) Or check for which node was clicked inside the event:
var $target = $(e.target);
var id = $target.prop('tagName') === 'I'
? $target.parent().attr('data-id')
: $target.attr('data-id');
if (!id ) {
console.error( $target );
throw new Error( 'cannot find the correct id for target' );
}
else {
var is_correct_id = confirm( 'Entry with ID ' + id );
if ( is_correct_id ) {
//createAjaxCall( 'DELETE', 'somePath', id );
}
}
There are other methods to find the correct parent element, in case one day you change the structure and the icon is not an immediate child of the hyperlink anymore. But I don't use JQuery anymore, so I'll leave searching for the correct syntax for .findParent( 'a[data-id]' ) up to the implementer.
3) Or as you demonstrate, duplicate the id onto the icon. :)
The answer is actually based on Shilly's comment to the question.
Since I indeed got another element within my a-tag, the target was different depending on where I clicked the link/button. As an easy fix for that, I simply appended the ID to the i-tag as well:
<a class="btn btn-light delete-record" href="" data-id="5c25f547d42" title="Delete">
<i class="fa fa-trash" data-id="5c25f547d42"></i>
</a>
Did you tried to href="javascript" and also this could return list of elements so try to put the listener using an id like this
<a class="btn btn-light delete-record" id="deleteButton" href="" data-id="5c25f547d42" title="Delete">
$(document).ready(function(){
$('#deleteButton').on('click', function(e){
e.stopPropagation();
$target = $(e.target);
var id = $target.attr('data-id');
if(confirm('Entry with ID ' + id){
//AJAX
}
});
});
You should change your JS + HTML to this:
HTML
<button class="btn btn-light delete-record"
data-id="5c25f547d42"
title="Delete">
Click me!
</button>
Your problem with using <a> is that you don't stop the defaul behaviour of the <a> tag - which is a link. It's just refreshing the page (if you leave href blank). Changing it to a button is much better, as it's .. well a button in principle.
jQuery
jQuery(document).ready(function($)
{
$('.delete-record').click(function()
{
let id = $(this).attr('data-id');
if (confirm('Entry with ID '+ id)) {
//whatever
}
});
})
You don't need to get the target, just use $(this) to get the clicked element's data-attribute. Then carry on script as normal
You could try specifying the role of the anchor tag to button. Then you won't have to worry about specifying the href as the anchor tag will be treated as button.
https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role
Use event.preventDefault() as first line in your callback function for "click" or you'll be redirected to link or just reloaded.
<a class="btn btn-light delete-record" id="btnDelete" title="Delete">
$(document).ready(function(){
$('#btnDelete').on('click', function(e){
e.stopPropagation();
$target = $(e.target);
var id = $target.attr('data-id');
if(confirm('Entry with ID ' + id){
//AJAX
}
});
});
Or you can try
<a class="btn btn-light delete-record" id="btnDelete" href="javascript:DeleteRecord()" title="Delete">
<script>
function DeleteRecord(){
//Do your code here
}
</script>
Since you are tracking the click you should prevent the default behaviour of the click, so do like this:
$('.delete-record').on('click', function(e){
e.preventDefault();
(...)
});
you don't need to use the target, you can get the data attribute directly.
if you want to use a vanilla js approach:
document.addEventListener("DOMContentLoaded", function () {
//const records = document.querySelectorAll('.delete-record');
Array.from(document.querySelectorAll('.delete-record')).forEach(elem =>{
elem.addEventListener('click', function(e){
//don't do the default link behaviour
e.preventDefault();
const id = this.dataset.id;
console.log('Entry with ID :' + id);
//use your jquery here
});
})
});
<a class="btn btn-light delete-record" href="" data-id="5c215f547d42" title="Delete">link1</a>
<a class="btn btn-light delete-record" href="" data-id="eeee5c1125f547d42" title="Delete">link2</a>
<a class="btn btn-light delete-record" href="" data-id="cccc5c25f431547d42" title="Delete">link3</a>
<a class="btn btn-light delete-record" href="" data-id="bbbbb5c2345f547d42" title="Delete">link4</a>
<a class="btn btn-light delete-record" href="" data-id="111115c25f547d42" title="Delete">link5</a>
Personally i had some problems with data attributes and jQuery so i try to avoid using jquery for that. So you can use this and use the ajax call with the id on the variable.
Have a look on my example, it should cover your problem:
$(document).ready(function(){
// assuming you're adding/removing .delete-record elements you should bind click on body
$('body').on('click', '.delete-record', function(e){
e.preventDefault(); // prevent default action
var id = $(this).attr('data-id') || false; // i removed $target, you don't need it
if( id !== false ){ // if id exists
if(confirm('Entry with ID ' + id){
//AJAX
}
}else{ console.log('id is invalid', id, typeof id); }
});
});
Use jQuery .data() function:
<a class="btn btn-light delete-record"
href=""
data-id="5c25f547d42"
title="Delete">
Delete
</a>
$(document).ready(function () {
$('.delete-record').on('click', function (e) {
$target = $(e.target);
var id = $target.data('id');
if (confirm('Entry with ID ' + id)) {
// AJAX
}
});
});
Related
I'm a little stuck on the follow issue. I have a webpage that has a button when clicked it does some ajax things and if the result/response of that is successful then the buttons class is changed.
What I then want, if that changed button is clicked again, I want it to call a different function.
The first part works no problem. The ajax is called and the buttons class is changed so the colour and text of the button is changed. But when click the button again, I want to call the .btn.off function, but it remains to call the .btn.on function while I would have hoped it would call the .btn.off function.
Unfortunately, my knowledge of jQuery is not the best, any help in the right direction would be very much appreciated.
Thank you so much.
<button type="button" class="btn on btn-danger" id="123"><i class="fa fa-trash-o"></i><span>On</span></button>
<script>
$(document).ready(function(){
$(".btn.on").click(function(){
//do some ajax stuf.....
$(this).removeClass('btn on btn-danger').addClass('btn off btn-success btn-sm');
$("span", this).text("Off");
});
$(".btn.off").click(function(){
//do some ajax stuf.....
$(this).removeClass('btn off btn-danger').addClass('btn on btn-danger btn-sm');
$("span", this).text("On");
});
});
</script>
$('.btn').click(function () {
var btn = $(this);
var isOn = btn.hasClass('on');
if (isOn) {
// do something maybe call on function or write logic for on
} else {
// do something maybe call off function or write logic for off
}
btn.toggleClass('on off'); // flip the on <-> off switch
$('span', this).text(isOn ? 'Off' : 'On'); // was on before toggle so flipped
})
You can do this by checking the classes and take action
The issue is because you're dynamically changing the classes on the element at runtime. One way to work around this is to use delegated event handlers, like this:
jQuery(function($) {
$(document).on('click', '.btn.on', function() {
// AJAX...
$(this).removeClass('on btn-danger').addClass('off btn-success btn-sm').find('span').text('Off');
});
$(document).on('click', '.btn.off', function() {
// AJAX...
$(this).removeClass('off btn-danger').addClass('on btn-danger btn-sm').find('span').text('On');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" />
<button type="button" class="btn on btn-danger" id="123">
<i class="fa fa-trash-o"></i>
<span>On</span>
</button>
I want to create a link (in form of a Bootstrap button) that works only on the second click; on the first click it is supposed to change its appearance a bit. For this I use .addClass(newClass), .removeClass(oldClass), and then attr("href", newUrl).
(Edit) To clarify: In the beginning, the link (anchor) has "#" as its href target, and an onlick handler. That handler, when executed on the first click, will remove itself from the anchor, and instead set the desired target URL in the hrefattribute. That is supposed to cause the link to only redirect to its target URL on the second click.)
This almost works, but only if I omit the attr() setting. When it is there, the class reverts to the old class of the link as soon as the script exits. When I step through it in the debugger, the link briefly changes its appearance as expected, but changes back when the event handler exits.
This is the HTML code:
<a id="twoclick-vjffkrzw" onclick="enabletwoclickbutton('twoclick-vjffkrzw',
'http://localhost/something.php?cmd=admin&func=userdetail&pk=53&action=removerole&rolepk=1')"
class="btn btn-xs btn-warning" href="#">Remove this</a>
The script:
function enabletwoclickbutton(btn_id, url) {
var whichbtn = '#' + btn_id;
var btn = $(whichbtn);
if (btn.hasClass("btn-warning")) {
btn.off("click");
btn.attr("href", url);
btn.removeClass('btn-warning');
btn.addClass('btn-danger');
} else {
console.log("Hey, this shouldnt happen.");
}
}
I'm not very experienced in JS and jQuery, so it's quite possible that this is a stupid mistake on my side, but I just can't see it.
Use e.preventDefault() to avoid the default behavior of anchor.
Your way (however I recommend you to go with one below for readability and easy to modify later.)
html
<a id="twoclick-vjffkrzw" onclick="enabletwoclickbutton(event,'twoclick-vjffkrzw', 'http://localhost/something.php?cmd=admin&func=userdetail&pk=53&action=removerole&rolepk=1')" class="btn btn-xs btn-warning" href="#">Remove this</a>
js
function enabletwoclickbutton(e,btn_id, url) {
var whichbtn = '#' + btn_id;
var btn = $(whichbtn);
if (btn.hasClass("btn-warning")) {
e.preventDefault();
//btn.off("click");
btn.attr("href", url);
btn.removeClass('btn-warning')
.addClass('btn-danger');
} else {
console.log("Hey, this shouldnt happen.");
}
}
Recommended
Do not mix your javascript and html which is very hard to read as you can see in your code. You can write the entire code in javascript only
eg.
$('#twoclick-vjffkrzw').click(function(e){
var btn = $(this);
if (btn.hasClass("btn-warning")) {
e.preventDefault();
//btn.off("click");
btn.attr("href", 'http://localhost/something.php?cmd=admin&func=userdetail&pk=53&action=removerole&rolepk=1');
btn.removeClass('btn-warning');
btn.addClass('btn-danger');
} else {
console.log("Hey, this shouldnt happen.");
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="twoclick-vjffkrzw" class="btn btn-xs btn-warning" href="#">Remove this</a>
First add return false; after the onclick function call to stop the default redirect. Then in your function you can set the onclick to null so that it isn't called a second time.
function enabletwoclickbutton(btn_id, url) {
var whichbtn = '#' + btn_id;
var btn = $(whichbtn);
if (btn.hasClass("btn-warning")) {
btn.off("click");
btn.attr("href", url);
btn.removeClass('btn-warning');
btn.addClass('btn-danger');
btn.attr('onclick', null);
} else {
console.log("Hey, this shouldnt happen.");
}
}
.btn-warning {
color: orange;
}
.btn-danger {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a id="twoclick-vjffkrzw" onclick="enabletwoclickbutton('twoclick-vjffkrzw',
'http://localhost/something.php?cmd=admin&func=userdetail&pk=53&action=removerole&rolepk=1');return false;" class="btn btn-xs btn-warning" href="#">Remove this</a>
you have to check if it is the first time you click the button. to do this you can use a variable . check the code below
var clk=0;
function enabletwoclickbutton(btn_id, url) {
if(clk==0){
clk++;
}else{
clk=0;
var whichbtn = '#' + btn_id;
var btn = $(whichbtn);
if (btn.hasClass("btn-warning")) {
btn.off("click");
btn.attr("href", url);
btn.removeClass('btn-warning');
btn.addClass('btn-danger');
} else {
console.log("Hey, this shouldnt happen.");
}
}
check jsfiddle
I'd use data attribute to store url value (added my-btn class for clarity)
<a data-action="http://localhost/something.php?cmd=admin&func=userdetail&pk=53&action=removerole&rolepk=1" class="btn btn-xs btn-warning my-btn" href="#">Remove this</a>
Then set click function with jQuery instead of using onClick attribute (as it's not good practice):
$('.my-btn').click(function(event){
// prevent default click action:
event.preventDefault();
if ($(this).hasClass("btn-warning")) {
$(this).removeClass('btn-warning').addClass('btn-danger');
}else{
// go to url on a second click:
location.href = $(this).data("action");
}
});
EDIT (#A.Wolff comment)
BTW.: Checking the existence of btn-warning class is actually pointless. The click event won't be handled at the second click anyway...
$('.my-btn').click(function(event){
event.preventDefault();
$(this).removeClass('btn-warning').addClass('btn-danger')
.off('click').attr('href', $(this).data("action"));
});
With input from the various answers, I was able to find out what was happening.
Apparently the changed href will be executed only after the the event handler exits. Since in my configuration by chnce it redirected to the same page, the page was actually reloaded, that's why the button/link got its original appearance back and that tricked me into believing that the attr() setting didn't work right.
The key was to simply call event.preventDefault() before setting the new URL.
Some of you recommended (directly or indirectly) to generate the button click handler in JS directly. I don't think this would make the code better readable (the only thing that made the HTML unreadable is the long URL.) As the HTML is generated dynamically, this wouldn't be a practical solution anyway.
So, the finalized code looks like this:
function enabletwoclickbutton(e, btn_id, url) {
var whichbtn = '#' + btn_id;
var btn = $(whichbtn);
if (btn.hasClass("btn-warning")) {
e.preventDefault();
btn.off("click");
btn.attr("href", url);
btn.removeClass('btn-warning');
btn.addClass('btn-danger');
} else {
console.log("Hey, this shouldnt happen.");
}
}
Now it works as exected.
I am trying to dynamically set a click function on a role=button element I add from jQuery. Here is my code:
box_resources.forEach(function(box){
var title_button = '<a class="btn btn-primary btn-xs" style="margin:5px">' + title + '</a>';
var $list_item = $(title_button);
$list_item.click(function() {
console.log("hello");
});
$("#resources-master-list").append(title_button);
});
It seems this way does not work. Does anyone have any idea? Thanks!
Instead of adding a new click handler each time you add an item to the DOM, try using event delegation. To understand how this works, check out the link for more information.:
$(document).on("click", "[role='button']", function () {
alert("i'm clicked");
});
I call call ajax and when success i build button elements.
Like this :
...
.done(function(data) {
$('#data-message').empty();
// console.log(data);
$('#total_notification_msg').html(data.total);
$.each(data.data, function(index, value) {
// console.log(value);
var redirectRead = '{{ route("adm1n.message.show", ":id") }}'
redirectRead = redirectRead.replace(":id", value.id);
var pesan = value.message.substr(0,100);
$('#data-message').append('<button id='reply' class='btn btn-default btn-xs' style='margin-top:5px;'>Reply</button>");
});
})
...
But, i can't add click event on #reply button.
I already using on or click event :
$(document).on('click', '#reply', function() {
alert('Reply here');
});
// or this ...
$('#reply').click(function() {
alert('Reply here');
});
But it still not works.
Please help, thank you ^^
You need to use quotes properly when creating elements using string.
$('#data-message').append('<button class="reply btn btn-default btn-xs" style="margin-top:5px;">Reply</button>");
And use Event Delegation using .on() delegated-events approach, when generating elements dynamically
$('#data-message').on('click', '.reply', function() {
alert('Reply here');
});
Since Identifiers must be unique, use class instead.
You need to change two things:
correct quotes.
change id to class.
$('#data-message').append("<button class='btn btn-default btn-xs reply' style='margin-top:5px;'>Reply</button>");
//-----------------change here-----------------------------------^^^^^
Because you are in loop and you are duplicating same ids.
change your event binding to class:
$(document).on('click', '.reply', function() {
alert('Reply here');
});
Hey guys I have some jquery code that adds a row to a table with a link to remove it and return it back to the select. Here's the code:
$('#addUser').on('click', function (e) {
var selectedUser = $('#Utilizadores option:selected').text();
$('#tabela > tbody:last').append('<tr id="'+selectedUser+'"><td>' + selectedUser + '</td><td><a id="removeUser" href="#" class="btn btn-default btn-xs"><i class="glyphicon glyphicon-remove"></i></a></td></tr>');
$("#Utilizadores option[value='" + selectedUser + "']").remove();
e.preventDefault();
});
It works! But now I want to do the reverse action of this. So I was just tying it out and not even the alert goes off. Here's the remove code:
$('#removeUser').on('click', function (e) {
alert('teste');
e.preventDefault();
});
The same id I gave to the <a> tag but still nothing gets called. I inspect the element and the id is corret and everything.
Does anyone know what the problem is?
To anyone who stumbles here and doesn't see the warning above!
You can check a Question for the same problem here
Try using the live() method
$('#removeUser').live('click', function (e) {
alert('teste');
e.preventDefault();
});