/*! * Ext JS Library 4.0 * Copyright(c) 2006-2011 Sencha Inc. * [email protected] * http://www.sencha.com/license */ /** * Barebones iframe implementation. For serious iframe work, see the * ManagedIFrame extension * (http://www.sencha.com/forum/showthread.php?71961). */ Ext.define('Ext.ux.IFrame', { extend: 'Ext.Component', alias: 'widget.uxiframe', loadMask: 'Loading...', src: 'about:blank', renderTpl: [ '<iframe src="{src}" name="{frameName}" width="100%" height="100%" frameborder="0"></iframe>' ], initComponent: function () { this.callParent(); this.frameName = this.frameName || this.id + '-frame'; this.addEvents( 'beforeload', 'load' ); Ext.apply(this.renderSelectors, { iframeEl: 'iframe' }); }, 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 () { var me = this, doc, prop; if (me.rendered) { try { doc = me.getDoc(); if (doc) { Ext.EventManager.removeAll(doc); for (prop in doc) { if (doc.hasOwnProperty && doc.hasOwnProperty(prop)) { delete doc[prop]; } } } } catch(e) { } } me.callParent(); }, onLoad: function() { var me = this, doc = me.getDoc(), fn = me.onRelayedEvent; if (doc) { try { Ext.EventManager.removeAll(doc); // 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.EventManager.on(doc, { 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.EventManager.on(window, 'unload', me.beforeDestroy, me); this.el.unmask(); this.fireEvent('load', this); } else if(me.src && 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 = Ext.Element.getTrueXY(iframeEl), originalEventXY = event.getXY(), // Get the left-based XY position. // This is because the consumer of the injected event (Ext.EventManager) will // perform its own RTL normalization. eventXY = Ext.EventManager.getPageXY(event.browserEvent); // 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); } } });