GWT PopupPanel not showing at the right time - javascript

I have a function which is called on a click of a button and it takes a long time to create and append to the DOM some elements so I would like to display a PopupPanel with a "loading" icon while the function finished what it has to do. Please note that my function does not make a call to the server, it only creates some elements in the UI which take a long time to compute, so I don't have an onSuccess() event or a callback function to work with.
So I have my PopupPanel:
pp = new PopupPanel();
pp.setTitle("loading....");
pp.setGlassEnabled(true);
Then on the click handler I have the following code:
public void onClick(ClickEvent event) {
pp.show();
functionWhichTakesaLongTimeToExecute();
pp.hide();
}
Since JavaScript is single-threaded I was expecting that the PopUp will appear, then functionWhichTakesaLongTimeToExecute() executes and then the PopUp to be hidden but what happens is that functionWhichTakesaLongTimeToExecute() executes first, taking a long time to append the elements to the DOM, and only after it has finished doing its job is the PopUp shown and then hidden.
It is as if like the code was:
functionWhichTakesaLongTimeToExecute();
pp.show();
pp.hide();
What bothers me even more is that if I add a Window.alert("test") after pp.show() this will break the flow until the OK button in the alert is pressd and this causes the PopUp to appear before the alert and before functionWhichTakesaLongTimeToExecute() is called.
So the following code works as expected:
pp.show();
Window.alert("test");
functionWhichTakesaLongTimeToExecute();
pp.hide();
Can somebody please explain to me why the PopUp is not displayed before the functionWhichTakesaLongTimeToExecute() is called but instead it "waits" for functionWhichTakesaLongTimeToExecute() to execute and only after that it gets to be displayed and why adding a Window.alert("test") causes it to be displayed properly?
PS: I have tested the code in both IE8 and Chrome and the behavior is the same.

This is how you can do it:
pp.show();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
functionWhichTakesaLongTimeToExecute();
pp.hide();
}
});
I explain it here: GWT: Timer and Scheduler Classes

I have had some issues while using setGlassEnabled as well. Can you check by removing the setGlassEnabled(true) line from your code and see if it works?
Also one more thing that I happened to note is that, you have not added any widgets to your PopupPanel. In the source code for PopupPanel it is mentioned that you mustattach a child widget to your PopupPanel object before show is called.
http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/user/client/ui/PopupPanel.java
Do try both of these and let me know if either of it works.

Related

Click button with Javascript after page load / as soon as element loads

I've checked many other answers on StackOverflow but none of them work for some reason.
I'm trying to use something simple like
window.onload = function() {
sleep(5000)
clickButton()
}
But as far as I can tell the button on a page I want clicked loads AFTER page load. So window.onload doesn't work at all. That's why I tried to use a custom sleep function to force the code to run after-after page load but nope. Code "sleeps" by preventing page from fully loading, then runs clickButton(), then the page loads. Useless.
I know my actual button clicking code works in practice because I just fed into the browser console line by line and it worked fine. But the button I'm targeting loads after my code is executed!
I have also tried these which also do not work:
window.addEventListener('load', function () {
clickButton()
})
setTimeout(clickButton(), 5000)
setInterval(clickButton(), 5000)
...
Also I'm using:
document.querySelector("[data-a-target='button-name']");
instead of:
document.getElementById("button-name");
since this button does not have an id.
...
Also I have never used jquery before if that is the answer.
...
How on earth do I get js to click a button immediately as soon as it loads?
The order in which you write your code plays an important role here.
Firstly, put the script tag at the very bottom of the body element of your html page. That forces the browser to have already read through the entire html page before getting to the script tag with your Javascript.
Secondly, I assume you have an event listener for a click on the button. Write the event listener before you let the button be clicked.
For example, I wrote this little code to test my assumption out:
button.addEventListener('click', function () {
console.log('Clicked');
});
button.click();
This should hopefully work for you too. Good luck

Added data disappear

jQuery Core 3.1.0
Chrome, Firefox
Below is a model of jquery.ajax() success behaviour.
Shortly: I managed to fetch data via AJAX. In this model example the data is represented by "Just something" placeholder. Now I want to add the data to the document.
<script>
var add_date = $("#add_date");
function add_date_ajax(){
$('.frame_date').append("Just something");
debugger; // 1
}
debugger; // 2
add_date.click(add_date_ajax);
</script>
A problem: the data appear and then disappear in half a second.
I placed breakpoints.
When the page is loading, it stops at breakpoint 2. That is correct.
When I click #add_date element, the script stops at breakpoint 1. That is also correct.
But when I click "resume script execution", the script again goes to breakpoint 2. This seem strange to me. As if the page is reloaded. Maybe that is why the added text disappears.
Could you help me cope with the problem?
Added later:
https://jsfiddle.net/mv1yu3zw/1/
It disappears because you are reloading the page. The html
Add date
should be
Add date
To bind all your events, you should use the ready on document.
To avoid the reloading of your page (because of the href of the a tag), you have to call preventDefault or use a button.
You should write your code like this:
$(document).ready(function() {
$("#add_date").on("click", add_date_ajax);
});
function add_date_ajax(event) {
event.preventDefault();
$('.frame_date').append("Just something");
}

