Adding Interactions

From Frontal Wiki

Jump to: navigation, search

In Frontal, we call a script that responds to an event, either generated by a user action or by a system operation, an "interaction". So far we've seen several examples of interactions, including calling a "script" when a user clicks or rolls over an element in the document. In this section, we'll take a more thorough look at what's going on and what's possible with interactions.

We define interactions with attributes. For example, to add an "onClick" interaction to a div element, we would add an attribute named "onClick" along with a value for the script we'd like to run when we click it:

<style><![CDATA[
    div
        {
            style-tween-ease: fl.transitions.easing.Regular.easeOut;
            style-tween-duration: 6;
            style-tween-use-secs: false;
            left: 0px;
            top: 0px;
            width: 40px;
            height: 40px;
            background-color: mediumseagreen;
        }
]]></style>
<div onClick="prepStyleTween ( ); sS ( 'left', 300 * Math.random ( ) ); sS ( 'top', 300 * Math.random ( ) ); tweenStyles ( );" />

Here we've added an "onClick" interaction that sets a style tween to a new position. (For more on style tweens, see the Advanced Topics section.) This can be hard to read even with such a simple script, so typically, rather than defining an interaction directly on an element, we put it in a style sheet. The one exception to this is the "onConstruct" interaction, which is run when the DocumentElement object for an element is created. This occurs before any style sheets are applied, and so this interaction must be defined directly on the element.

Contents

Interaction Scope and Pre-Defined Variables

Note that whenever an interaction is run, it's run in the context of the object that it's applied to. So in our example, we're able to call the set style method "sS" and have it apply to the div object that was clicked.

And when an interaction is run, depending on what triggered it and what the interaction is, there will be certain pre-defined variables. For example, for user interactions like onClick, there's a variable named "event" available. This is the original Flash MouseEvent that ultimately triggered the interaction.

User Interactions

User interactions result from a user's actions. Here's the complete list of user interactions:

  • onClick
  • onDoubleClick (Be sure that the "double-click-enabled" style is set to "true" on the target element for this to work.)
  • onFocusIn
  • onFocusOut
  • onKeyDown
  • onKeyFocusChange
  • onKeyUp
  • onMouseDown
  • onMouseFocusChange
  • onMouseMove
  • onMouseOut
  • onMouseOver
  • onMouseUp
  • onMouseWheel
  • onMouseRollOut
  • onMouseRollOver
  • onMouseUpAnywhere
  • onMouseUpOutside

All but "onMouseUpAnywhere" and "onMouseUpOutside" are directly correlated to an event in Flash, and so please refer to Flash documentation for complete details. This interaction is a special addition to handle a common case: after getting an onMouseDown interaction on an element, you'd like to know when the mouse button is released. With onMouseUp, the interaction is only called if the mouse button is released while over the particular element. With onMouseUpAnywhere, the interaction is fired whenever the mouse button is released. Note that this interaction is only called after the mouse down event occurs on the element. This is best understood with an example.

