Cross-browser IFRAME onload event listening)

Source: Internet
Author: User

In many cases, we need to change an IFRAME address (src attribute), or use the target of the form (Form) to submit in the specified IFRAME, and load the IFRAME (onload) to improve the value of Web applications. This article discusses how to listen for cross-browser IFRAME onload events.

If you do not have time to read the full text, you can view the solution Overview:

1. Page nesting in the same domain. It is best to have the embedded page call the function of the parent page, such as window. Parent. callparentfunctoin ().
2. if it is a foreign country or the child page already exists and cannot be modified, you can directly use the IFRAME onload event in Firefox/Opera/safari. in IE, you can use the timer to determine the document of the Child page. readystate, or use the IFRAME onreadystatechange event to calculate the number of responses to this event.

The above content is based on reference documents: q2000038 and q188763.

If you are very interested in this topic, please continue reading...

Note [1]: in order to make the problem more concentrated, the <IFRAME> described in this article are directly written in the parent page. createelement ("IFRAME") or IFRAME created by other methods are not discussed, because this will make the problem more complicated in IE, but as long as you use the conclusion in this article, no matter how IFRAME is created, the problem will still be solved.

A simple parent page containing IFRAME will look like this:

<! Doctype...>
<HTML xmlns = "...">
<Head>
<Meta.../>
<Title> IFRAME </title>
<Body>
<IFRAME name = "iframe1" id = "iframe1" width = "300" Height = "50" src = "#"> </iframe>
<SCRIPT type = "text/JavaScript"> // codes here </SCRIPT>
</Body>
</Html>

Start:

Let's start with a simple scenario and solution:
1. Window. Parent object
1.1 call the parent Page Object

<! -This is an inner page in the IFRAME->
<SCRIPT type = "text/JavaScript">
Window. onload = function {window. Parent. iframecall ();}
</SCRIPT>

Among the methods found on the Internet, the most interesting one is to call the parent page object on the Child page:

Window. Parent. callfunciton ().

But I think: Maybe everyone on Earth knows this. This method has a disadvantage, that is, the Child parent page must be in the same domain.

Another point is that front-end engineers must have the right to modify their child pages. Alternatively, they can ask their colleagues on this child page to add a piece of code for us:

<SCRIPT type = "text/JavaScript">
If (window. parent! = Window) window. Parent. iframecall ();
</SCRIPT>

Put it in window. onglad, or put it directly before </body>.

Note [2]: In front-end programming of IFRAME or other window properties, the same domain name is the most perfect innate condition. As long as the objects in various windows are shared in the same domain name, we can use them freely and control them back and forth between different windows. In short, you can't do it unless you can't think of it.
1.2 exotic

On pages of different domain names, the browser almost completely blocks the object communication between pages for security considerations. Here there is no Magpie Bridge, and the Cowherd and Weaver girl can only look far away. Of course, you can use IFRAME to nest pages. After all, you can miss it.

In the face of the family's blockout, Romeo still wants to see Juliette. He sets up a ladder in the night to catch Julia's window to meet her. In the nesting of exotic pages, sub-pages can always directly change the location of the parent window to prevent nesting, but the parent page does not have this method.

Of course, except for having the modification permission of the parent window. Location permanently, the Child page does not have any more. For example, in IE, the Child page can only directly change the. Location of the parent page to another source:

<SCRIPT tyle = "text/JavaScript"> parent. Location = "http://anotherpage.com/#; </SCRIPT>

However, you cannot access other objects, such as window. Name and document. You cannot access the sub-attributes of location. href. Of course, using top. Location is more powerful in preventing nesting.

However, in Firefox, it seems that you can add some things for top. Location, but this is a situation that has occurred in my not rigorous tests and has not been found in the relevant authoritative documentation.
2. IFRAME onload event

In Firefox/Opera/safari, you can directly use the onload event of the frame element:
Document. getelementbyid ("iframe1"). onload = function (){
// Your codes here.
};
It is a pity that it often does not work in IE, because in IE, it can only be activated once at most, and no matter how many IFRAME you have, the activated one can only be the last one. For more details, see q2000038 and q188763.

Cause
These events are activated in the Document Object Model in IFRAME, rather than the parent page. When the IFRAME is loaded, the event is activated, and the readystate is "completed. Therefore, you cannot use this event to check whether an IFRAME has been loaded.

For better performance, let's look at the problem: IFRAME recursion.
3. IFRAME Recursion

When processing IFRAME, the browser should have a basic rule, that is, to prevent recursion, prevent unlimited page self-loading, and cause the client device to crash. In fact, the several browsers mentioned in this Article do this, but different browsers have different processing methods. Try the following code:
<IFRAME src = "onload =" finish () "name =" iframe1 "> </iframe>
<IFRAME src = "# hashonly" onLoad = "finish ()" name = "iframe2"> </iframe>
<IFRAME src = "? Search "onLoad =" finish () "name =" iframe3 "> </iframe>
<IFRAME src = "http://anotherPage.com" onload = "finish ()" name = "iframe4"> </iframe>
The execution result is that when the parent page is loaded, the above IFRAME onload function will be activated in IE/Opera/safari, and Firefox will not respond to the second function. This is mainly because they have different processing methods in preventing recursion.
For # hashonly and? The browser will interpret a URL such as search as the page itself. However, the difference between hash and search is that changing search can form a new source without changing the hash. Generally, when a browser encounters an IFRAME page of the same source, it stops loading, but safari loads the page multiple times.
Assume that the finish () function is written as follows:
VaR finsh = function () {alert ("onload from:" + this. SRC );}
The message pop-up boxes popped up during running are as follows:

