Menu

StageText

SourceForge Editorial Staff

StageText - Functional and Design Specification


\

Glossary

Native text input field - A text input field provided and drawn by the underlying operating system or by a component library that is bundled with the operating system.

Soft-keyboard - A virtual keyboard input device used on mobile devices which do not have hardware keys or where the use of hardware keys is impractical. Soft-keyboards are usually displayed on touchscreens and can display custom or special-purpose keys that do not exist on hardware keyboards.

Soft-keyboard hint - A property which may be used to control some aspects of soft-keyboard behavior or appearance. If no soft-keyboard is present or the soft-keyboard doesn't support the property, the hint is ignored.

\

Summary and Background

The purpose of StageText is to allow applications to use native text controls for editing and presentation of text in mobile applications. With StageText components, applications' text fields will keep a platform look and feel when those platforms' text controls are revised, will avoid reflow and other rendering issues that stem from emulated text controls, and will be able to leverage platform-provided soft-keyboard and text manipulation enhancements.

\

Usage Scenarios

The use of StageText should be transparent. The SDK will provide skins of TextInput and TextArea that use StageText in their implementations. These skins will result in the use of native text controls for editing and presentation of text in mobile applications. Application developers should continue to use TextInput and TextArea as before.

\

Detailed Description

StageText is a component provided by the runtime that wraps either a native text input field or a TextField in cases where a native text input field is unavailable or not desirable. The native text input field is necessary because, on some platforms, the TextField class does not provide an adequate reproduction of the platform's text entry experience. Native text fields on these platforms provide correct visuals, text spacing and reflow, selection behavior, and text entry assistance that are either incorrect in or missing from TextField.

To use StageText, the SDK will provide new default skins for the TextInput and TextArea components when the mobile theme is in use. These new skins will interface with StageText through a wrapper object which implements IEditableText much like the StyleableTextField object does today.

TextInput and TextArea will have new properties for soft keyboard hints added to them. The softKeyboardType hint may be used by the native text implementation to display different keyboard types (numeric, punctuation, e-mail address-specific, etc.) for text entry. The returnKeyLabel hint may be used to display a different label or symbol on the soft keyboard's return key. The autoCaptialize hint may be used by the native text entry system to change how entered text is capitalized by default. All of these properties are hints which may be ignored by the underlying text field's implementation when they don't apply (e.g. when a hardware keyboard is in use).

In the near-term, StageText will not support an event model necessary to allow for touch-based scrolling of forms containing native text fields. This limitation was already in place for applications running under iOS in the previous release. This release will extend that limitation to apply to all platforms. In order to allow for such a scrolling form workflow, StageText would need to allow the outer form to override the native control's behavior for scroll gestures and would also need to forward changes in the native control's size and carat position to the containing object. Due to time constraints, that infrastructure will not be available for this release. To allow application developers to continue to build scrollable forms, the existing TextField-based skins for TextInput and TextArea will remain unchanged.

Because StageText uses native text controls to render and edit text, the skins that use StageText will not support the use of embedded fonts.

\

API Description