In the previous example, first note that if you press down on the green square, then drag the mouse off and release the button, nothing happens. Now change "onClick" to "onMouseUpAnywhere" and run it in the Workspace. If you first press the mouse button while you're off the green square, you'll see that nothing happens. But if you first press down on the green square, then it moves regardless of whether or not you release the mouse button while still over the green square. ("onMouseUpOutside" is like "onMouseUpAnywhere" except that it'll only be called if the mouse is released outside of the green square.)

Propagating Interactions

The way Flash events work, a single event like a mouse click may have many listeners associated with it. Flash will then pass this event from listener to listener for processing until there are no more listeners, or until one of the listeners directs Flash to stop propagating the event. By default, this is the way interactions work; they tell Flash to stop propagating an event once they've processed it. We can see this in action in this example.

Here there are two divs, each with an onClick interaction that will change their respective div's background color. When we click them though, only the parent div changes color. This is because the event is passed down through Flash's DisplayObject list and gets to the parent div first. It runs it's interaction and then stops the event's propagation, which means the child div never receives it. Go ahead and try it.

<style><![CDATA[
    div
        {
            width: 25%;
            height: 50%;
            margin: auto;
            @onClick { sS ( "background-color", gA ( "clickColor" ) ); }
        }
]]></style>
<div clickColor="red" style="background-color: blue;">
    <div clickColor="green" style="background-color: yellow;" />
</div>

The idea behind this default behavior is to simulate a simple button when an interaction is applied to an element. This is in keeping with what you'd expect if you have a Flash AS2 background. You may notice that, for example, the mouse becomes a hand cursor when rolled over the divs. Internally, Frontal is setting the Flash movie's buttonMode and tabEnabled properties to true, and its mouseChildren property to false.

To change this behavior, we use the "raw" variant of the interaction. To get this variant, we simply add the word "Raw" to the end of the user interaction's name. So in the example above, change "onClick" in the style sheet to "onClickRaw." Now when we click the divs, both receive the event and both change their background colors.

Note that with the change to onClickRaw, we lost the button-like behavior on our divs. For example, the hand cursor went away. We can re-enable this if we like with the styles "button-mode" and "tab-enabled".

System Interactions

System interactions are triggered by events not necessarily directly related to a user action. These are:

  • onConstruct: Called when a DocumentElement object is created.
  • onDestroy: Called when destroy ( ) is called on a DocumentElement object.

Using the "wants-reset" style, we can make a DocumentElement resettable. A resettable DocumentElement is typically one that can be visited several times or never, and would like to know when this occurs. For example, an animated slide in a slide show would like to know when it's being visited so that it can restart its animation. If it uses external images, then it'd want to know this so that it could request that these images be moved to the top of the load queue. These interactions, then, are part of the framework for handling these events:

  • onInitialReset: Called the first time this DocumentElement is reset.
  • onReset: Called each time the DocumentElement is reset including the first time.

Visual Element Interactions

The following are called during the render process of a visual DocumentElement. For more details about the render process see the Advanced Topics section. A point to keep in mind is that the render process is run iteratively as needed throughout the life of the element.

  • onApplyStyles: Called after styles have been applied (or reapplied) to a DocumentElement.
  • onCustomRender: A visual DocumentElement has a custom rendering phase to do things like render text, images and videos. This interaction is called at the beginning of that phase.
  • onRenderBackground: This interaction is called twice -- before the background, as defined by the visual element's styles, has been rendered, and then after. The difference is determined by the predefined variable "state" which is either set to "beforeRender" or "afterRender". Returning false from the interaction when state is "beforeRender" causes the DocumentElement to not have its standard background rendered.
  • onRender: Called when the render process has completed.
  • onFirstRender: It's often convenient to do some initialization on a DocumentElement at a point after the style sheets have been applied. This interaction is useful for that case. It gets called when the first render process on the element completes, and just before the onRender interaction is called.

The onEnterFrame interaction is called on every frame, and so could affect performance if many are active. It's often the case in the Frontal cookbook that you'll see this interaction added and removed dynamically as needed. The following would add the interaction to a DocumentElement indexed by "index:"

gE ( index ).applyInteraction ( FrontalEvent.ENTER_FRAME, gE ( index ).movie );

Applying it to the current DocumentElement, it'd simply be:

applyInteraction ( FrontalEvent.ENTER_FRAME, movie );

To remove an interaction, we'd do this (and we could likewise simplify it for the current object):

gE ( index ).removeInteraction ( flash.events.MouseEvent.MOUSE_MOVE, gE ( index ).movie );
  • onTabChildrenChange: Called when the Flash event Event.TAB_CHILDREN_CHANGE is received on the DocumentElement's movie.
  • onTabEnabledChange: Called when the Flash event Event.TAB_ENABLED_CHANGE is received on the DocumentElement's movie.
  • onTabIndexChange: Called when the Flash event Event.TAB_INDEX_CHANGE is received on the DocumentElement's movie.
  • onEnterFrame: Called every frame.
  • onAddedToStage: Called when the DocumentElement's movie is attached to the Flash Stage.
  • onRemovedFromStage: Called when the DocumentElement's movie is removed from the Flash Stage.

Manager and Transitioner Interactions

When a visual element is being managed by a "manager" element, there's the notion of it being selected or deselected. There are also transitions that occur as the manager changes the selection of an element. (For more information, see Advanced Topics section.) The following interactions relate to such DocumentElements:

  • onSelect: Called on the next DocumentElement as soon as the 'manager' tag initiates the change of selection.
  • onDeselect: Called on the current DocumentElement as soon as the 'manager' tag initiates the change of selection.
  • onSelectTransitionEnd: Called on the next DocumentElement after the transition to it has completed.
  • onDeselectTransitionEnd: Called on the current DocumentElement after the transition away from it has completed.
  • onWillSelect: Called on a DocumentElement if it's requested while a transition is in progress. This doesn't necessarily mean that the DocumentElement will be selected, because before the transition ends, another DocumentElement may be requested.

When an element is set to be a marker via the "is-marker" style, then it's associated with a "manager" element. (See the section on the 'manager' tag for more details.) It then receives detailed interactions about the manager's activities. This is because markers are used to enable such things as slide show "next" and "previous" controls, menu buttons and thumbnail buttons. To keep their state accurate, they need to carefully track the manager objects. These interactions have "event" in their pre-defined variables -- it's a ContainerMgrEvent object with the following properties:

  • type: The type of the event.
  • manager: The manager object the marker is associated with.
  • current: The current DocumentElement.
  • next: The next DocumentElement if a transition is occurring or else null.
  • afterNext: The DocumentElement selected after the current transition completes or null.
  • transitioners: The array of transitioners active for the current transition. (Not all transitioners need be used for every transition. See the section on the 'transitioner' tag for more details.)
  • progress: A number from 0 to 1 indicating the progress of the transition. There will always be at least two events per transition in which one will have a progress of 0 and the other will have a progress of 1.

The interactions associated with the ContainerMgrEvent are:

  • onWillSelect: Called on a marker when a transition is occurring and the user has selected the next container before it completes. It doesn't indicate the object will actually be selected, as the user may choose yet another object before the transition completes.
  • onSelect: Called on a marker when the 'manager' tag initiates the change of selection.
  • onProgress: Called on a marker as the transition between the current selection and the next selection progresses.
  • onTransitionEnd: Called on a marker when the transition between the current selection and the next selection completes.
  • onPause: Called on a marker when the transition between the current selection and the next selection pauses.
  • onResume: Called on a marker when the transition between the current selection and the next selection resumes.
  • onHoldProgress: Called on a marker as the manager holds on the current selection before automatically going to the next. This is only called if the style "auto-play" is true for the manager.

A manager element uses its children transitioner elements to define the transition from one element to another. The following interactions are called on the individual transitioner DocumentElements:

  • onInit: Called when the manager is changing the currently selected element. Because transitioners may be delayed, this event doesn't necessarily correspond with this transitioner starting.
  • onStart: Called when the transitioner actually begins its process. This may be after some delay.
  • onFastForward: Called when the transitioner process is fast forwarded to the end,
  • onStop: Called when the transitioner's process is stopped.
  • onResume: Called when the transitioner's process is resumed.
  • onTransitionDone: Called when the transitioner's process is completed.

Image Interactions

The following interactions apply to the "img" element:

  • onLoaded: Called when the external image or symbol is loaded.
  • onFailed: Called when the external image or symbol fails to load.

To better control the calculation of image dimensions for scaling purposes, Frontal supports an interaction named getImageDimensions. It has these pre-defined variables:

  • image: An instance of the Flash DisplayObject class that represents the loaded image, Flash SWF or Flash library symbol.
  • src: The string used to identify the image, i.e., the URL or library linkage.
  • isSymbol: This is true if the image is a Flash library symbol (and so loaded with the "symbol" attribute on the 'img' tag) otherwise it is false.

This interaction should return an Object with "width" and "height" properties.

See Resizing Images for more details.

Form Interactions

The following interactions apply to the "form" element. See the Advanced Topics section for more information about form submissions, including multi-file submissions which entail multiple subsmissions.

  • onSubmit: Called when the form submit request is received. This is an opportunity to do validation on the form's entries. If the interaction returns false then the form submission will be canceled.
  • onAction: Called just before the form is about to submit it's information. A pre-defined variable "request" is available in the interaction's scope. This variable is the Flash URLRequest that's being used for the submission, and this interaction allows a Frontal script to change the default values derived from the form. (In other words, this interaction need not be defined for a form to work; it's simply provided for customizations like using the form to submit XML RPC data for example.)
  • onFormData: If one or more files are being submitted with the form, then when information is returned from the server, this interaction is called. See the Flash documentation on FileReference.upload() for more details. In the pre-defined variables, there's the standard "event" as well as several other variables:
    • file: the FileReference that dispatched this event.
    • submissionId: A Frontal-generated ID that's used to group the multiple submissions that Flash requires for a multi-file submission.
    • request: the URLRequest used during the FileReference.upload() call.
    • submissionCount: The number of submissions that are part of this multi-file submission.
    • submissionIndex: The 1-based index of the submission that triggered this event. (Submissions are sequential and do not overlap.)
    • fileReferences: An array of objects, one for each file in the multi-file submission. Each object has two properties: "file", which is the Flash FileRequest object for this file upload, and "name", which is the name attribute on the file input that was used to select the file.
  • onPartialSuccess: Called during a multi-file submission after each successful file submission. It has the same pre-defined variables as the onFormData interaction.
  • onSuccess: Called when the form successfully (and completely for multi-file submission) finishes.
  • onError: Called when a form fails to complete successfully, signaling an IO error or a security error.

