//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package mx.controls { import flash.events.Event; import flash.events.FocusEvent; import flash.events.HTMLUncaughtScriptExceptionEvent; import flash.events.MouseEvent; import flash.html.HTMLLoader; import flash.html.HTMLHistoryItem; import flash.html.HTMLHost; import flash.net.URLRequest; import flash.system.ApplicationDomain; import flash.system.IME; import flash.system.IMEConversionMode; import mx.controls.listClasses.BaseListData; import mx.controls.listClasses.IDropInListItemRenderer; import mx.controls.listClasses.IListItemRenderer; import mx.core.ClassFactory; import mx.core.EdgeMetrics; import mx.core.IDataRenderer; import mx.core.IFactory; import mx.core.IIMESupport; import mx.core.FlexHTMLLoader; import mx.core.mx_internal; import mx.core.ScrollControlBase; import mx.core.ScrollPolicy; import mx.events.FlexEvent; import mx.events.ScrollEvent; import mx.styles.StyleManager import mx.styles.CSSStyleDeclaration; import mx.managers.IFocusManagerComponent; use namespace mx_internal; //-------------------------------------- // Events //-------------------------------------- /** * Dispatched after the last loading operation caused by * setting the location or htmlText * property has completed. * *

This event is always dispatched asynchronously, * after the JavaScript load event * has been dispatched in the HTML DOM.

* *

An event handler for this event may call any method * or access any property of this control * or its internal htmlLoader.

* * @eventType flash.events.Event.COMPLETE * * @see location * @see htmlText * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Event(name="complete", type="flash.events.Event")] /** * Dispatched after the HTML DOM has been initialized * in response to a loading operation caused by * setting the location or htmlText property. * *

When this event is dispatched, * no JavaScript methods have yet executed. * The domWindowand domWindow.document * objects exist, but other DOM objects may not. * You can use this event to set properties * onto the domWindow and domWindow.document * objects for JavaScript methods to later access.

* *

A handler for this event should not set any properties * or call any methods which start another loading operation * or which affect the URL for the current loading operation; * doing so causes either an ActionScript or a JavaScript exception.

* * @eventType flash.events.Event.HTML_DOM_INITIALIZE * * @see location * @see htmlText * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Event(name="htmlDOMInitialize", type="flash.events.Event")] /** * Dispatched when this control's HTML content initially renders, * and each time that it re-renders. * *

Because an HTML control can dispatch many of these events, * you should avoid significant processing in a render * handler that might negatively impact performance.

* * @eventType flash.events.Event.HTML_RENDER * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Event(name="htmlRender", type="flash.events.Event")] /** * Dispatched when the location property changes. * *

This event is always dispatched asynchronously. * An event handler for this event may call any method * or access any property of this control * or its internal htmlLoader.

* * @eventType flash.events.Event.LOCATION_CHANGE * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Event(name="locationChange", type="flash.events.Event")] /** * Dispatched when an uncaught JavaScript exception occurs. * *

This event is always dispatched asynchronously. * An event handler for this event may call any method * or access any property of this control * or its internal htmlLoader.

* * @eventType flash.events.HTMLUncaughtScriptExceptionEvent.UNCAUGHT_SCRIPT_EXCEPTION * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Event(name="uncaughtScriptException", type="flash.events.HTMLUncaughtScriptExceptionEvent")] //-------------------------------------- // Styles //-------------------------------------- /** * The number of pixels between the bottom edge of this control * and the bottom edge of its HTML content area. * * @default 0 * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Style(name="paddingBottom", type="Number", format="Length", inherit="no")] /** * The number of pixels between the left edge of this control * and the left edge of its HTML content area. * * @default 0 * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Style(name="paddingLeft", type="Number", format="Length", inherit="no")] /** * The number of pixels between the right edge of this control * and the right edge of its HTML content area. * * @default 0 * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Style(name="paddingRight", type="Number", format="Length", inherit="no")] /** * The number of pixels between the top edge of this control * and the top edge of its HTML content area. * * @default 0 * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ [Style(name="paddingTop", type="Number", format="Length", inherit="no")] //-------------------------------------- // Other metadata //-------------------------------------- [IconFile("HTML.png")] [ResourceBundle("controls")] /** * The HTML control lets you display HTML content in your application. * *

You use the location property to specify the URL * of an HTML page whose content is displayed in the control, or you * can set the htmlText property to specify a String * containing HTML-formatted text that is rendered in the control.

* * @mxml * *

The <mx:HTML> tag inherits all of the tag * attributes of its superclass and adds the following tag attributes:

* *
 *  <mx:HTML
 *    Properties
 *    data="null"
 *    historyPosition="0"
 *    htmlHost="null"
 *    htmlLoaderFactory="mx.core.ClassFactory"
 *    htmlText=""
 *    listData="null"
 *    location=""
 *    paintsDefaultBackground="false"
 *    runtimeApplicationDomain="null"
 *    userAgent="null"
 * 
 *    Styles
 *    paddingBottom="0"
 *    paddingLeft="0"
 *    paddingRight="0"
 *    paddingTop="0"
 * 
 *    Events
 *    complete="No default"
 *    htmlDOMInitialize="No default"
 *    htmlRender="No default"
 *    locationChange="No default"
 *    uncaughtScriptException="No default"
 *  />
 *  
* * @see ../../flash/html/HTMLLoader.html HTMLLoader * * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public class HTML extends ScrollControlBase implements IDataRenderer, IDropInListItemRenderer, IListItemRenderer, IFocusManagerComponent { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Class constants // //-------------------------------------------------------------------------- /** * @private */ private static const MAX_HTML_WIDTH:Number = 2880; /** * @private */ private static const MAX_HTML_HEIGHT:Number = 2880; //-------------------------------------------------------------------------- // // Class properties // //-------------------------------------------------------------------------- //---------------------------------- // pdfCapability //---------------------------------- /** * The type of PDF support on the user's system, * defined as an integer code value. * *

