microsoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemail
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
5.8 KiB
187 lines
5.8 KiB
/** |
|
* Barebones iframe implementation. |
|
*/ |
|
Ext.define('Ext.ux.IFrame', { |
|
extend: 'Ext.Component', |
|
|
|
alias: 'widget.uxiframe', |
|
|
|
loadMask: 'Loading...', |
|
|
|
src: 'about:blank', |
|
|
|
renderTpl: [ |
|
'<iframe src="{src}" id="{id}-iframeEl" data-ref="iframeEl" name="{frameName}" width="100%" height="100%" frameborder="0"></iframe>' |
|
], |
|
childEls: ['iframeEl'], |
|
|
|
initComponent: function () { |
|
this.callParent(); |
|
|
|
this.frameName = this.frameName || this.id + '-frame'; |
|
}, |
|
|
|
initEvents : function() { |
|
var me = this; |
|
me.callParent(); |
|
me.iframeEl.on('load', me.onLoad, me); |
|
}, |
|
|
|
initRenderData: function() { |
|
return Ext.apply(this.callParent(), { |
|
src: this.src, |
|
frameName: this.frameName |
|
}); |
|
}, |
|
|
|
getBody: function() { |
|
var doc = this.getDoc(); |
|
return doc.body || doc.documentElement; |
|
}, |
|
|
|
getDoc: function() { |
|
try { |
|
return this.getWin().document; |
|
} catch (ex) { |
|
return null; |
|
} |
|
}, |
|
|
|
getWin: function() { |
|
var me = this, |
|
name = me.frameName, |
|
win = Ext.isIE |
|
? me.iframeEl.dom.contentWindow |
|
: window.frames[name]; |
|
return win; |
|
}, |
|
|
|
getFrame: function() { |
|
var me = this; |
|
return me.iframeEl.dom; |
|
}, |
|
|
|
beforeDestroy: function () { |
|
this.cleanupListeners(true); |
|
this.callParent(); |
|
}, |
|
|
|
cleanupListeners: function(destroying){ |
|
var doc, prop; |
|
|
|
if (this.rendered) { |
|
try { |
|
doc = this.getDoc(); |
|
if (doc) { |
|
Ext.get(doc).un(this._docListeners); |
|
if (destroying) { |
|
for (prop in doc) { |
|
if (doc.hasOwnProperty && doc.hasOwnProperty(prop)) { |
|
delete doc[prop]; |
|
} |
|
} |
|
} |
|
} |
|
} catch(e) { } |
|
} |
|
}, |
|
|
|
onLoad: function() { |
|
var me = this, |
|
doc = me.getDoc(), |
|
fn = me.onRelayedEvent; |
|
|
|
if (doc) { |
|
try { |
|
// These events need to be relayed from the inner document (where they stop |
|
// bubbling) up to the outer document. This has to be done at the DOM level so |
|
// the event reaches listeners on elements like the document body. The effected |
|
// mechanisms that depend on this bubbling behavior are listed to the right |
|
// of the event. |
|
Ext.get(doc).on( |
|
me._docListeners = { |
|
mousedown: fn, // menu dismisal (MenuManager) and Window onMouseDown (toFront) |
|
mousemove: fn, // window resize drag detection |
|
mouseup: fn, // window resize termination |
|
click: fn, // not sure, but just to be safe |
|
dblclick: fn, // not sure again |
|
scope: me |
|
} |
|
); |
|
} catch(e) { |
|
// cannot do this xss |
|
} |
|
|
|
// We need to be sure we remove all our events from the iframe on unload or we're going to LEAK! |
|
Ext.get(this.getWin()).on('beforeunload', me.cleanupListeners, me); |
|
|
|
this.el.unmask(); |
|
this.fireEvent('load', this); |
|
|
|
} else if (me.src) { |
|
|
|
this.el.unmask(); |
|
this.fireEvent('error', this); |
|
} |
|
|
|
|
|
}, |
|
|
|
onRelayedEvent: function (event) { |
|
// relay event from the iframe's document to the document that owns the iframe... |
|
|
|
var iframeEl = this.iframeEl, |
|
|
|
// Get the left-based iframe position |
|
iframeXY = iframeEl.getTrueXY(), |
|
originalEventXY = event.getXY(), |
|
|
|
// Get the left-based XY position. |
|
// This is because the consumer of the injected event will |
|
// perform its own RTL normalization. |
|
eventXY = event.getTrueXY(); |
|
|
|
// the event from the inner document has XY relative to that document's origin, |
|
// so adjust it to use the origin of the iframe in the outer document: |
|
event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]]; |
|
|
|
event.injectEvent(iframeEl); // blame the iframe for the event... |
|
|
|
event.xy = originalEventXY; // restore the original XY (just for safety) |
|
}, |
|
|
|
load: function (src) { |
|
var me = this, |
|
text = me.loadMask, |
|
frame = me.getFrame(); |
|
|
|
if (me.fireEvent('beforeload', me, src) !== false) { |
|
if (text && me.el) { |
|
me.el.mask(text); |
|
} |
|
|
|
frame.src = me.src = (src || me.src); |
|
} |
|
} |
|
}); |
|
|
|
/* |
|
* TODO items: |
|
* |
|
* Iframe should clean up any Ext.dom.Element wrappers around its window, document |
|
* documentElement and body when it is destroyed. This helps prevent "Permission Denied" |
|
* errors in IE when Ext.dom.GarbageCollector tries to access those objects on an orphaned |
|
* iframe. Permission Denied errors can occur in one of the following 2 scenarios: |
|
* |
|
* a. When an iframe is removed from the document, and all references to it have been |
|
* removed, IE will "clear" the window object. At this point the window object becomes |
|
* completely inaccessible - accessing any of its properties results in a "Permission |
|
* Denied" error. http://msdn.microsoft.com/en-us/library/ie/hh180174(v=vs.85).aspx |
|
* |
|
* b. When an iframe is unloaded (either by navigating to a new url, or via document.open/ |
|
* document.write, new html and body elements are created and the old the html and body |
|
* elements are orphaned. Accessing the html and body elements or any of their properties |
|
* results in a "Permission Denied" error. |
|
*/ |
|
|
|
|
|
|