JS function "Confirm" acting out of order - javascript

The following function mimics a pattern of behavior I would like in my system:
Press button
Change text to an Icon
Ask for user confirmation
Fire Ajax call to an endpoint, and handle the result
Return the text to the previous state.
As it is written, step 3 happens before steps 2 and 4; making step 2 borderline pointless. The Ajax call as I have it in my system loads pretty quickly, but the jQuery function barely blinks the text across. I have made a testable snippet here.
How do I ensure that step 2 correctly in order?
function callAjax() {
$('#loadingIcon').css('display', 'inline-block');
$('#buttonText').css('display', 'none');
if (confirm('Are you sure would you like to proceed?')) {
$.ajax({
url: "...",
timeout: 60000,
context: document.body,
success: function (data) {
location.reload();
},
error: function (data) {
$('#loadingIcon').css('display', 'none');
$('#buttonText').css('display', 'initial');
}
});
} else {
$('#loadingIcon').css('display', 'none');
$('#buttonText').css('display', 'initial');
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onClick=callAjax()>
<span id="buttonText">Loading Text</span>
<span id="loadingIcon" style="display:none;">Icon</span>
</button>

The UI doesn't update until the thread has finished doing what it's doing, and confirm (and prompt, and alert) is a blocking operation.
Ideally you wouldn't use confirm at all. Instead, create a UI within the page to prompt the user for data. It could be form elements on the page, a "modal dialog", etc.
But if you want to use confirm, you'd need to allow the thread to finish first. It's a bit of a hack, but wrapping it in a near-immediate setTimeout should do the trick:
$('#loadingIcon').css('display', 'inline-block');
$('#buttonText').css('display', 'none');
setTimeout(function () {
if (confirm('Are you sure would you like to proceed?')) {
$.ajax({
/* etc. */
});
} else {
$('#loadingIcon').css('display', 'none');
$('#buttonText').css('display', 'initial');
}
}, 1); // only delaying 1ms
This introduces a 1ms delay, which would certainly be imperceptible. But by virtue of using setTimeout at all, the thread first finishes everything it's processing (including UI updates) and then executes what's scheduled in the timeout.

Related

Function initiated in ajax call only works one time

I am using a plugin called mixitup that makes sure I have a masonry layout with some animations.
The masonry comes from another page which gets loaded in through ajax. I have a search bar which searches for photos and returns them from the masonry page. The issue is this works the first time but not the second time and so on. Why is that?
My code for the search input:
$('.photosearchinput').keyup(function(e) {
clearTimeout($.data(this, 'timer'));
if (e.keyCode == 13){
searchphotos(true);
}else{
$(this).data('timer', setTimeout(searchphotos, 500));
}
});
My function that makes the ajax call and which has my masonry mixitup function in the complete:
function searchphotos(force) {
var photoform = $(".photosearchform").serialize();
$.ajax({
type:'post',
url:"includes/photoresults.php",
data:({photoform: photoform}),
success:function(data){
$( "#searchphotos" ).show().empty().append( data );
},
complete:function(){
// I tried calling #masongallery from the body (body always stays the same and does not get added again)
$('body').find('#masonrygallery').mixItUp({
selectors: {
target: '.tile',
filter: '.filter',
sort: '.sort-btn'
},
animation: {
animateResizeContainer: false,
effects: 'fade scale'
}
});
}
});
}
I thought maybe the DOM gets reloaded and jquery cannot find the element #masonrygallery anymore so I tried calling it like this: $('body').find('#masonrygallery').mixItUp({ the body never gets reloaded so maybe this would fix it, but no. I get the same result. It works the first time, but not any time after that.
I have made a video to show what I mean: https://streamable.com/njy6x7
I get no errors in my console. And when I look in the network tab to see what ajax is retrieving, I see the correct images, they are just not visible as masonry layout (in fact they are not visible on the page at all but this is because of the plugin).

jQuery ajaxForm complete works sometimes, other times it only fires a native javascript function then stops

This may be a duplicate of this topic, but I must revive it as my issue seems to be a little deeper than this. I'm currently using ajaxForm() to submit a 4 question quiz to a PHP script, receive the result, and then populate it back into the DIV. The beforeSend function fires, sending the information to the ajax.php script. beforeSend also shows a loading graphic in the quiz container. Then the complete function fires properly as ajax.php returns the HTML to be populated back into the DOM. At that point, everything stops. The next line is a call to slideUp the loading div and then display the returned information in the quizContainer.
At this point if I put in a javascript alert it always fires, meaning that complete is at least firing when it should, but the jQuery reference to the loading div is completely ignored. Here's the code for the javascript file that handles the submission - the section handling this is "Handle the quiz submission":
$(document).ready(function () {
// Get rid of the message box after 15 seconds
setTimeout(function() {
$('#message').slideUp('fast');
}, 10000);
// Handle the Course List LIs
$('#courseList li').on('click', function () {
// Get the background color as it's set initially
var color = $(this).attr('oColor');
jQuery('div', this).toggle('slow', function () {
if ($(this).is(":hidden")) {
$(this).css('background-color', color);
}
});
// Change the background to be the same as the content background when it's expanded
if ($(this).is(":hidden")) {
$(this).css('background-color', '#33CC66');
} else {
$(this).removeAttr('style');
}
});
// Handle the quiz submission
jQuery.fn.exists = function(){return this.length>0;}
if ($('#quizForm').exists()) {
$('#quizForm').ajaxForm({
beforeSend: function() {
$('#quizContainer').slideUp('fast', function () {
$('#loading').show();
});
},
complete: function(xhr, theStatus) {
alert(theStatus);
$('#loading').slideUp('fast', function () {
$('#quizContainer').html(xhr.responseText);
$('#quizContainer').show();
});
}
});
}
});
If necessary I can provide more information and a temporary login to access this if anybody would like to see it in action. I'm currently using jQuery 1.8.1(.)
Thanks for any help!
Jon
I believe the first argument of the complete function is xhr.responseText rather than an xhr object which is actually the third argument. Try removing .responseText from your complete: function.

How to call a Javascript Function and make it perform twice properly?

Good evening, I have a javascript function to set background color, etc when user onclick the table row. The function does not perform correctly unless it is called twice or when I press F12 for development tools, similar situation as Function doesn't correctly perform unless it is called twice.
I managed to handle it as below but the problem is that, when the user onclick the table row, it needs around 2-3 seconds for the background color to be change. How can I reduce the time for the function to perform twice?
JavaScript
<SCRIPT LANGUAGE="JavaScript">
setBackGroundColorOnIE (tableRowNumber) {
//........
//........
setBackGroundColorOnIE (tableRowNumber)//I need the function to perform twice in one call
}
</SCRIPT>
I know it is a bad practice, but I'm really have no idea on how to fixed the compability issues in IE9. So, I came out with something like this. Need some hints and advices, thanks in advanced.
you could add some condition to check if your function need to run again, like:
function setBackGroundColorOnIE (tableRowNumber) {
//check if your condition is met
if( some_condition) {
var timerId = setTimeout(function() {
setBackGroundColorOnIE (tableRowNumber);
}, 5000); //set to 5 seconds
}
else {
clearTimeout ( timerId );
}
}
//call the function
setBackGroundColorOnIE(some_value);
An easy solution would be to include jquery ui which would allow you to change the color and then have a callback when the color change is completed. Here is a JS fiddle with jquery and jquery ui. http://jsfiddle.net/kqMs9/
$(function(){
$('button').on('click', function(){
$('.background').animate({
backgroundColor: '#000'
}, 1500, function(){ alert('background-color changed!');});
});
});

Disable a pop up link for 5 seconds using javascript

For a project I need to print a document using PHP code.
Currently I have a self closing pop up to start the print.
The only problem I have is that a user could spam the button creating a lot of print requests and a huge queue.
The code I have right now:
function newPopup(url) {
popupWindow = window.open(
url,'popUpWindow','height=10,width=100,left=10,top=10,resizable=no,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=no'); // Verstop op achtergrond
popupWindow.blur();
}
Print
I have found some code to stop links but I have problems implementing these since I already call it as a pop up.
You can use a flag:
var flag=true;
function newPopup(url) {
if(flag) {
window.open(...).blur();
flag=false;
window.setTimeout(function(){flag=true;},5*1000);
}
}
Not a "good" solution (uses a global variable), but it should work.
You may disable the link before you open the popup and then re-enable it after five seconds. The problem is that to enable/disable a link can't be done in a very portable way. To workaround this you have to save the actual link, replace it with a fake one and then re-enable it later (when interval elapsed). Like this:
function newPopup(url) {
// Save current link and replace it with a fake one
var oldLink = $("#linkid").attr("href");
$("#linkid").attr("href", "#");
setinterval(function() {
// Restore true link
$("#linkid").attr("href", oldLink);
}, 5000);
// ...
}
You can extract this code to a separate function temporaryDisableLink(id, timeout) to reuse it for many different links (without polluting all other code).
Now let's explore other solutions.
Your HTML code must be updated to (in case you want to reuse the same function for many links otherwise you do not need to pass the link id parameter) to:
<a id="link-print"
href="JavaScript:newPopup('#link-print', 'print.php');">
Print
</a>
The pointer-events CSS property isn't supported by IE (and Opera) so I can't suggest to use it in real world. Anyway it's:
function newPopup(id, url) {
$(id).css("pointer-events", "none");
setinterval(function() {
$(id).css("pointer-events", "auto");
}, 5000);
// ...
}
Because you're using JavaScript to open the pop-up you may consider to change a little bit the function to use a custom disabled attribute (or to check for pointer-events if you plan to use them together):
function newPopup(id, url) {
if ($(id).attr("disabled") == "disabled") {
return false;
}
$(id).attr("disabled", "disabled");
setinterval(function() {
$(id).removeAttr("disabled");
}, 5000);
// ...
}
<script>
function newPopup(url) {
setTimeout(function () {
popupWindow = window.open(
url, 'popUpWindow', 'height=10,width=100,left=10,top=10,resizable=no,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no,status=no'); // Verstop op achtergrond
popupWindow.blur();
},5000
);
}
</script>
Print

Multiple blocks in jquery ui blocker?

I am using this plugin.
However it seems to use global variables
$.blockUI();
$.unblockUI();
Is there away I can have different instances of this block.
$(document).ajaxStart(function (e)
{
$.blockUI(); //setup with a loading msg.
});
$(document).ajaxStop(function (e)
{
$.unblockUI();
})
var ajax = // ajax setup stuff
// 1.5 way of doing it
ajax .success(function (response)
{
var valid = checkIfValid(response); // check if valid
if(valid)
{
$.blockUI(); // setup with a save message
}
});
So that's sort of what I have. I put
$.blockUI();
to keep it simple with no options but in my real code I have messages and other options set.
So now the problem is this once the success is finished the ajax stop gets called and unblocks everything. I only want the one that was started in the ajax start to be cleared not the one in the valid.
So I need different instances.
You can accomplish what you're trying to do by calling block on a div that you create on the fly, and then simply removing that div from the DOM. For example:
$(document).ajaxStart(function (e) {
/* Create a <div> that will contain the blocking elements: */
$("<div id='ajax-block' style='position:fixed;width:100%;height:100%' />")
.appendTo("body").block()
});
$(document).ajaxStop(function (e) {
/* Remove the page block specific to the ajax request: */
$("#ajax-block").remove();
});
And do something similar for the other event you're blocking (just change the id attribute inside the dynamically appended div and the call to remove().

Categories

Resources