An HTML object can display PDF content only if this property * evaluates to PDFCapability.STATUS_OK. * The PDFCapability class defines constants for possible values * of the pdfCapability property, as follows:

* * * * * * * * * * * * * * * * * * * * * * *
PDFCapability constantMeaning
STATUS_OKA sufficient version (8.1 or later) of Acrobat Reader * is detected and PDF content can be loaded in an HTML object. *

Note: On Windows, if a Acrobat Acrobat * or Acrobat Reader version 7.x or above * is currently running on the user's system, * that version is used even if a later version * that supports loading PDF loaded in an HTML object is installed. * In this case, if the the value of the * pdfCampability property is * PDFCapability.STATUS_OK, * when an AIR application attempts to load PDF content * into an HTML object, the older version of Acrobat or Reader * displays an alert, without an error message displayed the AIR runtime. * If this is a possible situation for your end users, * you may consider providing them with instructions to close Acrobat * while running your application. * You may consider displaying these instructions if the PDF * content does not load within an acceptable timeframe.

ERROR_INSTALLED_READER_NOT_FOUNDNo version of Acrobat Reader is detected. * An HTML object cannot display PDF content.
ERROR_INSTALLED_READER_TOO_OLDAcrobat Reader has been detected, but the version is too old. * An HTML object cannot display PDF content.
ERROR_PREFERED_READER_TOO_OLDA sufficient version (8.1 or later) of Acrobat Reader is detected, * but the the version of Acrobat Reader that is setup * to handle PDF content is older than Reader 8.1. * An HTML object cannot display PDF content.
* * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public static function get pdfCapability():int { return HTMLLoader.pdfCapability; } //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function HTML() { super(); _horizontalScrollPolicy = ScrollPolicy.AUTO; _verticalScrollPolicy = ScrollPolicy.AUTO; tabFocusEnabled = false; } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- /** * @private * Flag that will block default data/listData behavior. */ private var textSet:Boolean; /** * @private */ private var errorCaught:Boolean = false; //-------------------------------------------------------------------------- // // Overridden properties // //-------------------------------------------------------------------------- /** * @private */ override public function set verticalScrollPosition(value:Number):void { // Clip the vertical scroll position to appropriate min/max bounds. value = Math.max(value,0); if (htmlLoader && (htmlLoader.contentHeight > htmlLoader.height)) value = Math.min(value,htmlLoader.contentHeight - htmlLoader.height) super.verticalScrollPosition = value; if (htmlLoader) htmlLoader.scrollV = value; else invalidateProperties(); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // contentHeight //---------------------------------- /** * The height, in pixels, of the HTML content. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get contentHeight():Number { if (!htmlLoader) return 0; return htmlLoader.contentHeight; } //---------------------------------- // contentWidth //---------------------------------- /** * The width, in pixels, of the HTML content. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get contentWidth():Number { if (!htmlLoader) return 0; return htmlLoader.contentWidth; } //---------------------------------- // data //---------------------------------- /** * @private * Storage for the data property. */ private var _data:Object; [Bindable("dataChange")] [Inspectable(environment="none")] /** * Lets you pass a value to the component * when you use it in an item renderer or item editor. * You typically use data binding to bind a field of the data * property to a property of this component. * *

