AngularJS: Getting Started

Getting Started

AngularJS is a JavaScript framework that provides lots of solutions to many of web development’s problems. This isn’t to say that it is the end-all-be-all of web development tools, but it does provide a great jumping off point for your web application.

There are a few things that you’ll need to wrap your head around before jumping in full force but let’s take a quick look at the basics with the following super-simple web application.

HTML

Nothing in the HTML should surprise you. We’re working with a few HTML tags, attributes and a bit of “templating”. If you’re not familiar with things like HandlebarsJS, check it out – not that it has much to do with AngularJS, but it is useful to know about.

JavaScript

We haven’t written any JavaScript. We’re only including the angular.min.js script in the fiddle.

And what have we gained? Well, admittedly the sample application isn’t overly useful or exciting. We are, however, leveraging a couple of the main concepts of Angular with this sample:

  1. Model/view/controller (MVC): Your HTML template is the “view”. That view is affected by Angular’s model, called the scope. The scope is kind of hidden in this example, but you’ll become very familiar with scope as you work more with Angular.
  2. 2-way binding (wha?!?!): A “super feature” of angular – when we type into the text field, the text value of the H2 updates as we type.

For those of us who aren’t so good with delayed gratification, then this sample is pretty great. But, this is only the beginning. AngularJS has so much more to offer. We’re starting with small steps & keeping it simple…for now. There will be plenty more AngularJS to follow.

AngularJS, what is it?

AngularJS, Simply Put

AngularJS

AngularJS is a JavaScript framework. It provides an Application Programming Interface (API) that allows you to build web applications using JavaScript, HTML, & CSS. The API that Angular provides is a well thought out and robust set of solutions that provide you the ability to create powerful web applications more simply & quickly.

AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop. – angularjs.org

Thinking Differently

For me, and I’m imagining many others, Angular required a paradigm shift in the way I thought about application development. Angular doesn’t just allow you to manipulate the DOM. What angular does is allow you as the developer to extend the existing features of HTML and add on to the capabilities of the browser in a very slick way. Angular’s angle (ha!) is to control the view by inspecting the DOM for an injection point where you can hen create the features of your application. These injections can be objects that act as the logical control center for an existing tag like an <h1> or adding on attributes to that same tag. Angular also allows you to create completely new tags that can be used in you application. The result then become the components, views and logic of you’re application.

The point being is that now you have control over the features and functionality of the browser for your application. Understanding how your new features features are added to the browser, and how you can best structure your application to allow for simplified and maintainable development is the first step. The way I tend to think of it is that Angular is responsible for telling the browser what to do, you just need to provide the logic and data to allow it to do so. That is a very important concept to grasp with Angular – the data is what drives the application. You don’t, and shouldn’t, manipulate the DOM directly. You change the data, then it is up to angular to render the view correctly based on that data.

For example, instead of using jQuery (or angular’s jQLite) to manipulate the DOM to show some text or change a class, we change the data model. This change is evaluated and angular then updates and renders the view appropriately based on that changed data. You can see this in the sample below:

The displayed H1 value changes when we type into the text input. This is Angular being notified that the model has updated and that the view needs to re-render the updated data. There is nothing we need to do programmatically to set the “innerHTML” of a specific div with the new data. Also notice that there is no custom JavaScript in the jsFiddle above. We only have to include the library & specify the model & bindings.

For me, it took some time to get it. But, once I did, I loved it!

AngularJS: Simple Tabs

Because of projects and personal interest, I’ve been working with AngularJS lately. A recent project needed a tab component to switch between views. The following is a simple prototype of the tab component that I created.

With a background in Flash and Flex it is interesting and exciting to have to change my perspective on how to create and use these types of UI components. Angular forces you to think about the structure of not just the components, but also the entire application in a different way. Before, I’d look to a component framework to provide the tab control. Now, these types of components seem to come together rather simply. So far, Angular is impressing me.

JavaScript Chops Meetup

JavaScript Chops Meetup

I was hanging out with Matt O’Donnell this weekend and we got to talking about javascript & how we both want to get better at it (along with HTML & CSS). We’re both super busy with work and life and don’t have a ton of spare time, but still want to make improving our javascript chops a priority.

So, here is the idea – a short (30-60 minute) online meetup.

