1 // ==========================================================================
  2 // Project:   SproutCore - JavaScript Application Framework
  3 // Copyright: ©2006-2011 Strobe Inc. and contributors.
  4 //            Portions ©2008-2011 Apple Inc. All rights reserved.
  5 // License:   Licensed under MIT license (see license.js)
  6 // ==========================================================================
  7 
  8 /** @class
  9 
 10   Used to display an iframe. The source, (specified by the value property) of
 11   the iFrame should be from the same domain. (i.e. the src / value should be
 12   from the same domain) if you want to access the contents of the iframe.
 13 
 14   @extends SC.View
 15   @extends SC.Control
 16   @since SproutCore 1.0
 17 */
 18 SC.WebView = SC.View.extend(SC.Control, {/** @scope SC.WebView.prototype */
 19   classNames: 'sc-web-view',
 20 
 21   /**
 22     @type Array
 23     @default ['value', 'shouldAutoResize']
 24     @see SC.View#displayProperties
 25   */
 26   displayProperties: ['value', 'shouldAutoResize'],
 27 
 28   /**
 29     The content of the iframe can be bigger than the size specified when creating
 30     the view. If you want the view to be auto-resized to the dimensions of the
 31     iframe, then set the value of this property to YES.
 32     The web view can be auto resized only if the contents are from the same
 33     domain as the parent domain.
 34 
 35     @type Boolean
 36     @default NO
 37   */
 38   shouldAutoResize: NO,
 39 
 40   /**
 41     @param {SC.RenderContext} context
 42     @param {Boolean} firstTime
 43   */
 44   render: function(context, firstTime) {
 45     var src = this.get('value') || '',
 46       iframe;
 47 
 48     if (firstTime) {
 49       context.push('<iframe src="' + src +
 50       '" style="position: absolute; width: 100%; height: 100%; border: 0px; margin: 0px; padding: 0px;"></iframe>');
 51     }
 52     else if(src!==this._lastSrc) {
 53       iframe = this.$('iframe');
 54       // clear out the previous src, to force a reload
 55       iframe.attr('src', 'javascript:;');
 56       iframe.attr('src', src);
 57     }
 58 
 59     this._lastSrc = src;
 60   },
 61 
 62   /**
 63     Called when the layer gets created.
 64   */
 65   didCreateLayer: function() {
 66     var f = this.$('iframe');
 67     // Attach an onload event to the iframe.
 68     SC.Event.add(f, 'load', this, this.iframeDidLoad);
 69   },
 70 
 71   /**
 72     Called before the layer gets destroyed.
 73   */
 74   willDestroyLayer: function() {
 75     var f = this.$('iframe');
 76     // Remove the onload event so that the iframe can be released
 77     SC.Event.remove(f, 'load', this, this.iframeDidLoad);
 78   },
 79 
 80   /**  @private
 81     Called when iframe onload event is fired.
 82     1. Resizes the view to fit the contents of the iframe using the
 83     scroll width and scroll height of the contents of the iframe
 84 
 85     The iframe contents can be accessed only when the src is from the same
 86     domain as the parent document
 87   */
 88   iframeDidLoad: function() {
 89 
 90     //fit the iframe to size of the contents.
 91     if (this.get('shouldAutoResize') === YES) {
 92       var contentWindow;
 93       var iframeElt = this.$('iframe')[0];
 94       if(iframeElt && iframeElt.contentWindow) {
 95         contentWindow = iframeElt.contentWindow;
 96         if(contentWindow && contentWindow.document && contentWindow.document.documentElement){
 97           var docElement = contentWindow.document.documentElement;
 98           // setting the width before the height gives more accurate results..
 99           // at least for the test iframe content i'm using.
100           //TODO: try out document flows other than top to bottom.
101           if (!SC.browser.isIE) {
102             this.$().width(docElement.scrollWidth);
103             this.$().height(docElement.scrollHeight);
104           }
105           else {
106             this.$().width(docElement.scrollWidth + 12);
107             this.$().height(docElement.scrollHeight + 5);
108           }
109         }
110       }
111     }
112   }
113 
114 });
115