Input Interactions

The following interactions are called on input elements by a surrounding form:

  • getSubmissionValue: This interaction provides an opportunity to return a modified input value to the surrounding form as it is submitted.

Style Interactions

The following interaction is applied to a DocumentElement and allows communication to all of those elements in the Frontal document that match some selector.

  • onSelectorNotification: Called when a FrontalEvent.NOTIFICATION event is dispatched from a selector that matches the DocumentElement.

Progress Indicator Interactions

The following is part of Frontal's progress indicator framework. With this framework, a Frontal DocumentElement may act as a progress indicator for another DocumentElement, like, for example, an "img" element. In this case, the DocumentElement being monitored dispatches progress events that are handled by an interaction on the indicator element. See the Advanced Topics section for more information.

  • onProgress: Called as the monitored DocumentElement makes progress in loading its external assets or submitting its form information, as examples. (Those are examples built into Frontal, though they may be customized to support additional scenarios.) In the predefined variables for the interaction, you'll find the object "progress", which has the following properties:
    • bytesLoaded: The number of bytes loaded so far.
    • bytesTotal: The total number of bytes to load. Because this number isn't immediately available for an external asset, it may change.
    • entries: An array of sub-entries that make up the total progress. For example, if several images are being loaded, each image makes up an entry. Each entry object has the following properties:
      • bytesLoaded
      • bytesTotal
      • docElem: The DocumentElement object reporting this information.
      • fraction: A number from zero to 1 indicating the fractional amount loaded. It's not necessarily bytesLoaded / bytesTotal. For example, consider the case where there's no external asset. Then bytesLoaded and bytesTotal are both zero and the ration is bytesLoaded / bytesTotal undefined; however, this fraction property has been set to equal 1.
    • fraction: A number from 0 to 1 indicating the fractional amount loaded. See the previous bullet for a discussion of its value.

