Execute 2 JavaScript functions in order - javascript

I have a function with two lines and I want them to be executed in order. The function is :
showNotification(message){
$("#notificationMessageBody").html(message); // line1
$("#notificationModal").modal('show'); //line2
}
So, whenever I call showNotification("Hello World!") how do I ensure line1 is executed before line2 (meaning content loading is done before the modal triggers)
Basically, I am trying to fill in my message in modal body and then show it, not before filling.
--EDIT--
The functions are indeed executing one after the other, but my modal pops before jQuery loads my message into my #notificationMessageBody
As a result, for example : If I call showNotification("Hello") I get a modal with "Hello" (the arrangement of modals and stuff is done), but then after that if I call showNotification("World") modal appears with "Hello" first then after that it changes to "World".
Note : "Hello" and "World" are big junk of text, so loading that into my DIV must be taking some time, I believe. Even though they are executed one after other, it appears (to common-er) that firstly modal is popping and then replacement is done. I hope the picture is a little clear now.
No AJAX involved anywhere here around the function. Basically, this is my custom alert() function one can say. A modal with proper ID is there in my page. I change the modal-body content(with jQuery's .html() function) and trigger the modal to show, as seen from the code.

You can use the .promise() method (added in jQuery 1.6) to ensure the second one is executed after first is completed:
$("#notificationMessageBody").html(message).promise().done(function() {
$("#notificationModal").modal('show');
});

Related

functions with button.click() are not executing the click part

I have 2 function as below:
<script type="text/javascript">
sm=()=>{
document.getElementById('show').click()
console.log('show')
}
hm=()=>{
document.getElementById('hide').click()
console.log('hide')
}
</script>
When the functions are called they do get executed (cause i can see the console.log) but the button click never gets executed. although when I tried the below jQuery the sm() got executed with all its lines(including the click)
$("#ss").ready( function(){
document.getElementById('show').click()
console.log("show")
});
the whole idea is that I want to show a modal when the page starts loading (with loading spinner) and then when the page is fully loaded (including getting database data and inserting them into a table). the modal gets automatically hidden
i prefer vanilla js rather than jquery

jQuery code to delay JavaScript execution until page load causes JS to throw runtime error

The Setting:
I coded some JavaScript to dynamically populate a table with data and then listen for a click event on any of that data, upon which it dynamically populates and displays a modal dialog with information about the clicked data. See the /test-table page of my site and the pen Table Play at CodePen. And up to this point, everything is jake, just hunky-dory.
Now I need to put all the JS in the <head> of the page with the table. But the JS manipulates the DOM, so I have to delay execution until the page loads. I've found answers to that issue which say to wrap the JS in the jQuery statement:
$(document).ready(function() {
// ... js code here ...
});
or in
$(window).bind('load', function() {
// ... js code here ...
});
The Problem:
That, however, causes the JS to throw a runtime error.
When testing it locally on my system, the error is "Uncaught ReferenceError: classes is not defined." When testing it in the pen Table Play, it's "Uncaught ReferenceError: removePopup is not defined." Classes is the array of objects from which the JS populates the table. RemovePopup is the function invoked when the modal dialog's dismiss button is clicked.
Edit 0:
The TablePlay base code is without the jQ. When I put the code
$(document).ready(function() {
at JS line 1 and the code
});
at JS line 316 (the last line), then click on a table cell item, then click the modal dialog's dismiss button, the "removePopup not defined" error logs to the console. See this screenshot.
The removePopup function is set as the dismiss button's onclick function at JS line 190. It is defined beginning at JS line 92. As to the line at which the error is occurring, the console message simply says "onclick # index.html?editors=0010:formatted:1".
End Edit 0
The error only occurs upon wrapping the JS in either of the jQ statements. And the JS in the pen and locally on my system are the same, the former copied and pasted from the latter, so one would expect any error to be the same.
The Question(s):
Does anyone have an inkling what might be going on?
Why would wrapping otherwise correct JS in one of these jQ statements cause an "undefined" error, and why would it be the variable classes on my system and the function removePopup in the pen?
More importantly, of course, how do I delay the execution of the JS until the DOM has fully loaded?
Well, I've not yet determined what it is that's causing the function undefined error, but I've found an alternate implementation that works.
Instead of using the jQuery document ready handler, I added
window.onload = function() {
init();
};
to the script in the document head. I defined init() to declare and initialize the global variables, to populate the table with its data, and to add the click event listeners.
Thanks to the commenters for their interest and time with a particular thanks to #nnnnnn for his/her remark about my possibly having
moved previously global function or variable declarations into your document ready handler but continued trying to reference them from other code that isn't in the ready handler.
Although I couldn't see where I might have done that, it made think of this alternative approach as a way to avoid that happening.

jquery toggleClass not working on img element

I have two buttons ("Approve","Unapprove") and an image of a loading spinner. By default the Approve button is showing and the Unapprove button and loading spinner image are hidden.
When the "Approve" button is clicked I want it to disappear, show the loading spinner, and then perform an ajax request. On completion of the request, I want the loading spinner image to get hidden again. If the ajax request was successful, I want the "Unapprove" button to show. If the ajax request failed, I want the "Approve" button to show again.
The problem I have is that upon completion of the ajax request, my .always() method runs but the spinner image does not get hidden. Here is an example:
https://jsfiddle.net/ebme6fjs/7/
If I change the url of my ajax request to give me a 404 not found error, this process works like it's supposed to:
https://jsfiddle.net/ebme6fjs/8/
Does anyone know why in my first case the spinner.toggleClass("hide"); command isn't running in the always() function? Thanks.
UPDATE:
One interesting thing I found is that if I redefine my spinner variable in the .always() function, it works correctly on a succesful ajax request:
https://jsfiddle.net/ebme6fjs/9/
If you modify the ajax url to receive a 404 though, the same problem of the spinner not disappearing happens again.
In a context where you always want to add the class, use addClass, not toggleClass. In your code, the class is toggled twice: Once in "always" and then again in "fail". So it ends up in the same state as before.
The reason you are targeting the image twice, is because you are defining otherButton like this:
var otherButton = currentButton.siblings();
When what you want to do is this:
var otherButton = currentButton.siblings('button');
toggleClass is most useful when you might want to add or remove the class depending on some condition.
In your code, you were toggling hide class on image twice, in always() callback and done()/fail() ones.
This is because you were targeting image in both variables, spinner & otherbutton.
You should define otherbutton as following:
var otherButton = currentButton.siblings("button");
Not including image in matched set.
As a side note, for code readability, you should use addClass()/removeClass() instead as noted in KWeiss answer and btw, set all your logic for displaying/undisplaying elements only in always() callback.

Completely delete all instances of a div with a specific class using javascript/jquery?

I am using Popup.js by Toddish.
http://docs.toddish.co.uk/popup/demos/
Long story short, the popup plugin creates divs by default given the classes ".popup_back" and ".popup_cont".
I have another button I wish to press which should completely delete the added divs with those classes after they have been generated and added to the html. As if they never even existed. Surely this is possible?
I have tried running a function which simply runs:
$(".popup_back").remove();
$(".popup_cont").remove();
As shown in this example:
http://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_dom_remove
Unfortunately despite the code running, the actual divs are never deleted as required.
Any ideas? I am new to this kind of thing and have googled around and read a lot about DOM etc but am yet to crack it.
Thanks
EDIT:
In reply to the comments:
The Javascript:
function removePopups() { // This function is called to remove the popups.
console.log("removing...");
$(".popup_back").remove();
$(".popup_cont").remove();
}
function func(url) { // url is the url of the image to be displayed within the popup.
removePopups(); // As soon as the function casillas is called, removePopups is used to remove any existing instances of the divs.
$('a.theimage').popup({ // This is where the Popup plugin is utilised.
content : $(url),
type : 'html'
});
}
The HTML:
<a class="theimage" onclick="func('image/image1.jpg')" href="#" >
Long story short, an image is displayed in the popup.
I think the issue is that the popup plugin runs due to the class but the function func is never actually run when the click occurs. However simultaneously "removing..." still prints out in the console which tells me that the function IS being executed. The problem is I want the popup plugin to run together with the javascript function. Is there a solution for this conflict?
Your implementation should really be as simple as this:
<a class="theimage" href="#" >Open</a>
Bind the popup creation to your popup link:
$('a.theimage').popup({
content : 'image/image1.jpg',
type : 'html'
});
I'm speculating here, but what might be happening is that you're invoking the popup twice by binding the popup() call to a click handler in your markup. The popup plugin already binds the popup creation to a click event.
View working demo. Note the 3 external resource: the popup CSS, the popup JS, and the jQuery JS.

Changing visibility does not immediately hide iFrame

I have a page that on a certain action makes an iframe visible and fills the iframe with some HTML (say for example a multi-select box and an ok button).
The OK button on the iframe has the onClick method defined kinda like this:
onClick="parent.hideIFrame();parent.processMultiSelectBox();"
When User clicks OK on the iframe (presumably after playing with the multi-select box), I'd like the iFrame to disappear immediately and then the selected values in the multi-select box can be processed. But this is not what's happening. The iFrame remains visible during the time the other function runs and disappears only after the second function finishes.
The hideIFrame function is pretty straightforward:
function hideIFrame() {
frmObj = document.all.iFrameID;
if(frmObj) {
frmObj.style.visibility = "hidden";
}
}
I've paraphrased the above function for clarity (removed some indicator variable assignments etc.)
The second function actually loops on all the options in the multi-select object and does stuff with it. This takes about a half a second and only after that is done, does my iFrame disappear. It is a little bothersome to see it linger for half a second when I click ok.
My question is whether there is some way I can make the darn thing disappear faster. Speaking in "classical C" lingo, is there a "flush" for the change in visibility to happen immediately?
I did notice that if I put an "alert" as the first line in my second function, the iframe disappears immediately but now it is the OK on the alert box that lingers for the time it takes the second function to finish.
Thanks.
EDIT: Based on DDaviesBrackett's answer, this is what I ended up doing:
The onclick in the iframe changed to:
onClick="parent.hideAndProcessMultiSelectBox(parm1, parm2);"
The hideAndProcessMultiSelectBox function was defined as:
function hideAndProcessMultiSelectBox( parm1, parm2 ) {
hideIFrame();
setTimeout( function() { processMultiSelectBox( parm1, parm2 ); }, 0 );
}
Voila.. no delay..
You've gotten to the root of your problem already; document reflow doesn't happen until the current JS thread is done (so as not to repaint lots of times during JS execution). You need to return control to the browser before doing your expensive processing.
The simplest way to achieve that, though it doesn't make for obvious code in the slightest, is to call processMultiSelectBox in a setTimeout with a delay of 0:
onClick="parent.hideIFrame();parent.setTimeout(parent.processMultiSelectBox,0);"
If you need to pass parameters to the thing you're setting a timeout on, you have two options: set a timeout on a string that evals to Javascript (bad, bad, very bad, horrible) or define an anonymous function that calls the one you're interested in:
onClick="parent.hideIFrame();parent.setTimeout(function(){parent.processMultiSelectBox(foo, bar, 'baz');},0);"
RSolberg's response may also help, though there's a difference between visibility:hidden and display:none.

Categories