package spark.components.supportClasses
{
    /**

     * Controls the visibility of prompt text for this component when it is
     * empty and focused.
     *
     * The default value for the Mobile theme is <code>true</code>.
     */
    <a href="Style%28name%3D%26quot%3BshowPromptWhenFocused%26quot%3B%2C%20type%3D%26quot%3BBoolean%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%2C%20theme%3D%26quot%3Bmobile%26quot%3B%29">Style(name="showPromptWhenFocused", type="Boolean", inherit="yes", theme="mobile")</a>

    class SkinnableTextBase
    {
        /**

         *  Hint indicating what captialization behavior soft keyboards should
         *  use.
         *
         *  Supported values are defined in flash.text.AutoCapitalize:
         *      "none" - no automatic capitalization
         *      "word" - capitalize the first letter following any space or
         *          punctuation
         *      "sentence" - captitalize the first letter following any period
         *      "all" - capitalize every letter
         *
         *  <p><b>For the Desktop theme, this is not supported.</b></p>
         */
        public function get autoCapitalize():String;
        public function set autoCaptialize(value:String):void;

        /**

         *  Hint indicating what label should be displayed for the return key on
         *  soft keyboards.
         *
         *  Supported values are defined in flash.text.ReturnKeyLabel:
         *      "default" - default icon or label text
         *      "done" - icon or label text indicating completed text entry
         *      "go" - icon or label text indicating that an action should start
         *      "next" - icon or label text indicating a move to the next field
         *      "search" - icon or label text indicating that the entered text
         *          should be searched for
         *
         *  <p><b>For the Desktop theme, this is not supported.</b></p>
         */
        public function get returnKeyLabel():String;
        public function set returnKeyLabel(value:String):void;

        /**

         *  Hint indicating what kind of soft keyboard should be displayed for
         *  this component.
         *
         *  Supported values are defined in flash.text.SoftKeyboardType:
         *      "default" - the default keyboard
         *      "punctuation" - puts the keyboard into punctuation/symbol entry
         *          mode
         *      "url" - present soft keys appropriate for URL entry, such as a
         *          specialized key that inserts '.com'
         *      "number" - puts the keyboard into numeric keypad mode
         *      "contact" - puts the keyboard into a mode appropriate for
         *          entering contact information
         *      "email" - puts the keyboard into e-mail addres entry mode, which
         *          may make it easier to enter '@' or '.com'
         *
         *  <p><b>For the Desktop theme, this is not supported.</b></p>
         */
        public function get softKeyboardType():String;
        public function set softKeyboardType(value:String):void;

        /**

         *  Hint indicating whether a soft keyboard should use its auto-correct
         *  behavior, if supported.
         *  <p><b>For the Desktop theme, this is not supported.</b></p>
         */
        public function get autoCorrect():Boolean;
        public function set autoCorrect(value:Boolean):void;
    }
}