When you use the control as a drop-in item renderer or drop-in * item editor, Flex automatically writes the current value of the item * to the text property of this control.

* *

You cannot set this property in MXML.

* * @default null * @see mx.core.IDataRenderer * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get data():Object { return _data; } /** * @private */ public function set data(value:Object):void { var newText:*; _data = value; if (_listData) { newText = _listData.label; } else if (_data != null) { if (_data is String) newText = String(_data); else newText = _data.toString(); } if (newText !== undefined && !textSet) { htmlText = newText; textSet = false; } dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE)); } //---------------------------------- // historyLength //---------------------------------- /** * The overall length of the history list, * including back and forward entries. * * This property has the same value * as the window.history.length * JavaScript property of the the HTML content. * * @see #historyPosition * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get historyLength():int { if (!htmlLoader) return 0; return htmlLoader.historyLength; } //---------------------------------- // historyPosition //---------------------------------- /** * The current position in the history list. * *

The history list corresponds to the window.history * object of the HTML content. * Entries less than the current position are the "back" list; * entries greater are "forward." * Attempting to set the position beyond the end sets it to the end.

* * @default 0 * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get historyPosition():int { if (!htmlLoader) return 0; return htmlLoader.historyPosition; } /** * @private */ public function set historyPosition(value:int):void { if (htmlLoader) htmlLoader.historyPosition = value; } //---------------------------------- // htmlLoader //---------------------------------- /** * The internal HTMLLoader object that renders * the HTML content for this control. * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public var htmlLoader:HTMLLoader; //---------------------------------- // htmlLoaderFactory //---------------------------------- /** * @private * Storage for the htmlLoaderFactory property. */ private var _htmlLoaderFactory:IFactory = new ClassFactory(FlexHTMLLoader); [Bindable("htmlLoaderFactoryChanged")] /** * The IFactory that creates an HTMLLoader-derived instance * to use as the htmlLoader. * *

The default value is an IFactory for HTMLLoader.

* * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get htmlLoaderFactory():IFactory { return _htmlLoaderFactory; } /** * @private */ public function set htmlLoaderFactory(value:IFactory):void { _htmlLoaderFactory = value; dispatchEvent(new Event("htmlLoaderFactoryChanged")); } //---------------------------------- // htmlHost //---------------------------------- /** * @private * Storage for the htmlHost property. */ private var _htmlHost:HTMLHost; /** * @private */ private var htmlHostChanged:Boolean = false; /** * The HTMLHost object is used to handle changes * to certain user interface elements in the HTML content, * such as the window.document.title property. * *

To override default behaviors for the HTMLLoader, * create a subclass of the HTMLHost class, * override its member functions * to handle various user interface changes in the HTML content, * and set this property to an instance of your subclass.