Document Interactions

Frontal uses the following interaction on the "document" element to support custom tags in the document definition. That is, if the Frontal parser encounters a tag that it doesn't recognize, it calls this interaction to see if it's supported.

  • onGetClassRefByNodeName: Called on the document element when an unknown tag is encountered. The pre-defined variables are:
    • nodeName: The name of the unknown tag.
    • attributes: An instance of the Frontal attributes class that represents the attributes on the tag. This object supports the same getAttribute and attributeExists methods that are defined on the DocumentElement class.
    • node: This is the Flash XML node that's being parsed. That is, node.name() is equivalent to the "name" variable.

For example, the following adds support for a "foo" element. In this case we're simply making it equivalent to a "div" element (the com.frontalcode.Container class is what handles this element).

If you build your own Frontal Renderer it is possible to create your own DocumentElement classes. You may to download the source code to build your own Frontal Renderer here. Learn more here:

http://code.google.com/p/frontal/wiki/Building_the_Frontal_Renderer

<script><![CDATA[
    document.sA ( "onGetClassRefByNodeName", "return getClassRefByNodeName ( nodeName, attributes, node );" );
 
    function getClassRefByNodeName ( nodeName, attributes, node )
    {
        var result = null;
        if ( nodeName == "foo" ) result = com.frontalcode.Container;
        return result;
    }
]]></script>
<foo style="width: 50px; height: 50px; background-color: purple;" />

Deep Linking Interactions

