toggling class on click by javascript on ajax post success - javascript

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.');
}
});
});

Related

on click event leads to chain of events after first click

Im trying to add and remove class followed by click events to perform ajax calls. later on success retrieve back the old class. Like Im changing a state of input field to enable, change text of edit button to save and adding class at the same time. when i click same button it has to send modified value in input field to api and restore back to original save button. This is happening for first time when I click edit button. After saving if I click the edit button its changing the state to save and edit back again.help needed.
$.each(data, function(key, value) {
if (parseInt(cat_id[i].innerHTML) == value.category.id) {
base_rate[i].value = value.base_rate;
ast[i].innerHTML = value.service_type.name;
airportEditId[i].setAttribute("id",value.id);
newEvent = value.id;
airportEditId[i].classList.add("fireevent"+value.id);
j = true;
base_rate[i].setAttribute("disabled",true);
$('.fireevent'+value.id).on('click',function(){
$(this).attr("id",value.id);
$(this).parents("tr").find("input").prop('disabled',false);
$(this).text("save");
$(this).removeClass().addClass("smokeevent"+value.id).addClass("btn btn-primary");
console.log(this);
$('.smokeevent'+value.id).on('click',function(){
var airport = {
"updated_by":{{user.id}},
"city":parseInt($('#city_list option:selected').val()),
"service_type":parseInt($('#select_service1 option:selected').val()),
"base_rate":parseInt($(this).parents("tr").find("input").val()),
"vehicle_varient":[1,2]
};
console.log(airport);
$.ajax({
url: '/rapido/api/update_airportratecard/'+value.id+'/',
method: 'PUT',
headers:{'X-CSRFToken':'{{ csrf_token }}'},
contentType : 'application/json',
context:this,
data: JSON.stringify(airport),
success:function(res){
console.log(this);
$(this).text("Edit");
$(this).parents("tr").find("input").prop('disabled',true);
$(this).removeClass().addClass("btn btn-success");
}
});
});
});
Try this, In a loop, there are multiple events attached for the same click.
let go off the earlier event and attach again.
$('.airportdata').off('click').on('click', ...
You are binding the event to elements through class selector in a loop.
By the end of the loop you will have multiple event handlers assigned to all the elements belong to that class. As a result of this, one trigger of a click will invoke all those event handlers.
Instead use your own airportEditId[i] to bind the event instead of
$( airportEditId[i] ).on('click',function(){
Note :Judging by this line
$(".airportdata").removeClass().addClass("airport_editid").addClass("btn btn-success");
airport_editid and airportdata are classes of same element. Hence you can replace both by $( airportEditId[i] ).on('click',function(){
Edit
Another approach could be to pull these two click event handlers outside the loop and bind them separately
$.each(data, function(key, value) {
if (parseInt(cat_id[i].innerHTML) == value.category.id) {
base_rate[i].value = value.base_rate;
ast[i].innerHTML = value.service_type.name;
airportEditId[i].setAttribute("id", value.id);
newEvent = value.id;
j = true;
base_rate[i].setAttribute("disabled", true);
}
});
$(".airport_editid").on('click', function() { //notice that this line is outside
$(this).parents("tr").find("input").prop('disabled', false);
$(this).text("save");
$(this).removeClass().addClass("airportdata").addClass("btn btn-primary");
$(this).on('click', function() { //notice that this line is using `this` instead of selector
var airport = {
"updated_by": {
{
user.id
}
},
"city": parseInt($('#city_list option:selected').val()),
"service_type": parseInt($('#select_service1 option:selected').val()),
"base_rate": parseInt($(this).parents("tr").find("input").val()),
"vehicle_varient": [1, 2]
};
$.ajax({
url: api,
method: 'PUT',
headers: {
'X-CSRFToken': '{{ csrf_token }}'
},
contentType: 'application/json',
data: JSON.stringify(airport),
success: function(res) { $(".airportdata").parents("tr").find("input").prop('disabled', true);
$(".airportdata").text("Edit"); $(".airportdata").removeClass().addClass("airport_editid").addClass("btn btn-success");
}
});
});
});

Ajax form is sent twice if validation errors take place

I know about event.preventDefault() and event.stopImmediatePropagation(). But it doesn't work for me. In my case I have such ajax call:
$('#templateConfirmDialog').on('show.bs.modal', function (event) {
$(this).find('.modal-yes').click(function(){
var form = form2js('search_form', '.', true, function (node) {}, false);
var requestData = JSON.stringify(form, replacer);
var $formErrors = $('.search_form').find('.alert-danger');
event.preventDefault();
event.stopImmediatePropagation();
$.ajax({
type: 'POST',
contentType : "application/json",
url: '/fraud/template/testCreate',
data: requestData,
dataType: 'json',
success: function (data) {
$formErrors.text('');
//if no errors just reload
if (data === undefined || data.length === 0) {
location.reload();
}
else {
//else bind error messages
data.forEach(function(error) {
$('#new-' + error.field + '-error').text(error.defaultMessage);
})
}
}
});
});
My problem is that the ajax call is prevented as much times as I made attempts to input data. If I entered invalid data once - ajax is called twice. If twice - 3 times. What may be a reason of such behavior?
Every time this event happens:
$('#templateConfirmDialog').on('show.bs.modal', function (event) {
You bind a new click event handler:
$(this).find('.modal-yes').click(function(){
So if you show.bs.modal twice, then you have two click event handlers both submitting the AJAX request. Instead, just bind the click event handler once to the target clickable element, instead of binding it every time the modal is displayed.
Replace this:
$('#templateConfirmDialog').on('show.bs.modal', function (event) {
$(this).find('.modal-yes').click(function(){
//...
});
});
With this:
$('#templateConfirmDialog').find('.modal-yes').click(function(){
//...
});
Or, if that element is dynamically added to the DOM, this:
$(document).on('click', '#templateConfirmDialog .modal-yes', function(){
//...
});
That way there's just a single click event handler created when the page loads, rather than adding a new handler every time you display the modal.

jQuery function doesn't work after after loading dynamic content

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.

Link causes refresh

I try to make a link fire a javascript function wich fires a ajax call to delete an item.
Like so:
<a class="delete" href="#item.Product.Id">(x)</a>
Clicking the cross caries the id of the product to be deleted.
The only reason the href attribute is there is to carry the value.
$(document).ready(function () {
$('.delete').click(function (e) {
e.preventDefault();
var id = $(this).attr("href");
deleteItem(id);
return false;
});
});
Ajax call: as requested:
function deleteItem(id) {
$.ajax({
url: "/Shoppingcart/RemoveItem",
type: "POST",
data: "id=" + id,
cache: false,
error: function (xhr, status, error) {
console.log(xhr, status, error);
},
success: function () {
$.ajax({
url: "/Shoppingcart/Index",
type: "GET",
cache: false,
error: function (xhr, status, error) {
console.log(xhr, status, error);
},
success: function (result) {
success(result);
}
});
}
});
}
The success function is there to get an updated version of the cart.
And this actually works just fine. However I get a wierd page refresh half way trough the cycle.
I click the link.
the page refreshes and the item is not deleted.
I click the link once more.
the page is not refreshed.
the item is deleted.
Why do I have to click two time and what can I do to resolve this?
The most correct answer is: You don't know what the error is,
because the page is refreshing before you see the error.
Return false prevents the page from refreshing after a click event, but if the code runs into an error before that point...
So you could try to remove the href tag and make it an rel (or something else) tag instead. read that and use it for your AJAX call. give the href a value like # or #removeItem.
This will give you the error your craving for.
Hope this helps!
Usually you get such behavior when page the is quite big and the document.ready event just hasn't fired yet when you click the link. The second time it may load faster (scripts/css already downloaded and coming from cache).
As per my knowledge, have a hidden field or a hidden span to save the "ProductId" and remove the href attribute altogether something like below.
<span id="productIdSpan">#item.Product.Id</span>
<a class="delete"></a>
jQuery:
$(document).ready(function () {
$('.delete').click(function (e) {
var id = $("#productIdSpan").html();
deleteItem(id);
return false;
});
});
EDIT:
Approach-2:
You can store the ProductId in the anchor tag's "title" attribute something like below
jQuery:
$(document).ready(function () {
$(".delete").on("click", function (e) {
deleteItem($(this).attr("title"));
return false;
});
});
This should solve your problem. Hope this helps!!
The correct answer is:
When you add an element to your html after the page is loaded ( for example with AJAX ) and you want to have, in any way, fire an event. You have to rebind the click event to the new element.
When the page is loaded and your javascript and jQuery are loaded. The element isn't their yet so they can't find it or interact with it.
So in my situation:
function addItem(id, amount) {
$.ajax({
url: "/Shoppingcart/AddItem",
type: "POST",
data: "id=" + id + "&amount=" + amount,
cache: false,
error: function (xhr, status, error) {
console.log(xhr, status, error);
},
success: function () {
// Calls for the new update version of the shopping cart.
$.ajax({
url: "/Shoppingcart/Index",
type: "GET",
cache: false,
error: function (xhr, status, error) {
console.log(xhr, status, error);
},
success: function (result) {
//Call the function that changes the html
success(result);
}
});
}
});
}
function success(result) {
$("#shoppingcart").html(result);
//The tricky part: rebinding the new event.
$('.delete').click(function (e) {
e.preventDefault();
var id = $(this).attr("data-id");
deleteItem(id);
return false;
});
}
The delete button did work after a refresh because in that way javascript got reloaded and the element was correctly bound.

jquery click event

I have some jquery that looks like this,
$('.career_select .selectitems').click(function(){
var selectedCareer = $(this).attr('title');
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
$('#grade_choice').SelectCustomizer();
}
});
});
My problem is that if the user keeps clicking then the .hfeed keeps getting data appended to it. How can I limit it so that it can only be clicked once?
Use the one function:
Attach a handler to an event for the elements. The handler is executed at most once per element
If you wanted the element to only be clicked once and then be re-enabled once the request finishes, you could:
A) Keep a state variable that updates if a request is currently in progress and exits at the top of the event if it is.
B) Use one, put your code inside a function, and rebind upon completion of request.
The second option would look like this:
function myClickEvent() {
var selectedCareer = $(this).attr('title');
var that = this;
$.ajax({
type: 'POST',
url: '/roadmap/step_two',
data: 'career_choice='+selectedCareer+"&ajax=true&submit_career=Next",
success: function(html){
$('.hfeed').append(html);
$('#grade_choice').SelectCustomizer();
},
complete: function() {
$(that).one('click', myClickEvent);
}
});
}
$('.career_select .selectitems').one('click', myClickEvent);
You can either use a global variable like
var added = false;
$('.career_select .selectitems').click(function(){
if(!added) {
// previous code here
added = true;
}
});
or use .one("click", function () { ... }) instead of the previous click function to execute the handler at most once per element. See http://api.jquery.com/one/ for more details.

Categories

Resources