* * @default null * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get htmlHost():HTMLHost { return _htmlHost; } /** * @private */ public function set htmlHost(value:HTMLHost):void { _htmlHost = value; htmlHostChanged = true; invalidateProperties(); } //---------------------------------- // htmlText //---------------------------------- /** * @private * Storage for the htmlText property. */ private var _htmlText:String; /** * @private */ private var htmlTextChanged:Boolean = false; [Bindable("htmlTextChanged")] /** * Specifies an HTML-formatted String for display by the control. * *

Setting this property has the side effect of setting * the location property to null, * and vice versa.

* *

Content added via the htmlText property is put in the * application security sandbox. If an AIR application includes an HTML * control located in the application sandbox, and remote HTML code is * directly added into the control by setting the htmlText * property, any script contained in the HTML text is executed in the * application sandbox.

* * @default "" * * @see #location * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get htmlText():String { return _htmlText; } /** * @private */ public function set htmlText(value:String):void { _htmlText = value; htmlTextChanged = true; // Setting both location and htmlText doesn't make sense, // so setting one sets the other to null, // and the last one set is applied in commitProperties(). _location = null; locationChanged = false; invalidateProperties(); invalidateSize(); invalidateDisplayList(); dispatchEvent(new Event("htmlTextChanged")); } //---------------------------------- // domWindow //---------------------------------- /** * The JavaScript window object * for the root frame of the HTML DOM inside this control. * *

This property is null until the * htmlDOMInitialize event has been dispatched.

* * @default null * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get domWindow():Object { if (!htmlLoader) return null; return htmlLoader.window; } //---------------------------------- // imeMode //---------------------------------- /** * @private */ private var _imeMode:String = null; /** * Specifies the IME (input method editor) mode. * The IME enables users to enter text in Chinese, Japanese, and Korean. * Flex sets the specified IME mode when the control gets the focus, * and sets it back to the previous value when the control loses the focus. * *

The flash.system.IMEConversionMode class defines constants for the * valid values for this property. * You can also specify null to specify no IME.