package spark.components.supportClasses
{
    /**

     *  Dispatched after a user editing operation is complete.
     *
     *  @eventType flash.events.Event.CHANGE
     */
    <a href="Event%28name%3D%26quot%3Bchange%26quot%3B%2C%20type%3D%26quot%3Bflash.events.Event%26quot%3B%29">Event(name="change", type="flash.events.Event")</a>

    /**

     *  Dispatched after the native text control gains focus. This happens when
     *  a user highlights the text field with a pointing device, keyboard
     *  navigation, or a touch gesture.
     *
     *  <p>Note: Since <code>flash.text.StageText</code> is not an
     *  <code>InteractiveObject</code>, the <code>Stage.focus</code> property
     *  may not be used to determine if a native text field has focus.</p>
     *
     *  @eventType flash.events.FocusEvent.FOCUS_IN
     */
    <a href="Event%28name%3D%26quot%3BfocusIn%26quot%3B%2C%20type%3D%26quot%3Bflash.events.FocusEvent%26quot%3B%29">Event(name="focusIn", type="flash.events.FocusEvent")</a>

    /**

     *  Dispatched after the native text control loses focus. This happens when
     *  a user highlights an object other than the text field with a pointing
     *  device, keyboard navigation, or a touch gesture.
     *
     *  <p>Note: Since <code>flash.text.StageText</code> is not an
     *  <code>InteractiveObject</code>, the <code>Stage.focus</code> property
     *  may not be used to determine if a native text field has focus.</p>
     *
     *  @eventType flash.events.FocusEvent.FOCUS_OUT
     */
    <a href="Event%28name%3D%26quot%3BfocusOut%26quot%3B%2C%20type%3D%26quot%3Bflash.events.FocusEvent%26quot%3B%29">Event(name="focusOut", type="flash.events.FocusEvent")</a>

    /**

     *  Dispatched when a user presses a key. Mappings between keys and specific
     *  characters vary by device and operating system. Not dispatched for all
     *  keys. Keys dispatched vary by platform.
     *
     *  <p>Note: Since <code>flash.text.StageText</code> only dispatches raw
     *  keyboard events for a very limited subset of keys, this event is only
     *  dispatched for the same limited subset. This includes the enter key, and
     *  the back and menu hard keys on Android platforms.</p>
     *
     *  @eventType flash.events.KeyboardEvent.KEY_DOWN
     */
    <a href="Event%28name%3D%26quot%3BkeyDown%26quot%3B%2C%20type%3D%26quot%3Bflash.events.KeyboardEvent%26quot%3B%29">Event(name="keyDown", type="flash.events.KeyboardEvent")</a>

    /**

     *  Dispatched when a user releases a key. Mappings between keys and
     *  specific characters vary by device and operating system. Not dispatched
     *  for all keys. Keys dispatched vary by platform.
     *
     *  <p>Note: Since <code>flash.text.StageText</code> only dispatches raw
     *  keyboard events for a very limited subset of keys, this event is only
     *  dispatched for the same limited subset. This includes the enter key, and
     *  the back and menu hard keys on Android platforms.</p>
     *
     *  @eventType flash.events.KeyboardEvent.KEY_DOWN
     */
    <a href="Event%28name%3D%26quot%3BkeyUp%26quot%3B%2C%20type%3D%26quot%3Bflash.events.KeyboardEvent%26quot%3B%29">Event(name="keyUp", type="flash.events.KeyboardEvent")</a>

    /**

     *  Dispatched immediately before a soft keyboard is displayed. If canceled
     *  by calling <code>preventDefault</code>, the soft keyboard will not open.
     *
     *  @eventType flash.events.SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING
     */
    <a href="Event%28name%3D%26quot%3BsoftKeyboardActivating%26quot%3B%2C%20type%3D%26quot%3Bflash.events.SoftKeyboardEvent%26quot%3B%29">Event(name="softKeyboardActivating", type="flash.events.SoftKeyboardEvent")</a>

    /**

     *  Dispatched when a soft keyboard is displayed.
     *
     *  @eventType flash.events.SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE
     */
    <a href="Event%28name%3D%26quot%3BsoftKeyboardActivate%26quot%3B%2C%20type%3D%26quot%3Bflash.events.SoftKeyboardEvent%26quot%3B%29">Event(name="softKeyboardActivate", type="flash.events.SoftKeyboardEvent")</a>

    /**

     *  Dispatched when a soft keyboard is lowered or hidden.
     *
     *  @eventType flash.events.SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE
     */
    <a href="Event%28name%3D%26quot%3BsoftKeyboardDeactivate%26quot%3B%2C%20type%3D%26quot%3Bflash.events.SoftKeyboardEvent%26quot%3B%29">Event(name="softKeyboardDeactivate", type="flash.events.SoftKeyboardEvent")</a>

    /**

     * Color of text in the component, including the component label.
     *
     * The default value for the Mobile theme is <code>0xFFFFFF</code>.
     */
    <a href="Style%28name%3D%26quot%3Bcolor%26quot%3B%2C%20type%3D%26quot%3Buint%26quot%3B%2C%20format%3D%26quot%3BColor%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%29">Style(name="color", type="uint", format="Color", inherit="yes")</a>

    /**

     * Name of the font to use.
     * Unlike in a full CSS implementation, comma-separated lists are not
     * supported. You can use any font family name. If you specify a generic
     * font name, it is converted to an appropriate device font.
     *
     * The default font for the Mobile theme is <code>"_sans"</code>.
     */
    <a href="Style%28name%3D%26quot%3BfontFamily%26quot%3B%2C%20type%3D%26quot%3BString%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%29">Style(name="fontFamily", type="String", inherit="yes")</a>

    /**

     * Height of the text, in pixels.
     *
     * The default value for the Mobile theme is 24.
     */
    <a href="Style%28name%3D%26quot%3BfontSize%26quot%3B%2C%20type%3D%26quot%3BNumber%26quot%3B%2C%20format%3D%26quot%3BLength%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%29">Style(name="fontSize", type="Number", format="Length", inherit="yes")</a>

    /**

     * Determines whether the text is italic font.
     * Recognized values are "normal" and "italic".
     *
     * @default "normal"
     */
    <a href="Style%28name%3D%26quot%3BfontStyle%26quot%3B%2C%20type%3D%26quot%3BString%26quot%3B%2C%20enumeration%3D%26quot%3Bnormal%2Citalic%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%29">Style(name="fontStyle", type="String", enumeration="normal,italic", inherit="yes")</a>

    /**

     * Determines whether the text is boldface.
     * Recognized values are "normal" and "bold".
     *
     * @default "normal"
     */
    <a href="Style%28name%3D%26quot%3BfontWeight%26quot%3B%2C%20type%3D%26quot%3BString%26quot%3B%2C%20enumeration%3D%26quot%3Bnormal%2Cbold%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%29">Style(name="fontWeight", type="String", enumeration="normal,bold", inherit="yes")</a>

    /**

     * Alignment of text within a container.
     * Possible values are "left", "right", or "center".
     *
     * @default "left"
     */
    <a href="Style%28name%3D%26quot%3BtextAlign%26quot%3B%2C%20type%3D%26quot%3BString%26quot%3B%2C%20enumeration%3D%26quot%3Bleft%2Ccenter%2Cright%26quot%3B%2C%20inherit%3D%26quot%3Byes%26quot%3B%29">Style(name="textAlign", type="String", enumeration="left,center,right", inherit="yes")</a>

    class StyleableStageText extends UIComponent implements IEditableText
    {
        /**

         *  Construct a StyleableStageText component.
         *
         *  @param multiline Whether the stage text should support multiline
         *  text.
         */
        public function StyleableStageText(multiline:Boolean = false);

        /**

         *  Specifies whether the text field is a password text field.
         *
         *  @default false
         */
        public function get displayAsPassword():Boolean;
        public function set displayAsPassword(value:Boolean):void;

        /**

         *  A flag indicating whether the user is allowed to edit the text in
         *  this component.
         *
         *  @default true
         */
        public function get editable():Boolean;
        public function set editable(value:Boolean):void;

        /**

         *  A flag indicating whether the component is enabled.
         *
         *  @default true
         */
        public function get enabled():Boolean;
        public function set enabled(value:Boolean):void;

        /**

         *  Describes how lines are broken within wrapping text. StageText only
         *  supports LineBreak.TO_FIT.
         */
        public function get lineBreak():String;
        public function set lineBreak(value:String):void;

        /**

         *  The capacity of this text field in characters.
         */
        public function get maxChars():int;
        public function set maxChars(value:int):void;

        /**

         *  A flag indicating whether this component supports multiline text.
         * The multiline value determines whether the enter key creates a new
         * line (with a value of false, the enter key does not create a new
         * line). If you paste text into a field with a multiline value of
         * false, newlines are stripped out of the text.
         */
        public function get multiline():Boolean;

        /**

         *  The set of characters that the user may enter into this field.
         */
        public function get restrict():String;
        public function set restrict(value:String):void;

        /**

         *  A flag indicating whether text is selectable. This is always true.
         */
        public function get selectable():Boolean;
        public function set selectable(value:Boolean):void;

        /**

         *  The character position specifying the end of the selection that
         *  moves when the selection is extended with the arrow keys.
         */
        public function get selectionActivePosition():int;

        /**

         *  The character position specifying the end of the selection that
         *  stays fixed when the selection is extended with the arrow keys.
         */
        public function get selectionAnchorPosition():int;

        /**

         *  Inserts the specified text as if the user had typed it.
         *  If a range was selected, the new text replaces the selected text.
         *  If there was an insertion point, the new text is inserted there.
         *  An insertion point is then set after the new text.
         *  If necessary, the text will scroll to ensure that the insertion
         *  point is visible.
         */
        public function insertText(text:String):void;

        /**

         *  Appends the specified text to the end of the component as if the
         *  user had clicked at the end and typed.
         */
        public function appendText(text:String):void;

        /**

         *  Selects the specified text range.
         */
        public function selectRange(anchorIndex:int, activeIndex:int):void;

        /**

         *  Selects all the text in the component.
         */
        public function selectAll():void;

        /**

         *  The text displayed in this component.
         */
        public function get text():String;
        public function set text(value:String):void;

        /**

         *  A flag indicating whether text in the component is truncated.
         */
        public function get isTruncated():Boolean;

        /**

         *  The source of this object's style values.
         *  The value of the styleName property can be one of three types:
         *
         *    String, such as "headerStyle". The String names a class selector
         *    that is defined in a CSS style sheet.
         *
         *    CSSStyleDeclaration, such as
         *    StyleManager.getStyleDeclaration(".headerStyle").
         *
         *    UIComponent. The object that implements this interface inherits
         *    all the style values from the referenced UIComponent.
         */
        public function get styleName():Object
        public function set styleName(value:Object):void

        /**

         *  Called when the value of a style property is changed.
         */
        public function styleChanged(styleProp:String):void;

        /**

         *  The StageText runtime object that this field uses.
         *
         *  This class needs a StageText member instead of extending StageText
         *  because the StageText class is final.
         */
        private var stageText:flash.text.StageText;
    }
}



