Iframe onload does not execute after file download? - javascript

I show a waiting dialog and then i create an iframe with the url of the file and append it to the document.
Neptune.ShowWaitingDialog();
iFrame.src = "ExportReportAllMediaDetailsCsv/?" + $.param(object);
iFrame.style.display = "none";
iFrame.onload = function () {
parent.Neptune.CloseWaitingDialog();
};
document.body.appendChild(iFrame);
If there is an error on the server side the iFrame.onload function executes accordingly and the waiting dialog is closed, however if a file is returned the onload function doesnt get executed and the waiting dialog stays open.
my question is, if a file is returned doesnt the iframe get refreshed and hence cause the onload event to execute?
if no then is there a way to detect if a file has been returned?

The way I do that, taken from T.J. Crowder's answer to this old question of mine, is this:
Add a hidden form field or GET parameter called "nonce" (or whatever you want). Fill it with a unique number or random string, either at page creation time or with JavaScript.
On the server, look for the "nonce" parameter and add a cookie called "FILE_READY" (or whatever you want), and set its value to the nonce value. Return the file as you normally would.
On the client, when the form posts or the iframe "src" is set — in other words, when you initiate the file download — start up a JavaScript interval timer to check the current value of the "FILE_READY" cookie. Check like every 100 milliseconds or so; it doesn't have to be super-frequently.
As soon as the "FILE_READY" cookie has the value sent in the "nonce" parameter, then you know that the HTTP response has come back from the server.
Works like a charm.

Related

Connection between Java and Javascript through ZK framework

I have been facing an issue with the communication between java and javascript through zk framework in a iframe.
In simple words, I want to save a string in the current session and access it (or even overwrite it) in javascript.
my java lines:
HttpSession session = (HttpSession)(Executions.getCurrent()).getDesktop().getSession().getNativeSession();
session.setAttribute("key","testing");
my zul lines:
<iframe id = "change_option" src="select_one_option.html" scrolling="no" width="700px" height="400px" > </iframe>
my javascript lines in the html file:
var session= /SESS\w*ID=([^;]+)/i.test(document.cookie) ? RegExp.$1 : false; //finds the correct session id + desktop name?
session = session.substring(0, session.indexOf('.')); //removes desktop name and keeps just the session id in a string
//another try
console.log("Saved: " + sessionStorage.getItem("key")); //returns "Saved: null"
//another try
var username = '<%= Session["key"] =%>'
console.log ( " Variable is : " + username) //returns "<%= Session["key"] %"
Since the html file is big I thought it would be better to do it through iframe and not try to rewrite inside the zul file. Any suggestion is highly appreciated.
There are a few approaches you can consider depending on your full requirement.
#1 The page located inside of the iframe and the outer page may communicate directly, using the window postMessage API:
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
This require a bit of setting up, but allows the page located in the iframe to post an event to the parent page. The event has a data field, which you can use to transfer data.
The parent page can subscribe to such event, and read the event data.
With this method, you don't actually need to write stuff to the session at server-side, since this communication happen fully at client-side.
This is good if the server doesn't care about knowing the value.
#2 saving the object in session from the inner page, using it from the outer page
You are already setting the session attribute in the native session:
HttpSession session = (HttpSession)(Executions.getCurrent()).getDesktop().getSession().getNativeSession();
session.setAttribute("key","testing");
Note that session attributes are Java-side only. They are not automatically returned to the client as cookies.
You can add a cookie with the same value to your response, if you want to handle this by cookies:
https://www.zkoss.org/wiki/ZK_Developer%27s_Reference/UI_Patterns/Communication/Inter-Application_Communication#Use_Cookie
However, this is a bit overkill because ZK is a communication framework and you can already pass the value to the outer zul page in a number of ways.
First, you can just execute arbitrary JS on the page using the Clients#evalJavascript method.
https://www.zkoss.org/wiki/ZK_Developer's_Reference/UI_Patterns/Useful_Java_Utilities#evalJavaScript
With that, you can just build a JS call containing your value retrieved at server side, and execute it in client. Should look like this:
String myValue = ... //retrieve your server-side value;
Clients.evalJavascript("myClientSideFunction('"+myValue+"')"); //executed in an execution of the zul page.
But you can also use that value as a client-attribute, pass it as a component value, etc.
There are a lot of arbitrary things you can do to pass that value back to the client, all with pros and cons.
For example, if you want to put that value back into a textbox, you can simply use the textbox#setValue method. It really depends on what you are looking to achieve.

Javascript Check if MS Form in Iframe was submitted

