jQuery toggle two clicks required in firefox - javascript

This works fine on all other browsers but in firefox, I need to click my 'show more reviews' link twice for my on click event to fire. any ideas?
$moreReviewsWrapper.toggle(function() {
$(this).on('click', function(e) {
e.preventDefault();
var moreReviewEndpoint = $(this).data().more;
if(moreReviewEndpoint) {
$.ajax({
type: 'GET',
dataType: 'html',
contentType: 'text/html; charset=utf-8',
url: moreReviewEndpoint,
beforeSend: function() {
$moreReviewsLink.text('Loading more reviews ...');
},
success: success,
error: function(){
$moreReviewsLink.prop('hidden', false);
$moreReviewsLink.text(originalText);
$commonError.show();
}
});
}
});
}, function() { $(this).off(); });

The structure of your jQuery looks kind of weird to me. toggle() is a show/hide function, and the first argument is a duration argument. You're passing it a function that creates an event handler. My guess is jQuery ends up running that function to evaluate it for a number (to use as the duration), which then sets your event handler.
I'm not sure what toggle() is supposed to be doing here, but moving your event listener outside of toggle() will fix your issue.

Related

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.

Cannot disable Twitter bootstrap button with jQuery?

I am doing some AJAX when a button is clicked
$btn.button('loading');
$.ajax({
type: 'PUT',
url: 'event/',
data: put_data,
dataType: 'json',
success: function(data){
if (data.redirect) {
window.location = data.redirect;
}
else {
$btn.button('reset');
if ($btn.is('#my-btn')) {
console.log('disabling button');
$btn.prop('disabled', true);
}
}
}
});
disabling button shows up in the console, but the button does not get disabled. Loading and resetting the button works just fine. I tried .addClass('disabled') and .attr('disabled','disabled'), but those also don't work.
See here: http://codepen.io/anon/pen/Wvbeeg
The problem is that button('reset') is asynchronous. You can watch the changes live in the html an see they aren't immediate
A short delay after reset resolves the problem, but personallly i would just code this whole process myself instead of using the bootstrap API
$(document).ready(function() {
$('#mybutton').click(function() {
var $btn = $(this);
$btn.button('loading');
setTimeout(function() {/// mimic ajax delay
$btn.button('reset');
setTimeout(function() {// short delay after reset
$btn.prop('disabled', true);
}, 200);
}, 1000);
});
});
DEMO
Remove:
$btn.button('reset');
For some reason, this doesn't evaluate until after you disable it. (It's asynchronous)
Rather than resetting the button using the 'reset' code, it might be better to just remove the disabled property if it exists. That will effectively enable the button if it should be active.
Modified code:
$btn.button('loading');
$.ajax({
type: 'PUT',
url: 'event/',
data: put_data,
dataType: 'json',
success: function(data){
if (data.redirect) {
window.location = data.redirect;
}
else {
if ($btn.is('#my-btn')) {
console.log('disabling button');
$btn.prop('disabled', true);
} else {
$btn.prop('disabled', false);
}
}
}
});
Bonus tip: Don't use .removeProp() to re-enable the button. That will completely remove the property and you won't be able to use it again. More about prop() here: https://api.jquery.com/prop/
It's because you are using jQuery to bind a click event to the button. So the disable property won't be able to stop it. In your code you will need to add this:
$('#mybutton').off('click');
That will unbind the event from the button.

Can I continue with a previous prevent link?

I have this link:
$('.popup-window').click(function (e) {
e.preventDefault();
$.ajax({
...
})
});
which is a .NET LinkButton (a link that call a javascript, not a real href). I want to prevent Default if ajax return some (let say, false). Else, if true, continue with that link handler.
How can I do it?
P.S. I need that e.preventDefault(); at the beginning, else .NET handler will act immediatly.
You can use the __doPostBack() js function to trigger the postback in your AJAX callback.
The only thing is that you need to pass in the id of the control causing the postback, e.g.
__doPostBack('btnPopup', null);
you can see more on this function in this question: How to use __doPostBack()
I think I understand what you're looking for.
Here's my idea on it: use a data attribute on the DOM element to decide weither default event should be prevented or not. Initially, the event is prevented but the ajax has the power to "unlock?" it, then fire it again. It's a little bit of custom work but it may do the trick:
var $popupWindow=$('popup-window');
// initially "tell" the LinkButton to prevent default
$popupWindow.data('prevent-default', 1);
// the click event (initially prevents default)
$popupWindow.click(function(e){
var $this=$(this);
if ($this.data('prevent-default')==0) { // if "unlocked"
// "lock" it again (default isn't prevented)
$this.data('prevent-default', 1);
} else { // if "locked"
// default is prevented
e.preventDefault();
// test if it should be unlocked
$.ajax({
// ...
}).done(function(data){
if (data.length>0 && data.response==false) {
// set the attribute so it shouldn't prevent default
$this.data('prevent-default', 0);
// trigger this click (should let the event fire completely)
$this.trigger('click');
}
});
}
});
UPDATE:
An alternative could be to add a Page Method.
(See: Using jQuery to directly call ASP.NET AJAX page methods)
This would reduce the mechanics to somethink like this:
$('popup-window').click(function(e){
e.preventDefault();
$.ajax({
// ...
}).done(function(data){
if (data.length>0 && data.response==false) {
$.ajax({
type: "POST",
url: "YourPage.aspx/YourMethod",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
// Replace the div's content with the page method's return.
$("#Result").text(msg.d);
}
});
}
});
});
$('.popup-window').click(function (e) {
data = '?sample=1' //serialized data here
callback = function(json){
if(json.returnVar!=true){ //check if returnVar is not true
e.preventDefault(); //prevent redirect if not true
}
};
$.ajax({
type: 'POST',
url: "../ajaxcall.php", //the url to call for ajax here
data: data,
success: callback,
dataType: 'json'
});
});
Try this, let me know if you can't understand the code

toggling class on click by javascript on ajax post success

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

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