package spark.skins.mobile.supportClasses
{
    class StageTextSkinBase extends MobileSkin
    {
        /**

         *  Defines the border.
         */
        protected var borderClass:Class;

        /**

         *  Defines the corner radius.
         */
        protected var layoutCornerEllipseSize:uint;

        /**

         *  Defines the border's thickness.
         */
        protected var layoutBorderSize:uint;

        /**

         *  textDisplay skin part.
         */
        public var textDisplay:StyleableStageText;

        <a href="Bindable">Bindable</a>
        /**

         *  Bindable promptDisplay skin part. Bindings fire when promptDisplay
         *  is removed and added for proper updating by the SkinnableTextBase.
         */
        public var promptDisplay:IDisplayText;
    }
}



package spark.skins.mobile
{
    class StageTextInputSkin extends StageTextSkinBase
    {
        /**

         *  A strongly typed property that references the component to which
         *  this skin is applied.
         */
        public var hostComponent:TextInput;
    }
}



package spark.skins.mobile
{
    class StageTextAreaSkin extends StageTextSkinBase
    {
        /**

         *  A strongly typed property that references the component to which
         *  this skin is applied.
         */
        public var hostComponent:TextArea;
    }
}

Classes involved with StageText relate to each other as follows:

  SkinnableTextBase                   StageTextSkinBase
    |           |                       |           |
