/*! * VisualEditor UserInterface Frame class. * * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ /** * UserInterface iframe abstraction. * * @class * @extends ve.Element * @mixins ve.EventEmitter * * @constructor * @param {Object} [config] Configuration options */ ve.ui.Frame = function VeUiFrame( config ) { // Parent constructor ve.Element.call( this, config ); // Mixin constructors ve.EventEmitter.call( this ); // Properties this.initialized = false; this.config = config; // Initialize this.$ .addClass( 've-ui-frame' ) .attr( { 'frameborder': 0, 'scrolling': 'no' } ); }; /* Inheritance */ ve.inheritClass( ve.ui.Frame, ve.Element ); ve.mixinClass( ve.ui.Frame, ve.EventEmitter ); /* Static Properties */ ve.ui.Frame.static.tagName = 'iframe'; /* Events */ /** * @event initialize */ /* Methods */ /** * Load the frame contents. * * Once the iframe's stylesheets are loaded, the `initialize` event will be emitted. * * Sounds simple right? Read on... * * When you create a dynamic iframe using open/write/close, the window.load event for the * iframe is triggered when you call close, and there's no further load event to indicate that * everything is actually loaded. * * By dynamically adding stylesheet links, we can detect when each link is loaded by testing if we * have access to each of their `sheet.cssRules` properties. Every 10ms we poll to see if we have * access to the style's `sheet.cssRules` property yet. * * However, because of security issues, we never have such access if the stylesheet came from a * different site. Thus, we are left with linking to the stylesheets through a style element with * multiple `@import` statements - which ends up being simpler anyway. Since we created that style, * we always have access, and its contents are only available when everything is done loading. * * @emits initialize */ ve.ui.Frame.prototype.load = function () { var win = this.$.prop( 'contentWindow' ), doc = win.document; // Figure out directionality: this.dir = this.$.closest( '[dir]' ).prop( 'dir' ) || 'ltr'; // Initialize contents doc.open(); doc.write( '' + '' + '
' + '' + '' + '' ); doc.close(); // Properties this.$$ = ve.Element.get$$( doc, this ); this.$content = this.$$( '.ve-ui-frame-content' ); this.$document = this.$$( doc ); this.transplantStyles(); this.initialized = true; this.emit( 'initialize' ); }; /** * Transplant the CSS styles from the frame's parent document to the frame's document. * * This loops over the style sheets in the parent document, and copies their tags to the * frame's document. `` tags pointing to same-origin style sheets are inlined as `