Twice refreshed in p:commandButton, race condtition with oncomplete - javascript

I'm executing the server action with p:commandButton. After those action is completed, I'm refreshing the form (to show hidden fields) and I show dialog. I've tried also to refresh only the panels with hidden buttons, but the effect was the same:
There is second refresh launched, after I call dialog.show(). The problem is, that the widgets defined inside the dialog and the dialog itself is not existing in the moment! So, when my JavaScript code runs too fast, before the post with update of the dialog finishes, I'm getting an exception, because the object I want to modify doesn't exist in DOM tree.
So my first question, is it possible to avoid such situation and second refresh, can't the dialog be refreshed along with page?
And second, if the first can't be answered, how can I launch my code after those second post finishes? I need simply a callback when refreshing of the dialog component will be completed, and than run my operations.
<p:commandButton id="doTask" value="Do task" widgetVar="doTaskButton"
action="#{service.doTask}" update="#form"
onclick="disableMainButtons()"
oncomplete="async.showAsyncDialog()" />
The HTTP sequence:
// button click
POST http://localhost:9080/myapp/order.xhtml 200 OK
// oncomplete launches dialog.show()
// I receive answer from COMET before the dialog to display it is shown
POST http://localhost:9080/myapp/channel/async 200 OK
// refresh triggered by dialog.show(), only now the dialog is shown and it's widgets are rendered
POST http://localhost:9080/myapp/order.xhtml 200 OK

The workaround, that isn't beautiful from programming point of view is to check if the dialog is rendered and if not, delay my procedure. In case the dialog is still not rendered, delay once again etc.
waitForDialogRendered: function() {
var visible = asyncDialog.jq.css('visibility') == 'visible';
if (!visible) {
setTimeout(waitForDialogRendered, 250);
return;
}
runComet();
}
Not that asyncDialog.jq.is(':visible') returns true even if dialog is not visible for user!
Still, I'd be happier without the need to write such code.

Related

Bootstrap remote Modal doesn't update content after first run

