////////////////////////////////////////////////////////////////////////////////
//
// 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 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.
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.