Here is what I’m thinking a Google Hangout in the evening, once or twice a month. We spend 30-60 minutes talking mainly about javascript with some HTML & CSS tossed in to make sure we are covering our bases. Everyone involved takes turns presenting on and discussing concepts like “the basics” & “getting started”, best practices, tools, libraries, & frameworks, specific projects, problems and/or questions that we have.

Initially I’d like to keep it to a small group so the conversations don’t get out of hand.
What do you think? Want to do it?

Sign up to let me know you’re interesteed & I’ll let you about the when’s and where’s.

#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
/* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */

Subscribe to our mailing list

* indicates required

Email Format

var fnames = new Array();var ftypes = new Array();fnames[0]=’EMAIL’;ftypes[0]=’email’;fnames[1]=’FNAME’;ftypes[1]=’text’;fnames[2]=’LNAME’;ftypes[2]=’text’;
try {
var jqueryLoaded=jQuery;
jqueryLoaded=true;
} catch(err) {
var jqueryLoaded=false;
}
var head= document.getElementsByTagName(‘head’)[0];
if (!jqueryLoaded) {
var script = document.createElement(‘script’);
script.type = ‘text/javascript’;
script.src = ‘//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js’;
head.appendChild(script);
if (script.readyState && script.onload!==null){
script.onreadystatechange= function () {
if (this.readyState == ‘complete’) mce_preload_check();
}
}
}

var err_style = ”;
try{
err_style = mc_custom_error_style;
} catch(e){
err_style = ‘#mc_embed_signup input.mce_inline_error{border-color:#6B0505;} #mc_embed_signup div.mce_inline_error{margin: 0 0 1em 0; padding: 5px 10px; background-color:#6B0505; font-weight: bold; z-index: 1; color:#fff;}’;
}
var head= document.getElementsByTagName(‘head’)[0];
var style= document.createElement(‘style’);
style.type= ‘text/css’;
if (style.styleSheet) {
style.styleSheet.cssText = err_style;
} else {
style.appendChild(document.createTextNode(err_style));
}
head.appendChild(style);
setTimeout(‘mce_preload_check();’, 250);

