I am not sure if this is possible but I have a small web application that is responsible for uploading files to the server. This app is used by another app which includes it in an iFrame.
The uploader app is using jQuery form to submit the file in the background and I would like to be able to notify the parent app when the upload is complete and the success callback fires.
I was thinking about somehow passing a function into the iFrame app that could be called from the parent but I am not sure how to do this or if it is even possible.
If both apps are hosted on the same domain, accomplishing this is trivial.
To call a function in the parent window from the iframe:
parent.myFunction();
To call a function in the iframe from the parent window:
document.myFrameName.myFunction();
(This requires that the iframe have a name attribute set).
If the apps are on different domains, you'll have to perform some greater hackery to accomplish this.
You can call parent.functionname. Or you can try the IFrame event, onLoad to call from the parent page itself.
I'm not sure what's the right way to do this, but you can write something like document.callback = function() { ... } in your parent frame and parent.document.callback() in your iframe.
Of course your pages in parent frame/iframe must be from the same domain or browser will block any interaction between them.
Related
I'm asking for single paged JavaScript applications where the page does not make a full request. Specifically for a site like YouTube where the initial request is a full request and everything else is a XMLHttpRequest where only the body is changing client side.
An example would be YouTube. I want to do something like this:
You go to YouTube.com and click on one of the videos.
When the video page finishes loading, console.log("page loaded");
Is there an event listener I can add for when the page loads?
No events are being fired when the DOM is modified, so it's not possible to add a listener on anything like that.
You will have to keep track of the modifications on the DOM, manually. You could add "callbacks" to the modification functions you use:
function addSomethingToPage(data){
data.doSomething():
domReady();
}
function domReady(){
//re-usable "callback"
}
Supposedly I have a page ("A.php") using Backbone.js with the following route defined:
routes: {
'item/:num': 'showItem'
}
And there is a Flash SWF that'll get embedded in both A.php and B.php (another page, without any Backbone structure).
Is there anyway to make it so that when a button inside this SWF is clicked, it will invoke the method bound with the route 'item/:num': 'showItem' without a page reload if the SWF is on A.php, but performs normal linking behavior if it's on B.php?
You'll need to set up JavaScript functions with the same name in both A.php and B.php - for example, both pages have Javascript to define a goToShowItem() function.
A's function will call the Backbone routing code, B's function will simply set the window.location to the normal link address.
The button in your flash project will call getURL("javascript:goToShowItem();"); to call the current page's goToShowItem() function.
I have been writing a browser based application (or rather, rapid prototyping an application) using HTML and Javascript. I would like the main window to be able to display popup windows with dynamic data. However, I cannot figure out how to push data from a parent window to a popup window in Javascript. Note, I am working with the assumption that the application may be used in "offline" scenarios, so all dynamic data should be coming from the main window.
Ideally, I'd like to write
var popup = window.open("popup.html", someidentifier, "");
popup.document.getElementById("SomeIdInPopupHtml").innerHTML = "1,2,3,4";
However, the getElementById function returns NULL. How can I push data to popup windows from a parent window?
Is the popup serving content from a different domain than the parent? If so, the short answer is you can't.
The long answer is that you can sent the popup's href fragment (i.e. the part after the # in protocol://server/path?query#fragment). If the content in the popup knows to check its fragment for changes, then you can pass data to it.
If it's from the same domain then your code should work, as long as an element with that id exists.
However, the getElementById function returns NULL.
Because popup.html hasn't loaded yet. If you want to interact with content from the document, you'll have to call back later when it has finished loading.
For completely dynamic popups, open them with a blank URL and popupwindow.document.write their content into them. For co-operatively-scripting popups loaded from a separate document, have the child document call its parent when it is ready to be accessed. Or just use in-page pop-up divs which are typically less annoyance, both for you as a coder and for the end user.
Let me start off by presenting a possible solution that I just experimented with. I would like to encourage feedback and better solutions, however...
Its not very neat, but I can append GET-style query parameters to the source URL of the popup:
var popup = window.open("popup.html?" + identifier, somename, "");
Now in my particular situation, the popup is a view to some model identified by a unique ID, so the popup window can ask for the parent window for data related to that ID:
var model = window.opener.getModel(document.location.href.split("?")[1]);
do_something_with_model(model);
This strategy won't work in all cases, especially when the data is not easily marshaled into the getModel() implementation. However, in my case, I think this approach may work.
I'd appreciate feedback on this strategy. Thanks!
When the user clicks on your link to open the popup window pass a query string to it and then react to that value with your server side code.
Background: I have written a bookmarklet (JavaScript) that appends an iframe to the current page you are viewing. This iframe's src attribute is pointing to a form back on my application.
Problem: I am trying to utilize addEventListener to detect if that form has been submitted. However, I don't seem to be able to access the elements within the iframe.
For example:
document.getElementById(remote_form_id).addEventListener("submit",afterSubmit,true)
does not work because the getElementByID call is returning null.
My current work-around is to add an event listener on the iframe to listen for a "load" action and then call an intermediary function that ups a counter because I know how many times the iframe will be loaded before I need to call afterSubmit().
document.getElementById(marklet_iframe_id).addEventListener("load",listenForSubmit,true)
function listenForSubmit(){
if (count==1){afterSubmit();}
count++;
}
Basically, I'm looking for a best practice cause this is a crap approach.
Although it doesn't work in IE, you may want to look at the postMessage method of the pages' window objects. It allows you to asynchronously send string data between windows, even when direct access would be forbidden by the same-origin policy.
You can do something like this:
var doc = document.getElementById(marklet_iframe_id).contentDocument;
var form = doc.getElementById(formId)
form.addEventListener("submit", afterSubmit, true)
Try the EasyXDM library which uses the best-available techniques in a given user's browser to achieve this. It also is "best practice-y" in that its goal is to send messages between windows, and it's up to those windows to handle the messages, which mimicks the postMessage functionality available in HTML5 browsers.
Application that I'm working on has multiple modules. Two are of a concern - main module and module that I write. And I have to call a function on window that contains main module and the problem is that I have to call that function not from page that is opened by parent webmodule, but from page to which user navigates from this page.
Basically first page presents just some query forms, lets user to make some query, and second holds query results, and I am supposed to update contents of parent page based on these results.
Navigation goes like that
Main module
First page of my module (i have main module page as an window.opener variable.
Second page of my module (and I would like to be able to open this page in the same browser window that the first one is opened)
And I would like to have as free navigation as possible - like opening query results in new tab, going back changing query parameters, making new query, etc. I would also like to present user query forms on page that displays results and let them to refine this query, and still be able to update main module.
I was thinking of following solutions:
Using AJAX to load query results to first window, but I would like to have this app as simple as possible, and AJAX is not simple ;)
Spawning new window on every request and doing code like var mainModule = opener.mainModule. Which is evil.
Embedding query results in a frame or iframe, but I havn'e got the slightest idea on how to inject main module window javascript variable into frame or iframe.
If being able to navigate in tabs is a requirement, I think you'd have to nix the idea of using a JavaScript opened window system. Because the opener property is definitely lost in Firefox, Safari, and most browsers, when you navigate to a different window. A new tab disturbs the neat sandbox.
Not being a requirement, per your comment, I think you can use either of 3 methods:
Parent-Child window communication-- which I will take up
next;
XMLHTTP Requests (a.k.a.
AJAX); or
iFrames (the old way
to remote to the server :)
I'll take the Parent child communication angle, here, since you seem to be most comfortable with it.
Inter-navigation in a "Child" window is easy.
any link on the page loads in the child and shares the same "opener".
the parent can reload a different page and it shares the same opener.
There will be a parent-listener function in the child;
The child will have a separate function to talk to the parent.
The parent will have one or more child listeners, depending on how
generic, or specific your needs.
I've updated (not completely) an article I wrote years ago, to let you play around with the windows and to actually do a minimal form submission. The communication alerts are rather verbose; but you will have no doubt as to who is communicating what to whom. The first child is annoyingly opened onload. But there is a link on the page to change the child to a server-generated form.
JavaScript: Beyond Parent Child Windows
EXAMPLE CODE SNIPPETS:
A Link:
open a window from link
Link Listener:
The event listener and target property are set up in the head of the document, in JavaScript that executes onload:
var mywin; //global variable for best results
//XDOM - normalizes browser differences:
var openingLink = XDOM.getElementById('newwinlink');
openingLink.target = "newWin"; //important!
XDOM.addListener(openingLink, 'click', function(e){mywin=window.open('','newWin','width=400,height=400,resizable,scrollbars');if (!mywin.opener){mywin.opener = self;}return true}, false);
Child Document - Parent Listener:
function parentListener(pmsg)
{
alert("I'm the child, and I just received the following message from my parent:\n\n" + pmsg);
}
Child Document - Talk to Parent:
function talktoParent()
{
if (self.opener!=null) {
opener.childListener("Hi from child window!");
} else {
alert("no opener... sorry, can't talk now");
}
}
Parent Document - Child Listener:
function childListener(cmsg)
{
alert("I'm the parent. Just received the following message from my child:\n\n" + cmsg);
//send back a message to the child, mywin...
mywin.parentListener("Hi, back, from parent window!");
}
These are simplistic. But you can see opener continuity, navigation, and communication between server-side postbacks and the Parent at the link provided above.
Again the downside is that opening any of these in another tab will lose the connection to the parent. Try it over on the page that I sent you to. I believe the child is set to alert you that it is disconnected from its "opener".
Feel free to ask questions, jb.
iirc, even after you navigate away from the original document in a window opened by window.open, window.opener is still available.