TextInput    TextArea        StageTextInputSkin  StageTextAreaSkin

StageTextInputSkin =====skins====> TextInput

StageTextAreaSkin =====skins====> TextArea

StageTextSkinBase =====contains====> StyleableStageText =====contains====> StageText

\

B Features

None

\

Examples and Usage

To change the automatic capitalization behavior of soft keyboards which support such behaviors, set autoCapitalize to one of the constants defined in the AutoCapitalize class. The keys available on soft keyboards and the label of the return key on keyboards which support changing them may be set using the softKeyboardType and returnKeyLabel properties, respectively. Constants for those properties are defined in the SoftKeyboardType and ReturnKeyLabel classes:

import flash.text.AutoCapitalize;
import flash.text.ReturnKeyLabel;
import flash.text.SoftKeyboardType;

private function setupMySoftKeyboard():void
{
    // Set the capitalization hint to capitalize nothing.
    myTextInput.autoCapitalize = AutoCapitalize.NONE;

    // Set the soft keyboard type to one appropriate for entering e-mail
    // addresses. On platforms which support it, such a keyboard may include
    // dedicated '@' and '.com' soft keys.
    myTextInput.softKeyboardType = SoftKeyboardType.EMAIL;

    // Set the soft keyboard to display a "next" label on its return key.
    myTextInput.returnKeyLabel = ReturnKeyLabel.NEXT;
}



<s:VGroup paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10" gap="10">
    <s:TextInput width="100%" id="toAddress"
        softKeyboardType="email"
        autoCorrect="false"
        returnKeyLabel="next"/>

    <s:TextInput width="100%" id="Subject"
        autoCapitalize="word"
        autoCorrect="true"
        returnKeyLabel="next"/>

    <s:TextArea width="100%" height="100%" id="bodyText"
        autoCapitalize="sentence"
        autoCorrect="true"/>
</s:VGroup>

Skins using StageText will not work in scrolling form workflows. To apply the old default skin which does not use StageText, set the skinClass style in CSS:

s|TextInput {
    skinClass: ClassReference("spark.skins.mobile.TextInputSkin");
}

s|TextArea {
    skinClass: ClassReference("spark.skins.mobile.TextAreaSkin");
}

\

Additional Implementation Details

Enter implementation/design details for the feature here. This section may be updated after the spec signs off.

\

Compiler Work

None

\