* * @default null * * @see flash.system.IMEConversionMode * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get imeMode():String { return _imeMode; } /** * @private */ public function set imeMode(value:String):void { _imeMode = value; // We don't call IME.conversionMode here. We call it // only on focusIn. Thus fringe cases like setting // imeMode dynamically without moving focus, through // keyboard events, wouldn't change the mode. Also // getting imeMode asynch. from the server which gets // delayed and set later after focusIn is not handled // as having the text partly in one script and partly // in another is not desirable. } //---------------------------------- // listData //---------------------------------- /** * @private * Storage for the listData property. */ private var _listData:BaseListData; [Bindable("dataChange")] [Inspectable(environment="none")] /** * When a component is used as a drop-in item renderer or drop-in * item editor, Flex initializes the listData property * of the component with the appropriate data from the List control. * The component can then use the listData property * to initialize the data property of the drop-in * item renderer or drop-in item editor. * *

You do not set this property in MXML or ActionScript; * Flex sets it when the component is used as a drop-in item renderer * or drop-in item editor.

* * @default null * @see mx.controls.listClasses.IDropInListItemRenderer * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get listData():BaseListData { return _listData; } /** * @private */ public function set listData(value:BaseListData):void { _listData = value; } //---------------------------------- // loaded //---------------------------------- /** * A flag which indicates whether the JavaScript load event * corresponding to the previous loading operation * has been delivered to the HTML DOM in this control. * *

This property is true * before the complete event is dispatched.

* *

It is possible that this property * never becomes true. * This happens in the same cases * in which the complete event is never dispatched.

* * @default false * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get loaded():Boolean { if (!htmlLoader || locationChanged || htmlTextChanged) return false; return htmlLoader.loaded; } //---------------------------------- // location //---------------------------------- /** * @private * Storage for the location property. */ private var _location:String; /** * @private */ private var locationChanged:Boolean = false; [Bindable("locationChange")] /** * The URL of an HTML page to be displayed by this control. * *

Setting this property has the side effect of setting * the htmlText property to null, * and vice versa.

* * @default "" * * @see #htmlText * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get location():String { return _location; } /** * @private */ public function set location(value:String):void { _location = value; locationChanged = true; // Setting both location and htmlText doesn't make sense, // so setting one sets the other to null, // and the last one set is applied in commitProperties(). _htmlText = null; htmlTextChanged = false; invalidateProperties(); invalidateSize(); invalidateDisplayList(); dispatchEvent(new Event("locationChange")); } //---------------------------------- // paintsDefaultBackground //---------------------------------- /** * @private * Storage for the paintsDefaultBackground property. */ private var _paintsDefaultBackground:Boolean; /** * @private */ private var paintsDefaultBackgroundChanged:Boolean = false; /** * Whether this control's HTML content * has a default opaque white background or not. * *

If this property is false, * then the background specified for this Flex control, if any, * appears behind the HTML content.

* *

However, if any HTML element has its own opaque background color * (specified by style="background-color:gray", for instance), * then that background appears behind that element.

* * @default false; * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get paintsDefaultBackground():Boolean { return _paintsDefaultBackground; } /** * @private */ public function set paintsDefaultBackground(value:Boolean):void { _paintsDefaultBackground = value; paintsDefaultBackgroundChanged = true; invalidateProperties(); } //---------------------------------- // runtimeApplicationDomain //---------------------------------- /** * @private * Storage for the runtimeApplicationDomain property. */ private var _runtimeApplicationDomain:ApplicationDomain; /** * @private */ private var runtimeApplicationDomainChanged:Boolean = false; /** * The ApplicationDomain to use for HTML's window.runtime * scripting. * *

If this property is null, or if it specifies * an ApplicationDomain from a different security domain * than the HTML content, the HTML page uses a default * ApplicationDomain for the page's domain.

* * @default null * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get runtimeApplicationDomain():ApplicationDomain { return _runtimeApplicationDomain; } /** * @private */ public function set runtimeApplicationDomain(value:ApplicationDomain):void { _runtimeApplicationDomain = value; runtimeApplicationDomainChanged = true; invalidateProperties(); } //---------------------------------- // userAgent //---------------------------------- /** * @private * Storage for the userAgent property. */ private var _userAgent:String; /** * @private */ private var userAgentChanged:Boolean = false; /** * The user agent string to be used in content requests * from this control. * *

You can set the default user agent string used by all * HTML controls in an application domain by setting the * static URLRequestDefaults.userAgent property. * If no value is set for the userAgent property * (or if the value is set to null), * the user agent string is set to the value of * URLRequestDefaults.userAgent.

* *

If neither the userAgent property * of this control nor for URLRequestDefaults.userAgent, * has a value set, a default value is used as the user agent string. * This default value varies depending on the runtime * operating system (such as Mac OS or Windows), * the runtime language, and the runtime version, * as in the following two examples:

* *
     *  "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) AdobeAIR/1.0"
     *  "Mozilla/5.0 (Windows; U; en) AppleWebKit/420+ (KHTML, like Gecko) AdobeAIR/1.0"
     *  
* * @default null * * @see flash.net.URLRequest#userAgent * @see flash.net.URLRequestDefaults#userAgent * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get userAgent():String { return _userAgent; } /** * @private */ public function set userAgent(value:String):void { _userAgent = value; userAgentChanged = true; invalidateProperties(); } //-------------------------------------------------------------------------- // // Overridden methods // //-------------------------------------------------------------------------- /** * @private */ override protected function createChildren():void { super.createChildren(); if (!htmlLoader) { htmlLoader = htmlLoaderFactory.newInstance(); htmlLoader.addEventListener( Event.HTML_DOM_INITIALIZE, htmlLoader_domInitialize); htmlLoader.addEventListener( Event.COMPLETE, htmlLoader_completeHandler); htmlLoader.addEventListener( Event.HTML_RENDER, htmlLoader_htmlRenderHandler); htmlLoader.addEventListener( Event.LOCATION_CHANGE, htmlLoader_locationChangeHandler); htmlLoader.addEventListener( Event.HTML_BOUNDS_CHANGE, htmlLoader_htmlBoundsChangeHandler); htmlLoader.addEventListener( Event.SCROLL, htmlLoader_scrollHandler); htmlLoader.addEventListener( HTMLUncaughtScriptExceptionEvent.UNCAUGHT_SCRIPT_EXCEPTION, htmlLoader_uncaughtScriptExceptionHandler); addChild(htmlLoader); } } /** * @private */ override protected function commitProperties():void { super.commitProperties(); // Change the properties of the HTMLLoader // before calling its load() or loadString() method. if (htmlHostChanged) { htmlLoader.htmlHost = _htmlHost; htmlHostChanged = false; } if (paintsDefaultBackgroundChanged) { htmlLoader.paintsDefaultBackground = _paintsDefaultBackground; paintsDefaultBackgroundChanged = false; } if (runtimeApplicationDomainChanged) { htmlLoader.runtimeApplicationDomain = _runtimeApplicationDomain; runtimeApplicationDomainChanged = false; } if (userAgentChanged) { htmlLoader.userAgent = _userAgent; userAgentChanged = false; } if (locationChanged) { htmlLoader.load(new URLRequest(_location)); locationChanged = false; } if (htmlTextChanged) { htmlLoader.loadString(_htmlText); htmlTextChanged = false; } } /** * @private */ override protected function measure():void { super.measure(); var em:EdgeMetrics = viewMetrics; em.left += getStyle("paddingLeft"); em.top += getStyle("paddingTop"); em.right += getStyle("paddingRight"); em.bottom += getStyle("paddingBottom"); measuredWidth = Math.min(htmlLoader.contentWidth + em.left + em.right, MAX_HTML_WIDTH); measuredHeight = Math.min(htmlLoader.contentHeight + em.top + em.bottom, MAX_HTML_HEIGHT); //trace("measure", htmlLoader.contentWidth, htmlLoader.contentHeight, measuredWidth, measuredHeight); } /** * @private */ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); var em:EdgeMetrics = viewMetrics; em.left += getStyle("paddingLeft"); em.top += getStyle("paddingTop"); em.right += getStyle("paddingRight"); em.bottom += getStyle("paddingBottom"); htmlLoader.x = em.left; htmlLoader.y = em.top; // The width and height of an HTMLLoader can't be 0. var w:Number = Math.max(unscaledWidth - em.left - em.right, 1); var h:Number = Math.max(unscaledHeight - em.top - em.bottom, 1); htmlLoader.width = w; htmlLoader.height = h; } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * Cancels any load operation in progress. * *

This method does nothing if it is called before this component's * internal HTMLLoader (the htmlLoader property) has been created.

* * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function cancelLoad():void { if (htmlLoader) htmlLoader.cancelLoad(); } /** * Returns the HTMLHistoryItem at the specified position * in this control's history list. * *

This method returns null if it is called before this * component's internal HTMLLoader (the htmlLoader property) has been created.

* * @param position The position in the history list. * * @return A HTMLHistoryItem object * for the history entry at the specified position. * * @see historyPosition * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function getHistoryAt(position:int):HTMLHistoryItem { if (!htmlLoader) return null; return htmlLoader.getHistoryAt(position); } /** * Navigates back in this control's history list, if possible. * *

Calling this method of the HTMLLoader object * has the same effect as calling the back() method * of the window.history property in JavaScript * in the HTML content.

* *

This method does nothing if it is called before this component's * internal HTMLLoader (the htmlLoader property) has been created.

* * @see #historyPosition * @see #historyForward() * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function historyBack():void { if (htmlLoader) htmlLoader.historyBack(); } /** * Navigates forward in this control's history list, if possible. * *

Calling this method of the HTMLLoader object * has the same effect as calling the forward() method * of the window.history property in JavaScript * in the HTML content.

* *

This function throws no errors.

* *

This method does nothing if it is called before this component's * internal HTMLLoader (the htmlLoader property) has been created.

* * @see #historyPosition * @see #historyBack() * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function historyForward():void { if (htmlLoader) htmlLoader.historyForward(); } /** * Navigates the specified number of steps in this control's history list. * *

This method navigates forward if the number of steps * is positive and backward if it is negative. * Navigation by zero steps is equivalent * to calling reload().

* *

This method is equivalent to calling the go() method * of the window.history property in JavaScript * in the HTML content.

* *

This method does nothing if it is called before this component's * internal HTMLLoader (the htmlLoader property) has been created.

* * @param steps The number of steps in the history list * to move forward (positive) or backward (negative). * * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function historyGo(steps:int):void { if (htmlLoader) htmlLoader.historyGo(steps); } /** * Reloads the HTML content from the current location. * *

This method does nothing if it is called before this component's * internal HTMLLoader (the htmlLoader property) has been created.

* * @langversion 3.0 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function reload():void { if (htmlLoader) htmlLoader.reload(); } /** * @private */ private function adjustScrollBars():void { setScrollBarProperties(htmlLoader.contentWidth, htmlLoader.width, htmlLoader.contentHeight, htmlLoader.height); // This is a temporary solution for adjusting the speed of scrolling // via scrollbar arrows. There isn't a lot of overhead here, but // we still shouldn't have to set these values every time // updateDisplayList() is called. if (verticalScrollBar) verticalScrollBar.lineScrollSize = 20; if (horizontalScrollBar) horizontalScrollBar.lineScrollSize = 20; } //-------------------------------------------------------------------------- // // Overridden event handlers: ScrollControlBase // //-------------------------------------------------------------------------- /** * @private * Gets called by internal field so we draw a focus rect around us. */ override protected function focusInHandler(event:FocusEvent):void { super.focusInHandler(event); if (_imeMode != null && (htmlLoader is IIMESupport && IIMESupport(htmlLoader).enableIME)) { // When IME.conversionMode is unknown it cannot be // set to anything other than unknown(English) try { if (!errorCaught && IME.conversionMode != IMEConversionMode.UNKNOWN) { IME.conversionMode = _imeMode; } errorCaught = false; } catch(e:Error) { // Once an error is thrown, focusIn is called // again after the Alert is closed, throw error // only the first time. errorCaught = true; var message:String = resourceManager.getString( "controls", "unsupportedMode", [ _imeMode ]); throw new Error(message); } } } /** * @private */ override protected function scrollHandler(event:Event):void { super.scrollHandler(event); htmlLoader.scrollH = horizontalScrollPosition; htmlLoader.scrollV = verticalScrollPosition; } /** * @private */ override protected function mouseWheelHandler(event:MouseEvent):void { // Ignore mouseWheel events that are bubbling up // from the HTMLLoader; they have already been handled there. if (event.target != this) return; // Magnify the scrolling to approximate what browsers do. event.delta *= 6; super.mouseWheelHandler(event); } //-------------------------------------------------------------------------- // // Event handlers // //-------------------------------------------------------------------------- /** * @private */ private function htmlLoader_domInitialize(event:Event):void { dispatchEvent(event); } /** * @private */ private function htmlLoader_completeHandler(event:Event):void { invalidateSize(); dispatchEvent(event); } /** * @private */ private function htmlLoader_htmlRenderHandler(event:Event):void { dispatchEvent(event); adjustScrollBars(); // we record this property here becuase it seems to // change as you interact with the content hasFocusableChildren = htmlLoader.hasFocusableContent; } /** * @private */ private function htmlLoader_locationChangeHandler(event:Event):void { var change:Boolean = _location != htmlLoader.location; _location = htmlLoader.location; if (change) dispatchEvent(event); } /** * @private */ private function htmlLoader_htmlBoundsChangeHandler(event:Event):void { invalidateSize(); adjustScrollBars(); } /** * @private */ private function htmlLoader_scrollHandler(event:Event):void { horizontalScrollPosition = htmlLoader.scrollH; verticalScrollPosition = htmlLoader.scrollV; } /** * @private */ private function htmlLoader_uncaughtScriptExceptionHandler( event:HTMLUncaughtScriptExceptionEvent):void { var clonedEvent:Event = event.clone(); dispatchEvent(clonedEvent); if (clonedEvent.isDefaultPrevented()) event.preventDefault(); } } }