I have a Web based Training where we'd like to embed an MS-Form as an Iframe into a page and via Javascript would like to enable the next page when the user has submitted the form.
Is there any way possible to check if the MS-Form inside the iframe was submitted?
I tried by getting the iframe via an assigned ID, but it is not possible to access the iframes #document (security cross-origin reason) and for example check buttons.
Maybe there are some messages that can be posted to the contentWindow?
I've also seen, that there is no API that would support checking if I've already submitted a certain form. As far as I have seen it is only possible to access your own forms via API.
You can use the PostMessage api to listen/send events from and to the iframe.
https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/online/scenarios/postmessage
You can listen to events by adding this event listener after the iframe has loaded:
function handlePostMessage(e) {
// The actual message is contained in the data property of the event.
var msg = JSON.parse(e.data);
// The message ID is now a property of the message object.
var msgId = msg.MessageId;
// The message parameters themselves are in the Values
// parameter on the message object.
var msgData = msg.Values;
// Do something with the message here. }
window.addEventListener('message', handlePostMessage, false);

How to respond to an event after loading a hyperlink page?

I wonder is it possible to respond to an event after the client click the hyperlink and the hyperlink is loaded? Which that event can use properties in the hyperlink(i.e. id, class...etc)?
For example, page_A have a hyperlink
link
But since some_func need to use some properties in page_B, let say page_B have this line
<p id="a">hello world</p>
and some_func want to do something with it(e.g. document.getElementById("a")), how can I first load the hyperlink(page_B) then run some_func?
You could use the localStorage to save the name of the function that you want to execute on the second page, and call it once it loads.
The code would be like this:
JS
// a sample function to be called
function myFunc() {
alert("Called from previous page!");
}
// save the name of the function in the local storage
function saveForLater(func) {
localStorage.setItem("func", func);
}
// if the function exists
if (localStorage.func) {
// call it (not using the evil eval)
window[localStorage.func]();
// remove it from the storage so the next page doesn't execute it
localStorage.removeItem("func");
}
HTML (just for testing)
Go to Page 2<br/>
Go to Page 2 (not saving function)
Notice: as this code runs on the client's side, it is subject to be changed by the user, so you must be careful on how to proceed and execute the "saved" function, or you may find yourself with a security problem.

Execute javascript inside the target of an Ajax Call Drag and Drop Shopping Cart without Server language

Well i wanna create an Ajax Drag and Drop Shopping cart using only javascript and ajax. Currently i'm using the example in this page as a stepping stone. Right now it's only with local jquery and it works fine but i want to make the cart work with ajax calls. Note that i do not want to use a server side language( like php, rubby, asp etc), only html and javascript.
My initial thought was that at the $(".basket").droppable i should add an ajax call to another html page containing the "server logic" in javascript, execute in that file all the necessary steps( like reading the get variables (product name, product id and quantity), set a cookie and then return an ok response back. When the server got the "ok" response it should "reload" the cart div with the updated info stored inside the cookie.
If this was with php i would know how to do it. The problem is that as far as i know, you can execute javascript once it reaches the DOM, but how can you execute that js from inside the page that isbeing called upon ? ( thanks to Amadan for the correction)
I've thought about loading the script using $.getScript( "ajax/test.js", function( data, textStatus, jqxhr ).. but the problem with that is that the url GET variables i want to pass to the "server script" do not exist in that page.
I havent implemented all the functionality yet as i am stuck in how to first achieve javascript execution inside an ajax target page.
Below is a very basic form of my logic so far
// read GET variables
var product = getQueryVariable("product");
var id = getQueryVariable("id");
var quantity= getQueryVariable("quantity");
//To DO
//--- here eill go all the logic regarding cookie handling
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
alert('Query Variable ' + variable + ' not found');
}
Any help regarding this matter will be appreciated.
Note: Logic in simple words:
1)have an html page with products+cart
2)Have an "addtocart.html" with the "Cart Server Logic"( being the target of the ajax call when an item is dropped into the product.)
If you have some other idea on this, please enlighten me :)
thanks in advance
Foot Note-1:
if i try loading the scipt using
$("#response").load("ajax/addtocart.html?"+ $.param({
product: product,
id: id,
quantity:quantity
})
);
i get the alert about not being able to find the url parameters( something that i thing is normal as because the content is being loaded into the initial page, from which the request is started, there are no get parameters in the url in the first place)
The problem is that as far as i know, you cannot execute javascript contained in the target of an ajax call, as that page never reaches the browser interpreter.
This is either incorrect or misleading. The browser will execute any JavaScript that enters DOM. Thus, you can use $.load to load content and execute code at the same time. Alternately, you can use hacked JSONP to both execute code and also provide content as a JSON document.
EDIT: Yes, you can't get to the AJAX parameters from JavaScript. Why do you want to? Do you have a good reason for it, or is it an XY problem?
The way I'd do it is this:
$('#response').load(url, data, function() {
onAddedToCart(product, id, quantity);
});
and wrap your JS code in your HTML into the onAddedToCart function.
Depending on what exactly you're doing, it could be simplified even further, but this should be enough to cover your use case.

Redirect page and call javascript function

I need to redirect to another page onClick of submit and call a function making an ajax call. This is what I have :
$('#submitButton').click(function() {
window.location.href = "otherPage";
displayData();
});
Also, Another way I tried is to set the form fields on otherPage by using
var elem = window.document.getElementById(field);
elem.value = "new-value";
so that I could call the eventhandler of a submit button present on otherPage, but it doesn't work. Please let me know where I am wrong.
I'm not sure if there is a neat way to achieve this, but you can add a hash in your url you redirect to, then just simply check if the hash exists, execute function and remove hash.
Here are some handy URLs:
Location.Hash - information about this function and how to use it.
Removing hash from url without a page refresh - This was a bit of an issue, as window.location.href = ''; removes everything after the hash.
A hash (as Arko Elsenaar said) or a querystring parameter added to the target URL would allow you to detect what to do once there.
The hash makes it a bit easier while the querystring is cleaner if you want to pass more information.
For instance on the first page: window.location.href = "other/page.html#displayData";
On the second page:
if (window.location.hash === '#displayData') {displayData();}
Another way could be to use the HTML5 Storage API, if and only if the 2 pages are on the same domain.
1st page would do, before the redirection:
localStorage.displayData = true
And the 2nd:
if (localStorage.displayData) {displayData();}
However in this case you'll need to clean up the localStorage.displayData value when used, otherwise it will stay there forever and your second page would always find it set to true.
delete localStorage.displayData
All in all, the hash method seems best here.

Categories

Resources