It comes javaScript and jQuery are beeing a big challenge for me. Like it's not enough I've started to use ajax to get over my problem - which is:
I've got some empty tables on my page. Each cell of a table has got its own id. A php-script is parsing a .xlsx file and puts the right link to the cell of my html table through javaScript code like:
document.getElementById("cellNrXY").innerHTML = "someLink";
If the link is clicked, then a Modal (Bootstrap) appears and loads the remote content (which is different depending on the clicked link).
My problem was that the remote content was cached in modal, so it worked only on first run. After closing the modal and choosing another link the previous modal appeared und didn't change to the new remote content.
I've read a lot solutions here that are based on:
$(this).removeData('bs.modal');
but had no luck with it. After some trying with different solutions one worked properly. The only problem was: when I've clicked the second time on some other link, the modal opened up with previous content and it took some seconds for the modal beeing updated. This is why I wanted to show a rotating element while the new modal content is beeing loaded. Somewhere here I've read a solution tu use ajax for this, which I've added "on luck" and ... it worked:
$("#myModal").on("show.bs.modal", function(e) {
$.ajax({
beforeSend: function() { $('#myModal')
.html('<div class="rotatingElement"></div>')
.show(); },
complete: function() { $('#myModal').html.hide(); }
});
var link = $(e.relatedTarget);
$(this).find(".modal-body").load(link.attr("href"));
});
The only thing is - I've no idea why this is working. Is there any chance that somebody here explain the functionality of this code to me?
if you read about the event show.bs.modal you will know that this event fires immediately when the show instance method is called. If caused by a click, the clicked element is available as the relatedTarget property of the event. Learn more about Events
so what is happening is every time you open a modal this event triggers and makes an ajax call which you see like this $.ajax({ wchi has 2 options set
A pre-request callback function beforeSend
A function to be called when the request finishes complete
so whenever the modal triggeres the ajax requet is made and every time ajax request i made just before sending the request the modal html is overridden $('#myModal').html('<div class="rotatingElement"></div>').show(); and a loader is added in form of a div element with class rotatingElement and as soon as the requet completes that loader is removed via complete function $('#myModal').html.hide(); and then the e.relatedTarget property as described above gets the anchor object and the href of that anchor .../remoteContent.php is loaded in side the modal body in the following 2 steps
var link = $(e.relatedTarget);
$(this).find(".modal-body").load(link.attr("href"));

Stop Safari extension from caching messages

I'm having problems with creating a safari extension that has been causing me headaches.
The problem is this: I have created an extension that gets images from a web page using an injected script. I have a function in the popover that displays the web images and allows the user to click and send the selected image to a backend. This all goes through the global page which handles signals and messages. The scenario is this:
When the popover opens, it sends a signal to the global page to initiate the response (image URLs) from the injected script.
When the global page gets the message from the injected script, it calls the function in the popover passing in the data from the injected script as an argument.
The popover shows all images returned from the global page via the injected script.
The problem is that every time I open the popover, it appends the images from the last call instead of giving a fresh list of images. For instance, on first popover open, I get one image (assuming the page has only one image). If I close the popover and open it again, I get two of the same image. If I close and open the popover a third time, it appends the first image with the one from the second time and gives me 3 of the same image. On the fourth open of the popover I get 1 + 1 + 1 + 1, so 4 images. So it seems to be appending the messages and not giving me a fresh message every time.
My question is: how can I destroy the messages that are being cached after each popover closes? I hope I am being clear. Perhaps something else is happening with my code that I am not aware of. Please help if you can. Here is my code from the global HTML:
function popoverHandler(event) {
//check for popover opening
if (event.target.identifier === "MyPopUp") {
//send message to injected script to send page info
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("getContent", '', false);
//this works fine, I get this message every time popover opens
console.log('getContent message sent');
//listen for message containing page info from injected script
safari.application.addEventListener('message', function (messageEvent) {
//only get message from current tab
if (messageEvent.name === "pageInfo" && messageEvent.message.url === safari.application.activeBrowserWindow.activeTab.url) {
pageInfo = messageEvent.message;
//the problem seems to be in here. Every time I open the popover, //I get the current page info plus all the page info messages from //the previous time I open the pover, all duplicates of the previous //messges
console.log(pageInfo);
// call a function in the popover, passing the pageInfo data //received from the injected script
safari.extension.popovers[0].contentWindow.onPageDetailsReceived(pageInfo);
}
});
}
}
Ok, so I was able to solve the problem. First of all, I separated the popoverHandler from the eventListener. For some reason, it was firing the function too many times and returning several lists of the same images. The major issue, however, was that in the popover.js, I was storing the list of images as a var. When I removed the var, the data stopped persisting and I was getting a fresh list every time.

javascript window confirm pops up several times

i am trying to use the confirm method but for some reason the confirm window pops up several times. I googled and tried different things but unfortunately I can't get it running properly. The code is the following:
//user clicks on the delete button
$("#deletePopUpImage").click(function(){
console.log("deletePopUpimageCalled");
//get the id of the image
id = ($(this).parent().prop("id"));
//create the ajax request
data = "typ=function&functionType=deleteUserImage&id="+id;
//open the confirm box
var r = confirm("Are you sure that you want to delete this image?");
if (r == true) {
console.log("loadAjaxCAlled");
//Ajax call
loadAjax(data);
//hide the image and the loader
hideImagePopup();
} else {
//do nothing
}
});
The strange thing is that sometimes the confirm window pops up twice, sometimes three times and sometimes as expected once. That's why inserted the two console.logs.
"deletePopUpimageCalled" always appears just once. However "loadAjaxCAlled" appears several times.
In the success callback of the Ajax request I am just hiding the thumbnail div.
Do you know what's wrong with my code above?
Thanks
Stefan
Probably the code that attaches the event:
$("#deletePopUpImage").click(function(){...});
is invoked several times. Every invocation of .click(...) makes a new handler that fires when the button is clicked.
Some browsers stack up log the same entries into one (so the log doesn't extend so fast), that could be the reason you don't see "deletePopUpimageCalled" many times.
It would the best to check this by debugging it in the browser.
Ok I found the problem. In the Ajax success handler I set the div of the image, that was deleted, to display:none instead of deleting it. Thus divIds could occur twice, three times, etc. After changing the code to delete, it worked smoothly.

Using Ajax.begin form in MVC application

I am working on MVC framework and posting my form by Ajax.BeginForm. No Doubt everything works very well but I have applied a ajax loader/Processing that starts work OnBegin and stops on this event OnComplete. So, when this function works after getting success from server:::
function MessageConfirmation(Json) {
if ($("#Id").val() > 0 && $("#Id").val() != '') {
}
else {
$("#Id").val(Json.Inserted_ID);
}
alert(Json.Message);
}
So, this message called after success but the problem arises when I am updating the page and clicking the submit again and again . So the Above function also works again and again and it brings a pop up alert that shows message. In that pop up if I click on "Prevent this page from creating addtional dialogs",
then it shows this error and no alert works
NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMWindow.alert] and ajax loader also keep on processing which is not user friendly at all and it shows if the record is not updated
If i get your question right you mean to say that after submit is clicked the success confirmation message is shown and then after subsequent click alert is generated and you want to prevent subsequent click.

How can my button close the window and refresh the parent after updating formview?

I have a "Save" button on a FormView with the CommandName="Update" set. This button updates an EntityDataSource that is bound to the FormView.
After the EDS is updated, I want to close this (child, popup) window and refresh my parent window (so it will reflect the changes just made to the data).
For reference, I have a similar "Cancel" button on this page that simply calls a Javascript function "OnClientClick":
function done() {
if (window.opener.closed) {
self.close();
} else {
window.opener.focus();
window.opener.location.href = opener.location;
self.close();
}
}
Now, how can I let the FormView and EDS do its thing (process the Update command) and then call this javascript function (or code to accomplish the equivalent)???
After doing some more digging, I solved it. The problem had to do with the FormView being inside an Update Panel. I had to use the following:
ScriptManager.RegisterClientScriptBlock(this.UpdatePanel1, typeof(string), "done", "done();", true);
As soon as your update is finished, it should return a page that you can just register your function with. In your Update command handler (assuming this is happening server side), just add the following:
Page.RegisterStartupScript("AfterUpdate", "done();");
It will cause the done() javascript function to run as soon as the windows refreshes from the postback caused by the update command. If you done function isn't already in the page, make sure you add it's definition before you call it to the RegisterStartupScript call.

Categories

Resources