Progress Indicators
From Frontal Wiki
Contents |
Introduction
Frontal provides a framework for measure the progress of an element. This progress may be towards downloading an image with the 'img' tag, uploading a file with the 'form' tag or some other process. This framework then is capable of producing a number of events that may be intercepted and acted on by interactions. It is in this way that we can show and animate an indicator that follows this progress.
Showing a Progress Indicator
Clear your browser's cache and then run the following code. Quickly switch to the result so that you can see the progress indicator.
<div style="show-progress-indicator: always; width: 100%; height: 100%; scroll: auto;"> <img src="assets/images/big_image_1.jpg" /> <img src="assets/images/big_image_2.jpg" /> <img src="assets/images/big_image_3.jpg" /> <img src="assets/images/big_image_4.jpg" /> <img src="assets/images/big_image_5.jpg" /> <img src="assets/images/big_image_6.jpg" /> <img src="assets/images/big_image_7.jpg" /> <img src="assets/images/big_image_8.jpg" /> <img src="assets/images/big_image_9.jpg" /> <img src="assets/images/big_image_10.jpg" /> </div>
We've enabled the progress indicator on the 'div' that surrounds the ten images. By doing this, it will track the loading progress of all of the contained images. We can do this with any depth of children under the progress indicator. We can even add a progress indicator on the 'document' tag which will track the progress of the whole Frontal document.
Progress of Managed Elements
When we have a 'manager' tag with the style hide-unselected set to true, then we are only interested in the progress of the next, current or initial managed element depending on the current state of the manager. The reasoning here is that since the visitor can only see one element at a time, then there's no reason to make them wait for the whole set to load before proceeding. In this case then, the progress reported by an element that contains a manager tag is the same is if it only contained the selected element.
Changing the Styling
Much like scrollbars, progress indicators are implemented by a 'template' in The Default Frontal Style Sheet. This means that we can affect them with styles or restructure them by replacing the template they use. Here is the template and pertinent rulesets from the default style sheet:
<style><![CDATA[ .frProgressIndicator [name=track] { background-color: #cccccc; border-color: #999999; border-width: 1px; width: 50%; height: 5px; margin: auto; } .frProgressIndicator [name=indicator] { height: 100%; width: 0%; background-color: #666666; } .frProgressIndicator { top: 0px; left: 0px; @onProgress { if ( progress.fraction < 1 ) { sS ( "display", "block" ); gE ( "indicator", false ).sS ( "width", progress.fraction * 100 + "%" ); } else { sS ( "display", "none" ); } } } ]]></style> <template name="frProgressIndicator"> <div class="frProgressIndicator"> <div name="track"> <div name="indicator" /> </div> </div> </template>
From this we can see how we might style the progress indicator. For example, add a style sheet like the following would change the color of the current progress indicator to red:
<style><![CDATA[ .frProgressIndicator [name=indicator] { background-color: red; } ]]></style>
Restructuring
From the above snippet from the default style sheet, we can get a clear idea of how the progress indicator is implemented. Really, it is just a set of divs laid out to look like a progress indicator and then an "onProgress" interaction that changes the width of one of those divs to match the current progress. It is therefore fairly straightforward to add our own, customized progress indicators.
A Numeric Progress Indicator
For example, we might want an indicator that just shows a big numeric percentage of the progress. To do that, we would add a template and some pertinent styles:
<style><![CDATA[ .numericProgressIndicator { scrollable: false; width: 100%; height: 100%; background-color: #000000; style-tween-ease: fl.transitions.easing.Regular.easeOut; style-tween-duration: 60; style-tween-use-secs: false; @onProgress { gE ( "display", false ).text = Math.ceil ( progress.fraction * 100 ) + "%"; if ( progress.fraction >= 1 && dynamic.progState != "outro" ) { dynamic.progState = "outro"; prepStyleTween ( ); sS ( "alpha", 0 ); tweenStyles ( ); } } } .numericProgressIndicator [name=display] { width: 100%; text-align: center; color: #ffffff; margin: auto; multiline: false; word-wrap: false; @onApplyStyles { sS ( "font-size", parent.height ); } } ]]></style> <template name="numericProgressIndicator"> <div class="numericProgressIndicator"> <text name="display">0%</text> </div> </template>
Notice that in this example we have not overwritten the standard progress indicator template but added a new one. To use this then we would need to set the progress-indicator-template style on the element whose progress is being monitored. For example:
<img src="assets/images/big_image_1.jpg" style="width: 1024px; height: 768px; show-progress-indicator: always; progress-indicator-template: numericProgressIndicator;" />
An Animated Progress Indicator
Animated loaders is something of a (vanishing) art for Flash movies. Typically with such loaders, there is some sort of intro, then a middle part that is either repeated as long as there is progress or is somehow indicative of the progress, and then some sort of outro. Here is an example of how such an animated progress indicator might be implemented in Frontal.
This example depends on the symbol "ProgressIndicator" which does not exist on the Frontal site. This movie clip is a simple timeline animation with a "intro" frame label on frame 1, an "introDone" frame label and a "stop();" action on the frame when the intro completes, and "outro" label where the outro begins, and an "outroDone" frame label and a "stop();" action on the frame when the outro completes.
In this example, we start the animation at the "intro" frame. When it's done, we use a text tag to show the percentage done. Then we run the animation from the outro. When its done, we fade away the whole progress indicator.
<style><![CDATA[ .animatedProgressIndicator { left: 0px; top: 0px; scrollable: false; border-width: 1px; width: 100% leftover; height: 100% leftover; background-color: #ffffff; style-tween-ease: fl.transitions.easing.Regular.easeOut; style-tween-duration: 6; style-tween-use-secs: false; @onEnterFrame { var anim = gE ( "animation", false ).image; switch ( anim.currentLabel ) { case "introDone": if ( dynamic.progState == "intro" ) { gE ( "display", false ).sS ( "visibility", "visible" ); if ( dynamic.progress.fraction < 1 ) { dynamic.progState = "introDone"; } else { gE ( "display", false ).text = "Loaded!" anim.gotoAndPlay ( "outro" ); dynamic.progState = "outro"; } } break; case "outroDone": if ( dynamic.progState == "outro" ) { gE ( "display", false ).sS ( "display", "none" ); prepStyleTween ( ); sS ( "alpha", 0 ); tweenStyles ( ); dynamic.progState = "outroDone"; sA ( "onEnterFrame", undefined ); } break; } } @onProgress { dynamic.progress = progress; var anim = gE ( "animation", false ).image; if ( dynamic.progState == null ) { anim.gotoAndPlay ( "intro" ); dynamic.progState = "intro"; } if ( progress.fraction < 1 ) gE ( "display", false ).text = Math.ceil ( progress.fraction * 100 ) + "%"; if ( dynamic.progState == "introDone" && progress.fraction >= 1 ) { gE ( "display", false ).text = "Loaded!" anim.gotoAndPlay ( "outro" ); dynamic.progState = "outro"; } } } .animatedProgressIndicator [name=animation] { margin: auto; width: 100px; height: 30px; overflow: visible; resize-scale: none; } .animatedProgressIndicator [name=display] { visibility: hidden; font-family: Trajan Pro; width: 100%; text-align: center; color: #ffffff; margin: auto 0px; font-size: 14px; } ]]> </style> <template name="animatedProgressIndicator"> <div class="animatedProgressIndicator"> <img name="animation" symbol="ProgressIndicator"> <text name="display">0%</text> </img> </div> </template>