Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/net/iframeloadmonitor.js
2868 views
1
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Class that can be used to determine when an iframe is loaded.
17
*/
18
19
goog.provide('goog.net.IframeLoadMonitor');
20
21
goog.require('goog.dom');
22
goog.require('goog.events');
23
goog.require('goog.events.EventTarget');
24
goog.require('goog.events.EventType');
25
goog.require('goog.userAgent');
26
27
28
29
/**
30
* The correct way to determine whether a same-domain iframe has completed
31
* loading is different in IE and Firefox. This class abstracts above these
32
* differences, providing a consistent interface for:
33
* <ol>
34
* <li> Determing if an iframe is currently loaded
35
* <li> Listening for an iframe that is not currently loaded, to finish loading
36
* </ol>
37
*
38
* @param {HTMLIFrameElement} iframe An iframe.
39
* @param {boolean=} opt_hasContent Whether to wait for the loaded iframe to
40
* have content in its document body.
41
* @extends {goog.events.EventTarget}
42
* @constructor
43
* @final
44
*/
45
goog.net.IframeLoadMonitor = function(iframe, opt_hasContent) {
46
goog.net.IframeLoadMonitor.base(this, 'constructor');
47
48
/**
49
* Iframe whose load state is monitored by this IframeLoadMonitor
50
* @type {HTMLIFrameElement}
51
* @private
52
*/
53
this.iframe_ = iframe;
54
55
/**
56
* Whether to wait for the loaded iframe to have content in its document body.
57
* @type {boolean}
58
* @private
59
*/
60
this.hasContent_ = !!opt_hasContent;
61
62
/**
63
* Whether or not the iframe is loaded.
64
* @type {boolean}
65
* @private
66
*/
67
this.isLoaded_ = this.isLoadedHelper_();
68
69
if (!this.isLoaded_) {
70
// IE 6 (and lower?) does not reliably fire load events, so listen to
71
// readystatechange.
72
// IE 7 does not reliably fire readystatechange events but listening on load
73
// seems to work just fine.
74
var isIe6OrLess =
75
goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7');
76
var loadEvtType = isIe6OrLess ? goog.events.EventType.READYSTATECHANGE :
77
goog.events.EventType.LOAD;
78
this.onloadListenerKey_ = goog.events.listen(
79
this.iframe_, loadEvtType, this.handleLoad_, false, this);
80
81
// Sometimes we still don't get the event callback, so we'll poll just to
82
// be safe.
83
this.intervalId_ = window.setInterval(
84
goog.bind(this.handleLoad_, this),
85
goog.net.IframeLoadMonitor.POLL_INTERVAL_MS_);
86
}
87
};
88
goog.inherits(goog.net.IframeLoadMonitor, goog.events.EventTarget);
89
90
91
/**
92
* Event type dispatched by a goog.net.IframeLoadMonitor when it internal iframe
93
* finishes loading for the first time after construction of the
94
* goog.net.IframeLoadMonitor
95
* @type {string}
96
*/
97
goog.net.IframeLoadMonitor.LOAD_EVENT = 'ifload';
98
99
100
/**
101
* Poll interval for polling iframe load states in milliseconds.
102
* @type {number}
103
* @private
104
*/
105
goog.net.IframeLoadMonitor.POLL_INTERVAL_MS_ = 100;
106
107
108
/**
109
* Key for iframe load listener, or null if not currently listening on the
110
* iframe for a load event.
111
* @type {goog.events.Key}
112
* @private
113
*/
114
goog.net.IframeLoadMonitor.prototype.onloadListenerKey_ = null;
115
116
117
/**
118
* Returns whether or not the iframe is loaded.
119
* @return {boolean} whether or not the iframe is loaded.
120
*/
121
goog.net.IframeLoadMonitor.prototype.isLoaded = function() {
122
return this.isLoaded_;
123
};
124
125
126
/**
127
* Stops the poll timer if this IframeLoadMonitor is currently polling.
128
* @private
129
*/
130
goog.net.IframeLoadMonitor.prototype.maybeStopTimer_ = function() {
131
if (this.intervalId_) {
132
window.clearInterval(this.intervalId_);
133
this.intervalId_ = null;
134
}
135
};
136
137
138
/**
139
* Returns the iframe whose load state this IframeLoader monitors.
140
* @return {HTMLIFrameElement} the iframe whose load state this IframeLoader
141
* monitors.
142
*/
143
goog.net.IframeLoadMonitor.prototype.getIframe = function() {
144
return this.iframe_;
145
};
146
147
148
/** @override */
149
goog.net.IframeLoadMonitor.prototype.disposeInternal = function() {
150
delete this.iframe_;
151
this.maybeStopTimer_();
152
goog.events.unlistenByKey(this.onloadListenerKey_);
153
goog.net.IframeLoadMonitor.superClass_.disposeInternal.call(this);
154
};
155
156
157
/**
158
* Returns whether or not the iframe is loaded. Determines this by inspecting
159
* browser dependent properties of the iframe.
160
* @return {boolean} whether or not the iframe is loaded.
161
* @private
162
*/
163
goog.net.IframeLoadMonitor.prototype.isLoadedHelper_ = function() {
164
var isLoaded = false;
165
166
try {
167
if (!this.hasContent_ && goog.userAgent.IE &&
168
!goog.userAgent.isVersionOrHigher('11')) {
169
// IE versions before IE11 will reliably have readyState set to complete
170
// if the iframe is loaded.
171
isLoaded = this.iframe_.readyState == 'complete';
172
} else {
173
// For other browsers, check whether the document body exists to determine
174
// whether the iframe has loaded. Older versions of Firefox may fire the
175
// LOAD event early for an empty frame and then, a few hundred
176
// milliseconds later, replace the contentDocument. If the hasContent
177
// check is requested, the iframe is considered loaded only once there is
178
// content in the body.
179
var body = goog.dom.getFrameContentDocument(this.iframe_).body;
180
isLoaded = this.hasContent_ ? !!body && !!body.firstChild : !!body;
181
}
182
} catch (e) {
183
// Ignore these errors. This just means that the iframe is not loaded
184
// IE will throw error reading readyState if the iframe is not appended
185
// to the dom yet.
186
// Firefox will throw error getting the iframe body if the iframe is not
187
// fully loaded.
188
}
189
return isLoaded;
190
};
191
192
193
/**
194
* Handles an event indicating that the loading status of the iframe has
195
* changed. In Firefox this is a goog.events.EventType.LOAD event, in IE
196
* this is a goog.events.EventType.READYSTATECHANGED
197
* @private
198
*/
199
goog.net.IframeLoadMonitor.prototype.handleLoad_ = function() {
200
// Only do the handler if the iframe is loaded.
201
if (this.isLoadedHelper_()) {
202
this.maybeStopTimer_();
203
goog.events.unlistenByKey(this.onloadListenerKey_);
204
this.onloadListenerKey_ = null;
205
this.isLoaded_ = true;
206
this.dispatchEvent(goog.net.IframeLoadMonitor.LOAD_EVENT);
207
}
208
};
209
210