Cross-Form-Factor Considerations

The primary purpose of StageText is to allow for better text entry and manipulation experiences on mobile devices. The affected components, however, run on all form-factors.

When run on Windows or Mac OS desktop platforms, StageText behaves as a wrapper around TextField. This way, TextInput and TextArea running with the default skins will behave normally on desktop platforms.

The new, soft-keyboard-specific properties for these components are only hints. In a desktop environment and in mobile environments with only hardware keyboards, these hints are ignored. Similarly, if a soft-keyboard is present but does not support a feature represented by the hint, the hint is ignored.

\

Cross-Platform Considerations

StageText uses the platform's native text field on Andriod and iOS platforms. On other platforms, including desktop Windows and Mac OS, StageText is a thin wrapper around TextField. Because of this, Android and iOS applications may require additional testing focusing on native text field behaviors.

\

Backwards Compatibility

Syntax changes

None.

Behavior

In prior releases, TextInput and TextArea were usable in scrolling form workflows in Android applications. StageText, however, does not support the necessary events to allow this workflow at this time. To work around this, developers may use the old TextInputSkin and TextAreaSkin classes instead of the new default StageText-based skin classes.

Scrolling form workflows did not work in prior releases on iOS, so there are no significant changes in this case.

The new default skins for TextInput and TextArea cannot be used with embedded fonts. StageText uses a native text control both for text display and text entry. These native controls cannot use embedded fonts directly. Other text controls that use FTE or TLF for text rendering may be used as workarounds if embedded font support is a requirement.

StageText does not support fractional alpha values. So, they will likely not look as intended when placed inside semi-transparent containers.

Native text input fields cannot be clipped by other Flex content and are rendered in a layer above the Stage. Because of this limitation, components that use StageText-based skin classes will always appear to be on top of other Flex components. If a Callout or other SkinnablePopUpContainer is shown, Flex will automatically replace the StageText portions of components in layers under the pop-up with bitmaps captured from the StageText. If the owner property of the pop-up is set to a component hosting a StageText, that StageText will not be replaced by a bitmap. These bitmaps will not be interactive, even if the pop-up is non-modal. The only StageText-based components that will remain interactive will be components inside the active pop-up and the owner of the active pop-up. If the pop-up overlaps its owner, the native text in the owner will appear above the pop-up. Developers may use the old TextInputSkin and TextAreaSkin classes if they wish to maintain text interactivity in components on layers under the active pop-up.

StageText is currently not capable of measuring text. Because of this, any functionality which requires determining the dimensions of text is not supported when using StageText-based skins. This includes setting the dimensions of controls using numbers of lines or omitting dimensions to make a text control automatically resize. When using StageText-based skins, TextInput and TextArea must be given explicit, percent-based, or constraint-based dimensions. Also, because of this limitation, components using StageText-based skins will not return true for isTruncated.

The native text controls used by StageText apply different paddings around text. In order to avoid vertical scrolling in TextInput, StageText-based skins attempt to estimate this padding and compensate for that. Because of this and other differences in how native text controls treat text, the default height of TextInput using StageText-based skins will differ from its default height using the old TextInputSkin.

StageText does not support links or html markup. Only plain text is supported.

Text in StageText is always selectable.

StageText does not support programmatic control of scroll position at this time. Getters and setters for horizontalScrollPosition and verticalScrollPosition and the scrollToRange function defined in the IEditableText interface are implemented as no-ops in StyleableStageText.

StageText does not dispatch low-level keyboard events for most keys. Most notably, the tab key will not dispatch keyDown or keyUp events. As a consequence, focus cannot be removed from a component using StageText with the tab key.

Warnings/Deprecation

None.

\

Accessibility

None.

\

Performance

None.

\

Globalization

On Andriod and iOS platforms, StageText uses a platform control which should be capable of supporting any character sets, input methods, and locale settings that the platform is capable of. On other platforms, it wraps TextField and inherits all of TextField's globalization capabilities and limitations.

TextField does not support bidirectional text and, by extension, StageText and the skins which use it will not support bidirectional text either.

\

Localization

None.

\

Issues and Recommendations

None.


Related

Wiki: Flex 4.6

MongoDB Logo MongoDB