////////////////////////////////////////////////////////////////////////////////
//
// 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
.
location
or htmlText
property.
*
* When this event is dispatched,
* no JavaScript methods have yet executed.
* The domWindow
and 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.
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
.
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
.
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.
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 constant | *Meaning | *
---|---|
STATUS_OK |
* A 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
* |
*
ERROR_INSTALLED_READER_NOT_FOUND |
* No version of Acrobat Reader is detected. * An HTML object cannot display PDF content. | *
ERROR_INSTALLED_READER_TOO_OLD |
* Acrobat Reader has been detected, but the version is too old. * An HTML object cannot display PDF content. | *
ERROR_PREFERED_READER_TOO_OLD |
* A 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. | *
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 thewindow.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.
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 thewindow.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.
window
object
* for the root frame of the HTML DOM inside this control.
*
* This property is null
until the
* htmlDOMInitialize
event has been dispatched.
The flash.system.IMEConversionMode class defines constants for the
* valid values for this property.
* You can also specify null
to specify no IME.
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 JavaScriptload
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.
Setting this property has the side effect of setting
* the htmlText
property to null
,
* and vice versa.
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'swindow.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.
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.
This method returns null
if it is called before this
* component's internal HTMLLoader (the htmlLoader
property) has been created.
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.
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.
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.
location
.
*
* This method does nothing if it is called before this component's
* internal HTMLLoader (the htmlLoader
property) has been created.