IFM/BRW: IE | Firefox | opera | Safari
Iframe1: 1 | 1 | 1 | 0
Iframe2: 1 | 0 | 1 | 1
Iframe3: 2 | 1 | 2 | 2
Iframe4: 1 | 1 | 1 | 1

Based on the content displayed on the page, we can see some detailed rules of these browsers on Recursive processing:

* Firefox does not load anything in IFRAME or activate the onload event (possibly any event)
* IE and opera will not load pages in IFRAME, but will activate the onload event.
* Safari (Windows Version) loads the page once and only once in IFRAME, activates the onlaod event, and only activates the onload event attached to the IFRAME on the parent page.

In this section, if you only use IFRAME for page nesting, it is of little significance. If it is used for dynamic loading/rendering of internal pages, or form target form submission for good user experience (not Ajax ), the function is displayed only when high browser compatibility is required. To improve compatibility, the final result of this section points iframeto an empty page, which is the same in four browsers. If you don't want to load the page beforehand, you have to spend more time determining the browser type.
4. Code Implementation
4.1.firefox/Opera/safari, directly use the IFRAME onload event

Document. getelementbyid ("iframe1"). onload = function (){
// Your codes here.
};

. In ie, the timer tests document. readystate or registers IFRAME onreadystatechange event.

4.2.1. timer and document. readystate

VaR FM1 = Window. Frames ["iframe1"];
VaR fmstate = function (){
VaR state = NULL;
If (document. readystate ){
Try {
State1_fm1.doc ument. readystate;
} Catch (e) {state = NULL ;}
If (State = "complete" |! State) {// loading, interactive, complete
// Oncomplete ();
Return;
}
Window. setTimeout (fmstate, 10 );
}
};
// Execute the following statement when you change SRC or submit a form through form target:
If (fmstate. timeoutint) window. cleartimeout (fmstate. timeoutint );
Fmstate. timeoutint = Window. setTimeout (fmstatus, 400 );

Why is the latency 400 milliseconds? Because JavaScript operations on the Dom are asynchronous, we must wait for the script to execute the DOM before starting the next step. 400 seconds depends on the response speed of the client devices and browsers. The response speed of a good device can be 10 milliseconds or even faster, but about 100 milliseconds may be popular, 400 milliseconds should be very conservative. In short, a large number of milliseconds can adapt to more user device conditions and reduce the workload of client devices.

For document. readystate, it refers to the docuent. readystate of the child pages in IFRAME, rather than the parent page. If allowed, document. readystate returns five states in the same domain:
Uninitialized Object not initialized.
The loading object is loading data.
The loaded object has loaded data.
In this status, the user can participate in the interaction, even if the object is not loaded.
The complete object has been initialized.

Why try and catch? In exotic cases, when the IFRAME sub-page reaches the interactive state, the parent page will lose access, so it can only return to the loaded step at most, therefore, ie has an unknown error-in fact, it does not have the permission, so try and catch make the error silence.

Fortunately, this method only applies to IE (the version I can use now: IE6/7). Otherwise, it is too troublesome: opera starts interaction after loading the page, IE interacts with each other only after the page is loaded. Therefore, it feels that using opera to open a webpage is faster than that of IE.

4.2.2.onreadystatechange event three steps

VaR stateid = {};
VaR fmstchange = function (){
If (iffirstload) return;
Stateid [This. ID] = stateid [This. ID]? Stateid [This. ID] + 1:1;
Switch (stateid [This. ID]) {
Case 1:
// State Loading
// Oncomplete (Step1 );
Break;
Case 2:
// State interactive
// Oncomplete (step 2 );
Break;
Case 3:
// State complete
// Oncomplete (laststep );
Break;
}
If (stateid [This. ID] & gt; = 3) stateid [This. ID] = NULL;
};
$ ("Iframe1"). onreadystatechange = fmstchange;
// If you want to ignore the parent page Load
// Add the following two line
VaR iffirstload = true;
$ ("Iframe1"). onload = function () {iffirstload = false ;}

Each time an IFRAME loads a page, the onreadystatechange event is activated three times during the process. The corresponding statuses are loading, interactive, and complete, and the last one is complete. Therefore, we need to calculate this, it is not completed until the third time.

Note: stateid in this scheme is very important in status judgment and must be corrected and protected. For example, if you set stateid [iframe_id] to null every time IFRAME is applied, alternatively, do not load the IFRAME in a new round before the third response is complete, or delete the previous events and reset them before loading the new page.

 

 

 

-----------------------------------------------------------------------

Small programmer | PHP learning exchange www.xiaophper.com

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.