Frontal supports deep linking with the com.asual.SWFAddress class. The following interactions allow a custom integration with that process for a DocumentElement with the "deep-link" style set to "query" or "path". See Advanced Topics section for more information.

  • onGetDeepLinkValue: Called when a deep link value in the URL is being resolved. The value in the URL will be passed to this interaction as the predefined variable "index". This interaction should then return whatever value is associated with "index". For example, a 'manager' with "deep-link" set to "query" will treat "index" as a numeric value and return the corresponding managed DocumentElement.
  • onGetDeepLinkIndex: This interaction is called when the inverse operation of onGetDeepLinkValue is needed. That is, we have a value that's associated with a deep link and want to know what that deep link might be. The value of interest is passed to the interaction as the pre-defined variable "value". For example, a 'manager' with deep-link set to "path" would return the URL path of a managed element passed in as the "value".
  • onProcessDeepLink: After the interaction "onGetDeepLinkValue" processes an index from the URL, the returned value must be acted on. This interaction handles that piece of the puzzle. A pre-defined variable named "value" is the return from the "onGetDeepLinkValue" interaction. So for a "manager" object for example, this interaction would call its "jumpTo" method with the value parameter (a DocumentElement) as its argument.

Video Interactions

The video tag supports interactions based on the playback of the video. These include:

  • onVideoReady: This is called when the FLVPlayback instance dispatches the ready event. The pre-defined variable is:
    • event: The dispatched Flash VideoEvent.
  • onVideoStateChange: This is called when the FLVPlayback instance dispatches the change event. The pre-defined variable is:
    • event: The dispatched Flash VideoEvent.
  • onVideoComplete: This is called when the FLVPlayback instance dispatches the complete event. The pre-defined variable is:
    • event: The dispatched Flash VideoEvent.

The video tag also supports custom interactions for its cue points. For a "video" element, whenever it's rendered it checks its attributes for any that begin with the word "cuepoint". For each of these, it looks for a value that's in seconds and optionally followed by a comma and a title. With this information, the video object will add a cuepoint to the Flash FLVPlayback associated with each video object, and when the cuepoint is reached, a corresponding interaction will be called. The name of the interaction is simply the cuepoint's attribute name prefixed with "on". A predefined variable "cue" contains an object with these members:

  • name: The name of the cuepoint attribute.
  • time: The time of the cuepoint.
  • title: The title of the cuepoint if one was specified.

For example, here we add a cuepoint at the 5-second point with the attribute "cuePoint1". When the video hits 5 seconds, then the interaction "oncuePoint1" is called and the background of the document goes blue.

<style><![CDATA[
#myVideo
    {
        @cuePoint1: 5, Go Blue!
        @oncuePoint1: gE ( "bg" ).sS ( "background-color", "blue" );
    }
]]></style>
<div id="bg" style="width: 100%; height: 100%;">
     <video id="myVideo" src="http://www.frontalcode.com/assets/video/video_1.flv" style="margin: auto; video-auto-play: true;" />
</div>

Note that the cuepoint title is primarily for deep linking purposes. See the Advanced Topics section for more information.

You may also use the interaction "onAnyCuePoint" to have a single interaction for all cue points. That is, this interaction is called whenever any cue point is hit.

Manual Interactions

It's often handy to be able to call an interaction from a script. So for example, you'd like to simulate a click on a DocumentElement. To do this, there's a method on the DocumentElement object named "runInteractions". It takes three parameters:

  • attribute: The name of the interaction, e.g., "onClick". (Remember that interactions are applied to a DocumentElement as an attribute.
  • localVariables: An object whose properties will become the predefined variables for the interaction.
  • namespace: See the description of the "gA" method in the section Accessing Frontal Tags for Scripting for more details.

For example, this uses a manual interaction to click the button.

<div id="button" style="color: blue;" onClick="document.write ( 'You clicked me!' );">
    Hello, world.
</div>
<script><![CDATA[
gE ( "button" ).runInteractions ( "onClick" );
]]></script>

Adding Multiple Interactions for a Single Event

It's a common scenario in which you'd like to run multiple interactions for a single event. For example, let's say an onClick interaction has some graphical effect, and also has some tracking effect. We could put both of these tasks in a single interaction, but that'd make it difficult to reuse our code in certain situations, like when a click on some other element should only do the graphical effect, or only do the tracking effect.

The answer is to put the interactions in separate XML namespaces. Frontal will look through all the active namespaces for an element to find relevant interactions. In this way, we can define an onClick in the default namespace to do, say, the graphical effect and we can define another onClick in another namespace to do the tracking effect.

For more details and examples, see More Frontal Markup#Namespaces.

Personal tools
Get Adobe Flash player