var mce_preload_checks = 0;
function mce_preload_check(){
if (mce_preload_checks>40) return;
mce_preload_checks++;
try {
var jqueryLoaded=jQuery;
} catch(err) {
setTimeout(‘mce_preload_check();’, 250);
return;
}
var script = document.createElement(‘script’);
script.type = ‘text/javascript’;
script.src = ‘http://downloads.mailchimp.com/js/jquery.form-n-validate.js’;
head.appendChild(script);
try {
var validatorLoaded=jQuery(“#fake-form”).validate({});
} catch(err) {
setTimeout(‘mce_preload_check();’, 250);
return;
}
mce_init_form();
}
function mce_init_form(){
jQuery(document).ready( function($) {
var options = { errorClass: ‘mce_inline_error’, errorElement: ‘div’, onkeyup: function(){}, onfocusout:function(){}, onblur:function(){} };
var mce_validator = $(“#mc-embedded-subscribe-form”).validate(options);
$(“#mc-embedded-subscribe-form”).unbind(‘submit’);//remove the validator so we can get into beforeSubmit on the ajaxform, which then calls the validator
options = { url: ‘http://forkbites.us1.list-manage.com/subscribe/post-json?u=db7398b2dfeb32d6f5b9b98df&id=e8c62e786c&c=?’, type: ‘GET’, dataType: ‘json’, contentType: “application/json; charset=utf-8”,
beforeSubmit: function(){
$(‘#mce_tmp_error_msg’).remove();
$(‘.datefield’,’#mc_embed_signup’).each(
function(){
var txt = ‘filled’;
var fields = new Array();
var i = 0;
$(‘:text’, this).each(
function(){
fields[i] = this;
i++;
});
$(‘:hidden’, this).each(
function(){
var bday = false;
if (fields.length == 2){
bday = true;
fields[2] = {‘value’:1970};//trick birthdays into having years
}
if ( fields[0].value==’MM’ && fields[1].value==’DD’ && (fields[2].value==’YYYY’ || (bday && fields[2].value==1970) ) ){
this.value = ”;
} else if ( fields[0].value==” && fields[1].value==” && (fields[2].value==” || (bday && fields[2].value==1970) ) ){
this.value = ”;
} else {
if (/[day]/.test(fields[0].name)){
this.value = fields[1].value+’/’+fields[0].value+’/’+fields[2].value;
} else {
this.value = fields[0].value+’/’+fields[1].value+’/’+fields[2].value;
}
}
});
});
$(‘.phonefield-us’,’#mc_embed_signup’).each(
function(){
var fields = new Array();
var i = 0;
$(‘:text’, this).each(
function(){
fields[i] = this;
i++;
});
$(‘:hidden’, this).each(
function(){
if ( fields[0].value.length != 3 || fields[1].value.length!=3 || fields[2].value.length!=4 ){
this.value = ”;
} else {
this.value = ‘filled’;
}
});
});
return mce_validator.form();
},
success: mce_success_cb
};
$(‘#mc-embedded-subscribe-form’).ajaxForm(options);

});
}
function mce_success_cb(resp){
$(‘#mce-success-response’).hide();
$(‘#mce-error-response’).hide();
if (resp.result==”success”){
$(‘#mce-‘+resp.result+’-response’).show();
$(‘#mce-‘+resp.result+’-response’).html(resp.msg);
$(‘#mc-embedded-subscribe-form’).each(function(){
this.reset();
});
} else {
var index = -1;
var msg;
try {
var parts = resp.msg.split(‘ – ‘,2);
if (parts[1]==undefined){
msg = resp.msg;
} else {
i = parseInt(parts[0]);
if (i.toString() == parts[0]){
index = parts[0];
msg = parts[1];
} else {
index = -1;
msg = resp.msg;
}
}
} catch(e){
index = -1;
msg = resp.msg;
}
try{
if (index== -1){
$(‘#mce-‘+resp.result+’-response’).show();
$(‘#mce-‘+resp.result+’-response’).html(msg);
} else {
err_id = ‘mce_tmp_error_msg’;
html = ‘

‘+msg+’

‘;

var input_id = ‘#mc_embed_signup’;
var f = $(input_id);
if (ftypes[index]==’address’){
input_id = ‘#mce-‘+fnames[index]+’-addr1′;
f = $(input_id).parent().parent().get(0);
} else if (ftypes[index]==’date’){
input_id = ‘#mce-‘+fnames[index]+’-month’;
f = $(input_id).parent().parent().get(0);
} else {
input_id = ‘#mce-‘+fnames[index];
f = $().parent(input_id).get(0);
}
if (f){
$(f).append(html);
$(input_id).focus();
} else {
$(‘#mce-‘+resp.result+’-response’).show();
$(‘#mce-‘+resp.result+’-response’).html(msg);
}
}
} catch(e){
$(‘#mce-‘+resp.result+’-response’).show();
$(‘#mce-‘+resp.result+’-response’).html(msg);
}
}
}

Configure Adobe Flash Media Server for Live HTTP Dynamic Streaming

How to set up Live HTTP Dynamic Streaming

So you want to stream a live event using HTTP Dynamic Streaming (HDS) and HTTP Live Streaming (HLS)? No problem. Adobe Media Server (AMS) provides a right out-of-the-box solution for you. To do so, you’ll need to:

  1. Download and install Flash Media Live Encoder (FMLE)
  2. Make a small configuration change to the encoder
  3. Setup your live event
  4. Begin streaming
  5. Set up a player

Installing and configuring Flash Media Live Encoder

  1. Download FMLE from http://www.adobe.com/products/flash-media-encoder.html
  2. Once it is installed open the config.xml file from
    1. Windows: C:Program FilesAdobeFlash Media Live Encoder 3.2conf
    2. Mac: /Applications/Adobe/Flash Media Live Encoder 3.2/conf/
  3. Locate the “streamsynchronization” tag under flashmedialiveencoder_config -> mbrconfig -> streamsynchronization and set the value for “enable” to “true”. The streamsynchronization node should look similar to the following:
    <flashmedialiveencoder_config>
     <mbrconfig>
       <streamsynchronization>
         <enable>true</enable>
       </streamsynchronization>
    ...
  4. Save and close the file.

Setting up the live event

Streaming a live event involves using the “livepkgr” application that comes installed with AMS. The livepkgr application comes with a preconfigured event named livestream. We’ll use this as a template for our live event.

  1. On your server navigate to the {AMS_INSTALL}/applications/livepkgr/events/_definst_ directory.
  2. We’re going to call our event “myliveevent”. Create a new directory and name it “myliveevent”.
  3. Open the newly create mylivestream directory and create a new XML file named “Event.xml”. This file is used to configure the just-in-time (JIT) packaging settings for your HDS content. Add the following XML to the file. Note: You can also copy the Event.xml file from the liveevent directory that is setup by default. Just update the EventID to match the folder name.
    <Event> 
      <EventID>myliveevent</EventID> 
      <Recording> 
        <FragmentDuration>4000</FragmentDuration> 
        <SegmentDuration>16000</SegmentDuration> 
        <DiskManagementDuration>3</DiskManagementDuration> 
      </Recording> 
    </Event>

    For more information about the values in the Event.xml  file you can review Adobe’s documentation – link in the resources section below.

  4. Save and close the file.
  5. Your event is now set up. You can reuse this event all you want, or create another one for a different event name.

Begin streaming

Now we can start up FMLE and set it up to connect to our livepkgr application and begin streaming.

  1. In the left panel of FLME make sure the “Video” and “Audio” sections are both checked.
  2. Video
    1. In the video section, set the format to be “H.264” and then click the button with the wrench icon.
    2. In the resulting pop-up window, make sure the settings match the following:
      1. Profile: Main
      2. Level: 3.1
      3. Keyframe Frequency: 4 seconds
        Live HTTP Dynamic Streaming H.264 Settings
    1. Click “OK” to close the pop-up window.
    2. In the “Bit Rate” section make sure you only have one of the bit rates selected. We’re only creating a single stream for now.
      Live HTTP Dynamic Streaming Video Encoder Settings
  3. Audio
    1. In the Audio section, set the format to “AAC”
      Live HTTP Dynamic Streaming Audio Encoder Settings
  4. In the right panel set “FMS URL” to point to your server and the livepkgr application:
    1. Example: rtmp://192.168.1.113/livepkgr
  5. Set the “Stream” value to be mylivestream?adbe-live-event=myliveevent
    1. “mylivestream” is the name of the stream and can be anything you’d like. The actual files that AMS creates will be stored in the livepkgr/streams/_definst_/mylivestream directory.
    2. “?adbe-live-event=myliveevent” tells the livepkgr application to use the Event.xml in the livepkgr/events/_definst_/myliveevent directory that we created.
      Live HTTP Dynamic Streaming RTMP Server Settings
  6. Click the “Connect” button. If all goes well, you’ll connect to your server. If not, check to make sure there aren’t any typos in the values for “FMS URL” and “Stream” and that you can connect to your server and it is running.
  7. Click the bug green “Start” button to begin streaming.
    Live HTTP Dynamic Streaming Big Green Start Button
  8. You now have a stream. Let’s see if we can get a player to play it back.

Setting up the player

Getting to the HDS content for your new stream involves requesting a URL that lets Apache (installed with AMS) know what we are looking for. The path will consist of the following parts:

  1. The protocol: http://
  2. The server location: 192.168.1.113/ (in my case, yours will be different)
  3. The Location that is configured to deliver live streams. By default these are:
    1. HDS: hds-live/
    2. HLS: hls-live/
  4. The application name: livepkgr/
  5. The instance name (we’ll use the default): _definst_
  6. The event name: myliveevent
  7. The stream name: mylivestream
  8. The F4M file extension for HDS – .f4m or the M3U8 file extension for HLS.

So if we put all of that together we’ll get a URL that looks like:

  • HDS: http://192.168.1.113/hds-live/livepkgr/_definst_/myliveevent/mylivestream.f4m
  • HLS: http://192.168.1.113/hls-live/livepkgr/_definst_/myliveevent/mylivestream.m3u8

Note: You may need to add the 8134 port to the URL if you didn’t install AMS on port 80: http://192.168.1.113:8134/hds-live/livepkgr/_definst_/myliveevent/mylivestream.f4m

  1. Open a browser window and navigate to that URL, you should see the F4m’s XML content.
    Live HTTP Streaming F4M XML
  2. Open the following URL: http://www.osmf.org/configurator/fmp/#
  3. Set your F4M url as the value for “Video Source”
  4. Select the “Yes” radio button for “Are you using HTTP Streaming or Flash Access 2.0?”
  5. Set “Autoplay Content” to “Yes”
    Live HTTP Dynamic Streaming Player Settings
  6. Click the Preview button at the bottom of the page.
  7. Congratulations. You are now streaming live media over HTTP.

To verify the HTTP Streaming, open a tool that will let you inspect the HTTP traffic (something like Developer Tools or Firebug). You should see requests for resourecs like “mylivestreamSeg1-Frag52” and “mylivestream.bootstrap”. This is the player requesting HDS fragments and Apache and AMS working together to package them just-in-time for the player.
Live HTTP Dynamic Streaming HTTP Traffic

Hopefully this provides you with some good information about Live HTTP Dynamic Streaming and clarifies some of the setup and configuration details. Please, if you have any questions, let me know in the comments or contact me.

Resources

OSMF Fix: “Local HDS” Playback

OSMF & Local F4M Files

The Open Source Media Framework (OSFM) doesn’t respond well when you pass it a local F4M file path for playback. Playing back local HDS fragments is an edge case, but enough people have encountered this problem that I think it deserves a little attention.

Fixing the IndexHandler

The basics involve extending the HTTPStreamingF4FIndexHandler then overriding the constructFragmentRequest() method & removing the requirement that HTTP be part of the URI.

So, after you’ve created your new class that extends org.osmf.net.httpstreaming.f4f.HTTPStreamingF4FIndexHandler, add the following override:

[actionscript3]override protected function constructFragmentRequest(serverBaseURL:String, streamName:String, segmentId:uint, fragmentId:uint):String
{
var requestUrl:String = "";
requestUrl += streamName + "Seg" + segmentId + "-Frag" + fragmentId;
return requestUrl;
}[/actionscript3]

The original constructFragmentRequest() method looks like:

[actionscript3]protected function constructFragmentRequest(serverBaseURL:String, streamName:String, segmentId:uint, fragmentId:uint):String
{
var requestUrl:String = "";
if (streamName.indexOf("http") != 0)
{
requestUrl = serverBaseURL + "/" ;
}
requestUrl += streamName + "Seg" + segmentId + "-Frag" + fragmentId;
return requestUrl;
}[/actionscript3]

So you can see we just removed the “http” requirement.

Now you need to get OSMF to use your adjusted IndexHandler. This means you need to create a custom NetLoader, that creates a custom StreamingFactory & then the Factory creates your IndexHandler. Once you have all of this done, you can then create a custom MediaFactory (I usually just extend DefaultMediaFactory) and create a MediaFactoryItem that can handle your local F4M file resource, & specify your new NetLoader for the element that is returned.

Convoluted eh? Let’s break it down.

Creating the Factory

Since we are dealing with HDS content extend org.osmf.net.httpstreaming.f4f.HTTPStreamingF4FFactory & override the createIndexHandler() method. In this method set the indexHandler property equal to an instance of your IndexHandler (mine is named “LocalFileStreamingF4FIndexHandler”).

Example:
[actionscript3]override public function createIndexHandler(resource:MediaResourceBase, fileHandler:HTTPStreamingFileHandlerBase):HTTPStreamingIndexHandlerBase
{
indexHandler = new LocalFileStreamingF4FIndexHandler(fileHandler);
return indexHandler;
}[/actionscript3]

Creating a NetLoader

Now we need our NetLoader – this is where the Factory is created. I extended org.osmf.net.httpstreaming.HTTPStreamingNetLoader & created an override for the createHTTPStreamignFactory() method.

Example:
[actionscript3]override protected function createHTTPStreamingFactory():HTTPStreamingFactory
{
return new LocalFileStreamingF4FFactory();
}[/actionscript3]

Creating a custom MediaFactory

Now we need to be able to injet this NetLoader into the system. So extend the org.osmf.media.DefaultMediaFactory & add a MediaFactoryItem that return a new VideoElement. Pass in an instance of your NetLoader to the the VideoElement constructor.

Example:
[actionscript3]localFileStreamingNetLoader = new LocalFileStreamingNetLoader();
localHDSFileNetLoader = new LocalHDSContentNetLoader();
addItem( new MediaFactoryItem( "com.realeyes.osmf.elements.video.httpstreaming", localHDSFileNetLoader.canHandleResource,
function():MediaElement
{
return new VideoElement(null, localHDSFileNetLoader);
}
)
);[/actionscript3]

Specifying the canHandle and passing in the NetLoader

You can also see in the previous bit of code that the MediaFactoryItem asks for a canHandleResource function. This is where conditions are added to make sure the you’re working with the right type of media. For this situations you can default to the super’s canHandleResource() which checks the resource HTTP Streaming metadata.

Now you have a setup that can handle a local F4M file and the downloaded fragments. There are a couple of considerations you’ll need to keep in mind:

  1. The fragments and F4M file must reside in the same directory. OSMF looks for the fragments in the directory that they F4M is in.
  2. Multi-bitrate won’t work, unless you can download the fragments for all the bitrates and work out storage for them.

The provided examples is the least obtrusive way to get local HDS content to play. Alternatively  you can edit the HTTPStreamingIndexHandler and compile an OSMF swc to use for a quick and dirty fix.

Aptana SDOCML & Code Hinting Support

Prompted by this post, I’ve been working on a tool that uses jsduck and Adobe AIR to create the SDOCML necessary for Aptana code hinting. Specifically I’ve been playing with EXTJS 4.0 becuaseof some interest in Sencha.

In the near future I’ll post the SDOCML files that I’ve created for the code hinting and once I get the tool looking presentable and working efficiently, I’ll post the source of that to GitHub.

Here is the current version of the file. I’m not completely sure is has everything it needs. So, it is a work in progress and I’ll post updates as I create them.
extjs4.0-v0.1.sdocml

If you’d like the SDOCML for EXTJS 4.1 Beta
extjs4.1.beta-v0.1.sdocml

Mobile Flex: View Data

From the previous post you should know how to navigate from 1 view to the next using the ViewNavigator.  Now, you want some data in that view right? No problem, this is where the View object’s ‘data‘ property comes into play. Setting the data property is accomplished by passing the data object, in addition to the View’s class name, into the pushView() method on the navigator object.

Example:

[as3]navigator.pushView(MyNewView, dataObject);[/as3]

This effectively calls the setting for the data property of the new View (MyNewView) object that is created.

Managing View Data

You could work with the data property on the View object directly. For instance, if the data object passed into the View via the pushView() method was a simple user object that contained a name property, you could bind the name property to a label control.

Example:

[xml]<s:Label id="name_lbl" text="{data.name}" />[/xml]

Overriding the Data Property Setter

Usually though, you’d want to override the setter for the data property. Then you can type your object and work with it in a better manner.

Example:

[as3]protected var user:User;
override public function set data(value:Object):void
{
super.data = value;
user = value as User;
}[/as3]

[xml]<s:Label text="{user.name}" />[/xml]

So now we’ve got the data in the view. The next step is to manage the state of each view. With mobile apps you can’t count on the view staying around, so we’ll need to keep a tight control on the state of each view. That way we can bring the user right back where they expect to be when they come back to the app after a call for example. In the next post we’ll look into how to do this. Stay tuned.

This article has also been posted on the Realeyes website.

Mobile Flex: ViewNavigator Basics

Flex 4.5 provides some pretty slick updates and enhancements, the least of which is the of Mobile components and the ability to slam out some pretty nice mobile apps easily. The first thing I’d like to talk about is a new concept, the ViewNavigator. The ViewNavigator provides some pretty intense functionality such as view management.

What is the ViewNavigator?

The ViewNavigator keeps track of your views. It does this by keeping your views in a list.  To add a new view you ‘push’ the view into the list, to remove a view you can ‘pop’ a view out of the list. You can think of it as a stack – first in, last out – and the last view in is the visible view.

Pushing a View into ViewNavigator's 'stack'
Popping a view out of the ViewNavigator's 'stack'

Using the ViewNavigator

Using the view navigator is a pretty straight forward process of capturing a user interaction, such as a button click, then pushing the new View into the ViewNavigator’s stack.

For example, let’s pretend that you have a new Flex mobile project. The default view of that project contains a button, that when clicked should display another view named MyNewView.  MyNewView also contains a button, that when clicked returns you to the the home view.

Home View Component

In the Home View component all you really need to worry about the the click handler on the button:

[xml]<s:Button id="next_btn"
label="NEXT"
width="100%"
click="navigtor.pushView(MyNewView)" />[/xml]

The click handler calls the pushView() method on ‘navigator‘, a property available from the View class, passing it the class name of the View that you want to display. We’ll cover getting data into that view and transitions in other posts.  The creation of the new View & default transition are all handled by the  framework.

MyNewView Component

The MyNewView View component is basically the same thing:

[xml]<s:Button id="back_btn"
label="BACK"
width="100%"
click="navigtor.popView()" />[/xml]

You call popView() on the ‘navigator‘ property which removes the view from the stack displaying the Home view again.

Here is a quick screen cast of an application using similar code:
[kml_flashembed publishmethod=”static” fversion=”9.0.0″ movie=”http://thekuroko.com/wp-content/uploads/2011/03/ViewNavigatorSample.swf” width=”485″ height=”785″ targetclass=”flashmovie”]Get Adobe Flash player

[/kml_flashembed]

This article has also been posted on the Realeyes website.

OSMF Custom Media Elements

OSMF Video Sample

A good argument for using a framework is the ability to extend the built in capabilities of the framework. For example, there was a comment on the ‘Getting Sstarted with OSMF Plugins‘ post that asked about using embedded images in theWatermarkPlugin sample.

Here are the steps that I took to get an embedded asset (instead of a ‘loadable’ asset) to show as a watermark:

1. Create a new class that extends MediaElement (this is a simple element, but you could extend any existing element depending on your needs). I named mine StaticImageElement.

[actionscript3]
package com.realeyes.osmf.plugin.element
{
public class StaticImageElement extends MediaElement
{

}
}
[/actionscript3]

2. Add a private Bitmap property with a getter and setter to the class – I named mine _bitmap.

[actionscript3]
private var _bitmap:Bitmap;

public function get bitmap():Bitmap
{
return _bitmap;
}

public function set bitmap( value:Bitmap ):void
{
if( value != _bitmap )
{
bitmap = value;
}
}
[/actionscript3]

3. In the setter for the bitmap property add the DisplayObjectTrait to the StaticImageElement

[actionscript3]
addTrait( MediaTraitType.DISPLAY_OBJECT, new DisplayObjectTrait( _bitmap as DisplayObject, bitmap.width, bitmap.height ) );
[/actionscript3]

4. The completed class is pretty simple because we get to use everything already created for OSMF.

[actionscript3]
package com.realeyes.osmf.plugin.element
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;

import org.osmf.media.MediaElement;
import org.osmf.traits.DisplayObjectTrait;
import org.osmf.traits.MediaTraitType;

public class StaticImageElement extends MediaElement
{
private var _bitmap:Bitmap;

public function StaticImageElement()
{
super();
}

public function get bitmap():Bitmap
{
return _bitmap;
}

public function set bitmap( value:Bitmap ):void
{
if( value != _bitmap )
{
_bitmap = value;

addTrait( MediaTraitType.DISPLAY_OBJECT, new DisplayObjectTrait( _bitmap as DisplayObject, bitmap.width, bitmap.height ) );
}
}
}
}
[/actionscript3]

5. Create the embedded asset in the WatermarkPluginElement class
[actionscript3]
[Embed( "/assets/osmf_logo.png" )]
protected static const OSMF_LOGO:Class;
[/actionscript3]

6. Now all we need to do in the WatermarkProxyElement set the bitmap property on a new instance of the StaticImageElement instead of creating an ImageElement with the watermark URL and ImageLoader.
Before:

[actionscript3]
var watermark:ImageElement = new ImageElement( new URLResource( watermarkURL ), new ImageLoader() );
[/actionscript3]

After:

[actionscript3]
var watermark:StaticImageElement = new StaticImageElement();
watermark.bitmap = new OSMF_LOGO();
[/actionscript3]

Bonus points for developing with a framework – more specifically OSMF! The embedded watermark shows up.

Download the original sample code:
[dm]10[/dm]

UPDATE: I’ve created an additional custom MediaElement called InteractiveImageElement.as. Thanks for the idea @cucu_adrian! The new element handles rollover and rollout by adjusting the image’s alpha property and setting the cursor to a button cursor. It also navigates to a url specified in the class – this would be any easy thing to make configurable though.
[dm]11[/dm]