JS - Pause custom alert()

I've edited the default alert() function like this:
window.alert = function(str){
//custom alert
}
Essentially, the new function will show an HTML <div> modal.
Backstory:
I want to answer to this question because I am having a problem. The alert is hidden and will show when the custom alert function is called. So the custom alert is basically showing the element and changing it's text. Therefore, when I have multiple alert() calls, only the last message is displayed! :(
But, unlike the default alert box. It of course won't pause the webpage until the alert goes away like the default alert() function.
Is it possible to imitate this "pause the webpage" behavior?
Also, is there another way other then using setTimeout() to check if isCustomAlertOpen == true to delay another custom alert from triggering until the current one is dismissed?
Edit:
Is there a way to queue up the custom alerts?
I don't mind jQuery, but I thought it might be overpowered here.
My question title is bad. Can someone think of a better title for me please?
There is no way to block the execution because JavaScript is asynchronous (except obviously 3 modal functions and XmlHttpRequest).
For the same reason, you can't wait for a previous alert to be closed, but you can use events to create a stack of alerts using this pattern:
window.alert = (function() {
var stack = [];
var showNextAlert = function() {
var div = document.createElement("div");
/* Here, configure the div, show the string from stack[0] and add it to the document ... */
var okButton = /* ... */;
okButton.addEventListener("click", function() {
div.parentNode.removeChild(div);
stack = stack.slice(1);
if(stack.length > 0) {
showNextAlert();
}
});
}
return function(msg) {
stack.push(msg);
if(stack.length == 1) {
// Show it immediately if the stack is empty
showNextAlert();
}
};
})();
You should also use another name for this function instead of changing native properties (here window.alert).
Is it possible to imitate this "pause the webpage" behavior?
The answer to this is no. There are ways to block the ui (sync ajax call, long loop etc). But you wouldn't be able to stop these when the user has click the ok button.
A better approach would be to restructure the code so that it didn't run synchronously. Ie you wouldn't need to block the ui while waiting for the user.
Also, is there another way other then using setTimeout() to check if isCustomAlertOpen == true to delay another custom alert from triggering until the current one is dismissed?
One way to do this is: instead of setting a flag in one place and checking it repeatedly in another. You can use the concept of events. One part of code is waiting for an event to be triggered and another part triggers it. There is a library in jQuery which can do this for you or you could read up on it and write your own.

Javascript function runs twice when called

So, I'm working on a rich-text editor using contenteditable.
I have a function called "dveditor". I do var editor = new dveditor(); pass in some settings, and it replaces the content of a div with stuff.
But it runs twice.
If I remove the editor = new editor(); It does not run at all.
But if I call it once, it's run twice. I replace the code in the function with only an alert and same thing happens. So the function is not calling itself.
Any ideas what might be wrong? I'm kinda clueless. At least when I know that I'm only calling it once. I mean, if I remove the call to it, it stops completely.
Thanks in advance.

oncomplete method doesn't always executes after action, JSF

I have the next scenario (simplified) :
My function in my docsMB managed bean:
public void saveAdvance() {
// by default, finalized is false
finalized = getFinalizedByBySlowFunction();
}
A button in my xhtml:
<a4j:commandButton value="SAVE"
action="#{docsMB.saveAdvance}"
oncomplete="verifyDocs();"/>
And my verifyDocs function in the same xhtml:
<script type="text/javascript">
var verifyDocs = function(){
//alert(1);
if( #{docsMB.finalized == true} ){
#{rich:component('mpConfirmar')}.show();
}
}
</script>
This make me a problem.
If I execute my app, "finalized" is always false, but I realized that if I uncomment the alert in the verifyDocs function, it works.
I think the alert gives the "necesary" time to saveAdvance to finalize itself.
What can I do to be sure that the oncomplete method excecutes after the action has finalized?
Or am I doing a mistake in other place?
Thanks a lot
[Edit]
If I refresh the entire page, I get the correct "finalized" value...
The problem was that when I define the javascript function, it became like static, it means, It just execute once and the variable finalized gets the defined values when the page loads.
So, when I clicked the button it retrieve the value predefined, no te value at that moment.
But if I refresh the page, the variable gets the value at the moment of the refresh.
So to solve this, I just put my javascript code directly in the oncomplete method and finally WORKS :D
Maybe a better solution could be to find a way to refresh the javascript code each time the button is clicked, because if I put the javascript code in the oncomplete method, it seems dirty, because of the lot of characters in a line.

Categories

Resources