My Code-igniter view has AJAX data as follows. DIV article-data contents list of DIVs.(working perfect) Now i want to each DIV as a button and where i put button click event. Where i put following code.
$(".target").click(function () {
});
JS
$(window).load(function() {
$.ajax({
url: '<?php echo base_url(); ?>' + 'main/data',
dataType: "JSON",
type: "POST",
success: function(retdata) {
$.each(retdata, function(i) {
var content = '<div class="target btn-default">' + retdata[i].content + '</div>';
$(".article-data").append(content); //line 23
});
}
});
});
<div class="article-data">
</div>
You should use Event Delegation using .on() delegated-events approach, when generating elements dynamically. You don't need to bind event in success block.
The delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, we can use delegated events to bind the click event to dynamically created elements and also to avoid the need to frequently attach and remove event handlers.
General Syntax
$(document).on('event','selector',callback_function)
In place of document you should use closest static container.
Example
$(function() {
$(".article-data").on('click', ".target", function() {
//Your code
});
})
$(function() {
$(".article-data").on('click', ".target", function() {
//Your code
});
})
$(window).load(function() {
$.ajax({
url: '<?php echo base_url(); ?>' + 'main/data',
dataType: "JSON",
type: "POST",
success: function(retdata) {
$.each(retdata, function(i) {
var content = '<div class="target btn-default">' + retdata[i].content + '</div>';
$(".article-data").append(content); //line 23
});
}
});
});
<div class="article-data">
</div>
A good read Direct and delegated events
Just use event delegation. It will bind the event to items added to DOM even after the document is ready.
$(document).on('click', ".target", function () {
});
Related
I'm using below code. This is bootstrap 3 delete conformation message.
$(document).ready(function(){
$('a.btnDelete').on('click', function (e) {
e.preventDefault();
var id = $(this).closest('div').data('id');
$('#myModal').data('id', id).modal('show');
});
$('#btnDelteYes').click(function () {
var id = $('#myModal').data('id');
var dataString = 'id='+ id ;
$('[data-id=' + id + ']').parent().remove();
$('#myModal').modal('hide');
//ajax
$.ajax({
type: "POST",
url: "delete.php",
data: dataString,
cache: false,
success: function(html)
{
//$(".fav-count").html(html);
$("#output").html(html);
}
});
//ajax ends
});
});
This is the trigger element that I'm using
<div data-id="MYID"><a class="btnDelete" href="#">Delete</a></div>
And I'm using the same HTML element dynamically to trigger delete and it doesn't work.
Can someone point me the correct way to do it?
You have to use event delegation
$(document).on("click" , '#btnDelteYes' ,function () {
Pretty much: bind the click higher up to something that exists when the script is run, and when that something is clicked, tell it to pass the click event to the #btnDelteYes element instead
I cant understand what exactly you are doing on your code due to missing information, but the answer is: you should use event delegation on the dynamically inserted content
you can try
$('[data-id=MYID]').on('click','.btnDelteYes',function({
e.preventDefault();
var id = $(this).closest('div').data('id');
$('#myModal').data('id', id).modal('show');
});
here <div data-id="MYID"> should be a hard coded html content and The idea is to delegate the events to that wrapper, instead of binding handlers directly on the dynamic elements.
Hi I have written a GSP and Javascript code to perform on click remove file functionality.
JavaScript code
function remove(attachmentId) {
$(document).ready(function(){
$('.glyphicon-remove').click ( function(e){
e.preventDefault();
$(this).parent().parent().remove();
$.ajax({
url: "${g.createLink(controller: "landing", action: "deleteSelectedFile")}",
data: {
attachmentId: attachmentId
},
success: function(data){
alert("Success");
}
});
});
});
}
GSP Code
<g:each in="${fileList}" var="file">
<div>
<a href="#" onclick="remove('${file.attachmentId}')">
<span class="glyphicon glyphicon-remove"></span></a>
<a href="/forms/landing/attachment/${file.attachmentId}" >${file.name}</a>
</br>
</div>
</g:each>
Groovy Code
def deleteSelectedFile() {
String attachmentId= params.attachmentId
activitiService.deleteAttachemnt(attachmentId)
}
I am not getting why exactly it is taking double click for deleting the first record.
Please help me.
Note: Application is running in Internet Explorer.
The issue is you have bound a click event in a function. Because you have not called that function at page load, it is registering the click event on first click and on second click, it is getting executed.
To overcome this issue you have two ways either just use your inline handler and just call the ajax, don't try to bind any click in it:
function remove(attachmentId, elem) {
$(elem).parent().remove();
$.ajax({
url: "${g.createLink(controller: "landing", action: "deleteSelectedFile")}",
data: {attachmentId: attachmentId},
success: function(data){
alert("Success");
}
});
}
and in the view you have to pass this in the function:
<a href="#" onclick="remove('${file.attachmentId}', this)">
Second way is to use event delegation syntax:
$(static-parent).on(event, selector, callback);
so if you update your function as above and remove the inline event handler from the view and use data-* attribute. you can use it this way:
<a href="#" data-attachmentId='${file.attachmentId}'>
function remove() {
var attachmentId = $(this).parent().data('attachmentId');
$(this).closest('div').remove();
$.ajax({
url: "${g.createLink(controller: "landing", action: "deleteSelectedFile")}",
data: {attachmentId: attachmentId},
success: function(data){
alert("Success");
}
});
}
$(document).on('click', '.glyphicon-remove', remove);
I think removing the $(document).ready(function() {...}) part as well as $('.glypeicon-remove') part from the remove function but keeping the stuff happening inside of these untouched, should fix your problem.
So your code should look like:
JavaScript:
function remove(attachmentId) {
$(this).parent().parent().remove();
$.ajax({
url: '${g.createLink(controller: '
landing ', action: '
deleteSelectedFile ')}',
data: { attachmentId: attachmentId },
success: function (data) { alert('Success'); }
});
}
Hope this helps.
The problem is, in your case the jQuery event handler is registered only after the first click, so in the second click the event handler is getting triggered.
Looks like you are dealing dealing with dynamic elements. In that case instead of using inline event handlers use event delegation and remove the inline event handler
<a href="#" class="delete-attachment" data-attachment-id="${file.attachmentId}">
then
$(document).ready(function(){
$(document).on('click', '.delete-attachment', function(e){
e.preventDefault();
$(this).parent().parent().remove();
$.ajax({
url: "${g.createLink(controller: "landing", action: "deleteSelectedFile")}",
data: {
attachmentId: $(this).data('attachment-id')
},
success: function(data){
alert("Success");
}
});
});
I am not sure its working or not but as per jQuery rules try below code.
function remove(attachmentId) {
$(document).on('click','.glyphicon-remove', function(e){
e.preventDefault();
$(this).parent().parent().remove();
$.ajax({
url: "${g.createLink(controller: "landing", action: "deleteSelectedFile")}",
data: {
attachmentId: attachmentId
},
success: function(data){
alert("Success");
}
});
});
}
So I'm just getting started with event delegation and I'm still fairly confused by it but here goes:
I have a button which adds a rating in ajax, once clicked again I'd like it to remove the rating, here's the code with annotations (and some parts removed to make it look more clear).
$(document).on("click", '.add_rating', function() {
l.start();
var input = $(this).prev().children('.my_rating');
var score = input.val();
var what_do = input.attr('action_type');
var cur_average = $('.current_average').val();
var data = {};
data.score = score;
data.media_id = <?php echo $title_data->media_id; ?>;
data.what_do = what_do;
$.ajax({
dataType: "json",
type: 'post',
url: 'jquery/actions/add_remove_rating',
data: data,
success: function(data) {
if (data.comm === 'success') {
//do some other stuff there, irrelevant
$('.ladda-button').removeClass('btn-primary');
$('.ladda-button').removeClass('btn-sm');
$('.ladda-button').addClass('btn-danger btn-xs');
$('.ladda-label').html('Remove');
$('.ladda-button').addClass('remove_rating'); <-- add the remove rating class I want to call if the button is clicked again
input.attr('action_type', 'remove_rating');
l.stop();
}
}
});
$('.remove_rating').on('click', function() { <-- this doesn't work, why?
alert('remove was clicked');
});
});
I can't seem to trigger this:
$('.remove_rating').on('click', function() { <-- this doesn't work, why?
alert('remove was clicked');
});
Any help appreciated!
Edit: on a side note, I don't actually need this to work as php figures out if we're removing or adding a score based on the action_type attribute. I just wanted to find out why it's not triggering.
change your code to:
$(document).on("click", '.add_rating', function() {
l.start();
var input = $(this).prev().children('.my_rating');
var score = input.val();
var what_do = input.attr('action_type');
var cur_average = $('.current_average').val();
var data = {};
data.score = score;
data.media_id = <?php echo $title_data->media_id; ?>;
data.what_do = what_do;
$.ajax({
dataType: "json",
type: 'post',
url: 'jquery/actions/add_remove_rating',
data: data,
success: function(data) {
if (data.comm === 'success') {
//do some other stuff there, irrelevant
$('.ladda-button').removeClass('btn-primary');
$('.ladda-button').removeClass('btn-sm');
$('.ladda-button').addClass('btn-danger btn-xs');
$('.ladda-label').html('Remove');
$('.ladda-button').addClass('remove_rating'); <-- add the remove rating class I want to call if the button is clicked again
input.attr('action_type', 'remove_rating');
l.stop();
$('.remove_rating').on('click', function() { <-- this doesn't work, why?
alert('remove was clicked');
});
}
}
});
});
EXPLANATION:
first have a look here: Understanding Event Delegation.
event delegation is used when you need to create event handlers for elements that do not exist yet. you add a .remove_rating class to elements dynamically, however you are trying to attach a handler to elements with the above mentioned class before you even attach it.
you are attaching the class when the asynchronous ajax call returns, in the success function, however your event handler block is being processed right after you send the ajax, and not after the ajax returns (ajax is async rememeber?). therefore, you need to wait until the ajax returns and the elements are created, and only then attach the handler to them.
alternatively, using event delegation, you can attach the handler to the document, like you did in the following line:
$(document).on("click", '.add_rating', function() {
it means, that you attach the handler to the document, and whenever any element ON the document is clicked, if that element has the class '.add_rating' then execute the handler.
therefore, you may attach another handler to the document to monitor for clicks on elements with the .remove_rating class as follows:
$(document).on("click", '.remove_rating', function() {
this is called event delegation, because you delegate the event to a parent element.
Because class was added after click event initialised. You need to use live event handlers, like this:
$( document ).on('click', '.remove_rating', function() {
In this case .remove_rating click handler will work on dynamically created elements and on class name changes.
The title is very much self explanatory. I'm appending HTML to my document in an AJAX call and I would like to prevent the default event when you click in an <a> tag generated by this function. Here's my code:
$.ajax({
type: 'GET',
url: "/api/search/info/" +id,
accepts: 'application/json'
}).then(function(data, status, xhr) {
$(".book-results #results").append("<a class='bookitem' href='b"+data.value+"'>Add Book</a>");
}, showErr);
Inside the same javascript file (but not within the AJAX function ), I have this listener:
$(".bookitem").click(function(event) {
event.preventDefault();
console.log("HELLO");
});
When I trigger the ajax event, the .book-results #results gets populated, but when I click the <a> tag the default event gets triggered. Is there a way to make the listener work? If so, how?
You can't apply an event listener before the element you are trying to attach the listener to exists. So $(".bookitem").click(function(event) {...}); will only bind elements with the class of bookitem that exist at the time.
If you are dynamically adding elements, you need to either attach event handlers to those elements after you create them or, better, use delegation.
For delegation you attach the event handler to a parent element, for example:
$(".book-results #results").on("click",".bookitem", function(event) {
// your handler goes here.
});
For jQuery version 1.7 or higher use .on()...
$(document).on("click", ".bookitem", function(event){
event.preventDefault();
console.log("HELLO");
});
else use .delegate()...
$(body).delegate(".bookitem", "click", function(event){
event.preventDefault();
console.log("HELLO");
});
Try:
$(".book-results").on('click','a',function(event) {
event.preventDefault();
console.log("HELLO");
});
You have to attach event after creating element...
$.ajax({
type: 'GET',
url: "/api/search/info/" +id,
accepts: 'application/json'
}).then(function(data, status, xhr) {
$(".book-results #results").append("<a class='bookitem' href='b"+data.value+"'>Add Book</a>");
$(".bookitem").click(function(event) {
event.preventDefault();
console.log("HELLO");
});
}, showErr);
This code works fine for first click as it changes class along with image which is referenced from CSS. But when I click second time it acts like clicked in previous class which I assume removed already.
if(Model.SeenItWantToSeeIt.Status==1)
{
<div class="movie_data">
<div class="usermovie_option"> </div>
</div>
<div class="clear"></div>
}
else{
<div class="movie_data">
<div class="usermovie_option"> </div>
</div>
<div class="clear"></div>
}
And Javascript for toggling class is
$(".want_to_see_it").click(function () {
var wantToSeeIt = $(this);
alert('clicked on want to see it.');
$.ajax({
url: '#Url.Action("SeenIt", "MovieProfile")',
data: { Status: 1, MovieID: movieID },
dataType: 'json',
type: "POST",
success: function (data) {
wantToSeeIt.removeClass();
wantToSeeIt.addClass("dont_want_to_see_it");
$("dont_want_to_see_it").show();
},
error: function (data) {
alert('Error occurred.');
}
});
});
$(".dont_want_to_see_it").click(function () {
alert('clicked on donot want to see it');
var wantToSeeIt = $(this);
$.ajax({
url: '#Url.Action("SeenIt", "MovieProfile")',
data: { Status: 0, MovieID: movieID },
dataType: 'json',
type: "POST",
success: function (data) {
wantToSeeIt.removeClass();
wantToSeeIt.addClass("want_to_see_it");
$("want_to_see_it").show();
},
error: function (data) {
alert('Error occurred.');
}
});
});
And problem is it shows "clicked on donot want to see it" or "clicked on want to see it" as alert every time I click . What I have to do is this message should alternate every time I Click on their respective image.
Problem here is that you want to change the handlers dynamically on click of each element. But events are bound to the element directly using click event.
One option is to hide and show respective items.
Another option is to bind and unbind events.
Third option is to use event delegation. Your requirement will work with this since with event delegation events are not directly attached to the elements, they are instead delegated. So the moment you swap the class name event subscribed for that class name will automatically get delegated. SO next click on the same element will go to the other event handler attached its new class name. See if this is what you were looking for.
$(document).on('click',".want_to_see_it" ,function (e) {
var wantToSeeIt = $(this);
alert('clicked on want to see it.');
///Your ajax
wantToSeeIt.removeClass();
wantToSeeIt.addClass("dont_want_to_see_it");
$(".dont_want_to_see_it").show();
});
$(document).on('click',".dont_want_to_see_it" ,function (e) {
alert('clicked on donot want to see it');
var wantToSeeIt = $(this);
///Your ajax
wantToSeeIt.removeClass();
wantToSeeIt.addClass("want_to_see_it");
$(".want_to_see_it").show();
});
Note:- In the example i have attached to the document, You should n't attach it to the document, instead attach it to any containing element that is present in DOM at any time.
Demo
There was another issue, you missed . before the classname in your ajax success.
The problem is you need to unbind("click") to clear the previous handler then bind a new event handler for its new class.
Instead of unbinding and rebinding, do in one handler:
$(".usermovie_option a").on("click", function () {
var status = 0;
if ($(this).hasClass("want_to_see_it")) {
status = 1;
}
$.ajax({
url: '#Url.Action("SeenIt", "MovieProfile")',
data: { Status: status, MovieID: movieID,
dataType: 'json',
type: "POST",
success: function (data) {
$(this).toggleClass("want_to_see_it");
$(this).toggleClass("dont_want_to_see_it");
},
error: function (data) {
alert('Error occurred.');
}
});
});