First Unity Level
- December 22nd, 2011
- Write comment
Follow these steps to set up automatic code formatting within flash builder.
Note that this is specific to your workspace so you should store the file somewhere on
your system and become familiar with the steps to initialize these tools.
The install process is the same as anyone installing plugins on Flash Builder.
If you are familiar with this process feel free to just utilize the links to the
software below.
Install Flex Formatter:
http://flexformatter.googlecode.com/svn/trunk/FlexFormatter/FlexPrettyPrintCommandUpdateSite/
1. Help>Install New Software
2. In the work with input use the URL and click add
Note – use the name Flex Formatter
3. Select Flex Formatter
4. Click next
5. Click next
6. Accept the term of use
7. Click Finish
8. Click okay if you get a message about installing unsigned software
9. Wait to restart flash builder.
Install Any Edit
In flash builder go to http://andrei.gmxhome.de/eclipse/
10. Help>Install New Software
11. In the work with input use the URL and click add
Note – use the name AnyEdit
12. Click on the dropdown for Eclipse 3.5-3.7 plugins
13. Select AnyEditTools
14. Click next
15. Click next
16. Accept the term of use
17. Click Finish
18. Click okay if you get a message about installing unsigned software
19. Restart Flash Builder
Flex Formatter setup
1. Download the formatting.properties file attached to this page. Store it
somewhere you can reference down the road.
2. Flash Builder > Preferences > Flex Formatter
3. Select the radio button to indent using spaces
4. Select import at the bottom and point to the file “formatting.properties”
5. Click on the Flex Formatter arrow in the left hand navigation
6. Select Auto Format
7. Check the box to format ActionScript files on save
8. Select the radio box “format” instead of indent for ActionScript files
9. Do the same for MXML files
10. Click Apply
Any Edit Setup
1. Flash Builder > Preferences > General > Editors > AnyEditTools
2. Check the box “remove trailing whitespace”
3. Check the box “create new line at the end of the file”
4. Check the box “Convert tabs <-> spaces
5. Click on the “Convert” tab in the tabbar navigation at the top
6. Change the Tabwidth/number of spaces for tab to 4 instead of 2
7. Click Apply
Change Flash Builder to use spaces instead of tabs
1. Flash Builder > Preferences > Flash Builder > Editors
2. Check indent using spaces at the bottom
3. Click Apply
Life just got simpler—for us developers anyways. But the good news is that thanks to the public release of Flash Builder 4.5, clients, marketers and technologists are also going to benefit.
Flash Builder 4.5 was just publically released, giving us a taste of what Adobe has in store for the future of Flash applications running on devices. In short, devices will be a significant part of the road map for the Flash Platform. What I mean by this is that Adobe is providing developers with the tooling necessary to build, test, and deploy rich Internet applications across a broad number of environments and devices. In addition to the browser via Flash and the Desktop via AIR, we can now use AIR to deploy our applications on Android, iOS, and Blackberry Tablet OS devices.
THE WORKFLOW
Choose your Platform
When you create your new project in Flash Builder (FB) you now have the option of creating an “ActionScript Mobile Project.” This will allow you to build pure ActionScript 3 projects that are deployable to mobile and tablet devices.
Note: While there is also the option to build a “Flex mobile Project,” this is not supported yet on iOS or the Blackberry Tablet OS and will not be covered in this posting; expect a public update via Adobe in June adding support for these OSs’ to the Flex SDK.
When setting up the project you will have a few new project properties to configure. Specifically, now you have a step called “mobile” which will be where you configure your project’s device specific configurations. For example, you can specify what types of OS’s you wish to target including Google Android, iOS, and Blackberry Tablet OS. In addition to this, you can tell what FB types (if any) of user permissions you need granted to your application (used for Android apps). FB will also let you specify whether your application should be displayed to the user in full-screen or not, as well as whether you should automatically orient from portrait to landscape when the users rotates the device.

All of these properties will be reflected in your app-descriptor.xml, and could be setup manually there, but FB has streamlined the process to make our lives easier!
Debugging
Anyone that develops for the mobile or tablet space will tell you that you can only go so far using the emulators provided to you by the OS. FB has definitely made this process easy.
Before this, I was using shell scripts to package and sign the application as well as install it on the device. When that was done, I’d have to trick the FB debugger so I could debug my application directly on the device connecting over a wireless connection. While it was cool that I was able to do this, it made for anything but a rapid & realistic development process.
Now, you can setup a debug configuration within the IDE that will allow you to debug directly on the device via USB or your local wireless connection. You also have the option of debugging using an emulator that can replicate a variety of devices.
THE NET-NET
I was fortunate enough to be part of the private beta for this product and can say first-hand that it has come a long way in the last eight months! Streamlining the development process and targeting multiple platforms with one codebase is a great thing for us (the developers), our clients, and/or the consumers who use our applications. While this technology is still in it’s infancy and has a lot of room to grow, it is a definitely a huge step in the right direction. I, for one, tip my hat to Adobe for swimming up-stream in an effort of bridging the gap between software running on multiple operating systems and devices.
Interested in learning more or want to chat about what this means for your clients and projects? Come find me in the Boston office or reach out to me at ryan.canulla@digitas.com.
Since returning to agency life, and this time at a much larger agency, I find myself working on more multi-tiered applications and sites. This often involves dependencies on server-generated assets, content, flashvars and anything else you can think of that would make debugging in my local environment a bit of work. There are many times where debugging on the server is either easier or a requirement (Facebook development). In situations like this I use FTP with ANT to build my project, then deploy my new build to staging. Special thanks to Brian Connatser for teaching me this stuff!
Project Requirements:
Apache Ant
Commons-net-2.2.jar
Jakarta-oro-2.0.8.jar
Step One: Installing ANT
*Note – If you are using the ANT plugin for Flash Builder you can skip this step.
First, you need to go and download Apache Ant [http://ant.apache.org/]. If your not currently familiar with Ant, check out this Post by Charles Newman. Once you have ANT, unzip and store it somewhere on your system.
Now that you have ANT stored on your computer, you need to add it to your class path. What this means is that once added you will be able to run the ‘ant’ command from anywhere on your system as if you we inside your-ant-install-dir/bin. Basically, this is a list of directories that your shell will look through when running a command. Now open terminal and trace your current $PATH variable.
echo $PATH /Applications/apache-ant/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Applications/Adobe\ Flash\ Builder\ 4.5/sdks/4.1.1/bin:/usr/local/git/bin:/usr/X11/bin
When you look at your version you won’t see ‘/Applications/apache-ant/bin:’. This is because you haven’t added it yet. To add to your PATH variable run this command.
export PATH=$PATH:/Applications/apache-ant/bin
This will add your new path to the end of the list. Be careful if you have installed the developer tools that come with OSX as they ship with a version of ANT. If this happens, the one defined first will take precedence. To change this, you can modify your command to prepend your new class variable to your path listing by modifying the command.
export PATH=/Applications/apache-ant/bin:$PATH
Check what version you are currently using this command.
which ant /Applications/apache-ant/bin/ant
Now you can run the ant command ant see some type of response.
ant Buildfile: build.xml does not exist! Build failed
This is good because it means everything is working correctly (we haven’t created a build yet).
Next, we need to modify a file that runs on startup, which will add this to our class path every time we reboot. To do so open .bash_profile with your favorite text editor. I use VI:
vi Users/yourusername/.bash_profile
Now add the export command to the .bash_profile file.
export PATH=/Applications/apache-ant/bin:$PATH
Now close out of your text editor. If you reboot you will see that you can run ANT without having to add it again to your class path.
Step Two: Get external JAR dependencies
Now that we have ant, we need to get the exernal libraries that will allow us to use FTP & SSH (SFTP). Go get the following:
jakarta-oro-2.0.8.jar – http://archive.apache.org/dist/jakarta/oro/
commons-net-2.2.jar – http://commons.apache.org/net/download_net.cgi
jsch-0-1-44.jar – http://www.jcraft.com/jsch/
Now that we have these, we need to add them to our ANT lib directory. If we have downloaded ANT, just drag these to /your-ant-directory/lib/. If you are using the ANT plugin, you can add these through the preferences in the IDE.
Flash-builder>preferences>ant>runtime>global entries>runtime>classpath>global entries>global entries>add external jars
That’s all you need to do to set up your system. Now we need to build some scripts to FTP.
Step Three:
Here is an example of how to implement these new features from within ant. If you are behind a firewall be sure to use “passive” mode on FTP and “trust” mode on SFTP.
What is an Accelerometer?
An accelerometer is a piece of hardware that measures the acceleration of forces. There are two types of forces that we care about; static and dynamic. You can think of static force as gravity which at all times is pulling us towards the center of the earth. We use static acceleration to figure out the angle an object is tilted. Dynamic acceleration is used for measuring the actual motion of an object. For this intro we’ll be talking mostly about tilt-based static acceleration.
Common uses
There are accelerometers all around us from our cars to our computers and phones. In cars they use accelerometer data to determine vibrations on the engine and in the airbag sensors. Companies also use accelerometers in hard-drives to protect data during collisions and general impact. Nintendo Wii shaped the future of motion gaming adding an accelerometer to their remote. Whenever you see a labyrinth style game or are playing a driving game by tilting your phone or tablet you can thank the accelerometer. As developers it’s our job to learn and interpret this information in order to improve the experience to our users.
How to handle local accelerometer on mobile device
When you are writing flash application that will handle local accelerometer updates from a phone or tablet the work flow is very simple. You check the to see if the device supports accelerometer using the flash.sensors.Accelerometer.isSupported() method. If it is supported you register a few event listeners, then handle the updates when they come in.
if (Accelerometer.isSupported) {
accelerometer = new Accelerometer();
accelerometer.addEventListener(AccelerometerEvent.UPDATE, accUpdateHandler);
}
private final function accUpdateHandler(event:AccelerometerEvent):void {
xSpeed -= event.accelerationX;
ySpeed += event.accelerationY;
}
How to handle accelerometer data from litl os remotes
When you are dealing with multiple remotes connected to a single application things get a bit more complicated because you need to pair remote updates with specific remotes, manage connections, and not mix it up in the meantime. This is an approach that works for us. It involves the creation of three classes by the developer.

LitlRemoteManager()
We will need to extend RemoteHandlerManager in order to inherit functionality. By doing this now we can override two important methods; onRemoteConnected and onRemoteDisconnected. You can do whatever you want inside these methods knowing that they’ll be called when a remote connects/disconnects.
You will need to instantiate after you are connected to the LitlService() as you will need to pass a reference to your service into it’s constructor. You will also need to instantiate a new RemoteFactory() in the constructor. This is what it looks like in our instantiation:
private function createRemoteManager():void {
remoteManager = new LitlRemoteManager(_service, new RemoteFactory());
}
RemoteFactory()
Implement IRemoteFactory(), return RemoteHandler() and you are all set. I usually set this up once and barely look at it again.
package service
{
import com.litl.helpers.richinput.remotehandler.IRemoteHandler;
import com.litl.helpers.richinput.remotehandler.IRemoteHandlerFactory;
public class RemoteFactory implements IRemoteHandlerFactory
{
public function RemoteFactory() {
}
public function createHandler():IRemoteHandler {
return new RemoteHandler();
}
public function get klass():Class {
return RemoteHandler;
}
}
}
RemoteHandler()
We have one job left to do and RemoteHandler() keeps it simple and to the point. This is where we define what to do when we get accelerometer updates. Start by extending AccelerometerEventHandler() and implement IRemoteHandler(). Next, override onAccelerometerEvent and handle your logic to handle accelerometer data. I usually loop through an array of remotes/players in my model and reference the remoteID property to match up remotes.
package service
{
import com.litl.helpers.richinput.remotehandler.AccelerometerRemoteHandler;
import com.litl.helpers.richinput.remotehandler.IRemoteHandler;
import com.litl.sdk.event.AccelerometerEvent;
public class RemoteHandler extends AccelerometerRemoteHandler implements IRemoteHandler
{
public var xSpeed:Number = 0;
public var ySpeed:Number = 0;
public function RemoteHandler() {
super();
}
override protected function onAccelerometerEvent(event:AccelerometerEvent):void {
xSpeed -= event.accelerationX;
ySpeed += event.accelerationY;
}
}
}
Wrapping up
As you can see there are not too many differences between the two workflows. Check back soon as we’ll be posting more advanced accelerometer development articles, tutorials, tips and tricks!
Again, screen cast coming!
I’m planning on turning these into a screencast ASAP.
Overscan is extra image area around the four edges of a video image that may not be seen reliably by the viewer. It exists because television sets in the 1930s through 1970s were highly variable in how the video image was framed within the cathode ray tube (CRT).
source: Wikipedia
Simply put, overscan is about 5% (this will vary depending on TV size/manufacturer) of your content that will be cropped when put on a tv screen. If you crop an image and blow it up to the original size, you would be overscanning. If you are familiar with print, this process is similar to “bleeding”. Consider the example below.

The reason overscan exists is because of older CRT TV’s where the tube couldn’t produce quality images on the edge of the tube. In order to effectively deal with poor quality on the edges of tubes, TV manufacturers made tubes larger and hid the part that was blurry behind the TV casing, essentially cropping a portion of the image.

Look at the black bar of meta-data at the top of the screen

Check out the green line on the left of the screen.
Okay, I know what you’re saying, “So what; who still uses CRT anyway? Why am I still being affected by this?”, but the short of it is that over the years broadcast companies have been using this “cropped” area to send meta information over analog signals. Also, since they expect it to be cropped, there is less time polishing the content available on the edges of the screen. This is the reason that even modern TV’s overscan.
We sure do! Now that you know all about overscan, know that we handle everything for you so you don’t need to actually do anything different! Continue to use liquid layouts (based off percentages) and set view & view sizes by listening for the ViewChangeEvent on your litl service. In that event you will find the full viewing area for your TV screen.
Check out this sample code.
ViewManager.as
package com.litl.overscan
{
import com.litl.sdk.enum.View;
import com.litl.sdk.message.InitializeMessage;
import com.litl.sdk.message.ViewChangeMessage;
import com.litl.sdk.service.LitlService;
import flash.display.Sprite;
import flash.utils.Dictionary;
public class LitlViewManager extends Sprite
{
private var _service:LitlService;
private var _currentViewState:String;
protected var _view:Sprite;
protected var controller:GameController = GameController.getInstance();
protected var currentView:ViewBase;
protected var views:Dictionary;
public function LitlViewManager(view:Sprite) {
_view = view;
views = new Dictionary();
}
protected function setView(e:ViewChangeMessage):void {
// Remove the current view from the display list.
if (currentView && contains(currentView)) {
removeChild(currentView);
}
if (views == null)
views = new Dictionary(false);
currentView = views[e.view] as ViewBase;
switch (e.view) {
default:
throw new Error("Unknown view state");
break;
case View.CHANNEL:
if (currentView == null)
currentView = new ChannelView(_service);
_currentViewState = View.CHANNEL;
break;
case View.FOCUS:
if (currentView == null)
currentView = new ChannelView(_service);
_currentViewState = View.CHANNEL;
break;
case View.CARD:
if (currentView == null)
currentView = new CardView();
_currentViewState = View.CARD;
break;
}
views[e.view] = currentView;
controller.currentView = currentView;
// IMPORTANT -- This is where we update the size of the display object
// based on the dimensions returned by our ViewChangeEvent
// NOTE -- If you extend ViewBase from our SDK rather than sprite, you will have
// access to the setSize() method
currentView.setSize(e.width, e.height);
if (!contains(currentView))
addChild(currentView);
}
public function set service(value:LitlService):void {
_service = value;
_service.addEventListener(ViewChangeMessage.VIEW_CHANGE, setView);
}
public function get currentViewState():String {
return _currentViewState;
}
}
}
ChannelView.as
package com.litl.marbelmayhem.views
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.events.Event;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
public class Scoreboard extends ViewBase
{
private var background:Sprite;
private var timeBG:Bitmap;
private var logo:Bitmap;
private var timeDisplay:TextField;
public function Scoreboard(e:ViewBase) {
super();
_view = e;
init();
}
private function init():void {
createChildren();
}
// NOTE -- This is where we instantiate our objects and add them to memory
private function createChildren():void {
background = new Sprite();
background.graphics.beginFill(0x333333);
background.graphics.drawRect(0, 0, 1280, 800 * .15);
addChild(background);
logo = gameAssets.logoBitmap;
logo.cacheAsBitmap = true;
addChild(logo);
timeBG = gameAssets.timeBGBitmap;
timeBG.cacheAsBitmap = true;
addChild(timeBG);
var timeFormat:TextFormat = new TextFormat();
timeFormat.font = "Calibri";
timeFormat.size = 34;
timeFormat.color = 0x000000;
timeDisplay = new TextField();
timeDisplay.autoSize = TextFieldAutoSize.LEFT;
timeDisplay.defaultTextFormat = timeFormat;
timeDisplay.setTextFormat(timeFormat);
addChild(timeDisplay);
}
// Note -- The sizeUpdated() is part of ViewBase and called when the setSize() is called.
// This means that whenever our size changes the objects on our stage will
// reset. Notice how they are set using percentages (get liquid baby!)
override protected function sizeUpdated():void {
logo.x = this.width * .10;
logo.y = (background.height / 2) - (logo.height / 2);
timeBG.x = (this.width / 2) - (timeBG.width / 2);
timeBG.y = (background.height / 2) - (timeBG.height / 2);
timeDisplay.x = (timeBG.x + (timeBG.width / 2)) - (timeDisplay.width / 2);
timeDisplay.y = (timeBG.y + (timeBG.height / 2)) - (timeBG.height / 2) + 5;
}
}
}
Be prepared to get your hands dirty on Thursday, 11/11 at 1:00 during the RIAUnleashed workshop. Kathryn Rotondo and Ryan Canulla will teach and guide you through the latest litl technology, including our updated Channel SDK, new AIR simulator and exciting Android-remote controlled Accelerometer features. We’ll hand out USB sticks with the latest litl bits and Chuck Freedman will be serving as Teaching assistant to help you during the workshop.
We are happy to announce that our special developer incentive program, which awards each developer that submits a channel both $500 and a free litl TV Companion device, will be extended to those attending the workshop.
Lastly, while those in attendance at the RIAunleashed workshop will get to bask in the brilliance of our presenters, we are streaming our workshop to our developer community via a LIVE webinar.
So, whether attending in person, or looking to get a limited seat for the LIVE webinar, please sign up here:
More details on the workshop:This lab is a great opportunity for developers interested in deploying Flash/Flex Channels on the litl platform. We’ll have a good portion of our team on hand to work directly with you, doing a live walk through of our devices, platform, FAQs and sample channel code. The sample channel code projects are ready to import into either Flash CS5 or FlashBuilder, so they’re ready-to-run. After introducing you to the devices, SDK and platform, we’ll help you code your own channels and set you up to deploy them in our Channel store!
As you know, the litl SDK come with some pretty handy controls that will assist in your development process by allowing you to focus on the task at hand, and not re-inventing the controls (I mean wheel). In this post, we’ll be discussing how you can create custom item renderers for use with controls like the SlideShow and FilmStrip. Both of these will take an array and scroll through the data. We’ll look at how we can customize that data to create unique views for your channel.
You can find the completed code for this tutorial at developer.litl.com under sample channels.
This value object will allow us to type our data to a specific object. Ours looks something like this.
package com.litl.itemrenderersample.vo
{
public class RendererDataObjectVO
{
public var title:String;
public var description:String;
public var address:String;
public var imageUrl:String;
}
}
This class will define what data will be presented to the user via our control, how it looks, where it is placed, and how it’s updated. You can name it whatever you like, and store it somewhere in your channel directory (I usually store it inside of a renderers directory).
This class must do two things:
package com.litl.itemrenderersample.renderers
{
import com.litl.control.ControlBase;
import com.litl.control.listclasses.IItemRenderer;
public class RestaurantItemRenderer extends ControlBase implements IItemRenderer
{
public function RestaurantItemRenderer() {
super();
}
}
}
This is where you create the objects for your custom item renderer. These objects should have some sort of data property that will change with each object in your renderers collection. Great examples of these items are TextFields, TextAreas, and Images.
override protected function createChildren():void {
mouseChildren = false;
background = new Sprite();
addChild(background);
title = new TextField();
format = new TextFormat("CorpoS", 36, 0xffffff, false);
format.align = TextFormatAlign.LEFT;
title.defaultTextFormat = format;
title.wordWrap = true;
title.multiline = true;
title.selectable = false;
title.antiAliasType = "advanced";
title.gridFitType = "pixel";
title.autoSize = TextFieldAutoSize.CENTER;
addChild(title);
description = new TextField();
var descriptionFormat:TextFormat = new TextFormat("CorpoS", 28, 0xffffff, false);
description.defaultTextFormat = descriptionFormat;
description.wordWrap = true;
description.multiline = true;
description.selectable = false;
description.antiAliasType = "advanced";
description.gridFitType = "pixels";
description.autoSize = TextFieldAutoSize.CENTER;
addChild(description);
address = new TextField();
address.defaultTextFormat = descriptionFormat;
address.wordWrap = true;
address.multiline = true;
address.selectable = false;
address.antiAliasType = "advanced";
address.gridFitType = "pixels";
address.autoSize = TextFieldAutoSize.CENTER;
addChild(address);
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageComplete, false, 0, true);
addChild(loader);
}
This is where you will change the data that is presented to the user for all of your renderers child objects. For example, this is where we set/update the text property for a TextField or where we load a new image based on a new URL.
override protected function updateProperties():void {
if (title != null)
title.text = (_data == null) ? "" : _data.title;
description.text = (_data == null) ? "" : _data.description;
address.text = (_data == null) ? "" : _data.address;
if (loader != null) {
loader.load(new URLRequest(_data.imageUrl));
}
}
This is where we position our objects on the stage. We check the _width && _height properties that we inherit from ControlBase.
override protected function layout():void {
if (_width > 0 && _height > 0) {
graphics.clear();
graphics.beginFill(0x0, 1);
graphics.lineStyle(1, 0xffffff, 1, true);
graphics.drawRect(0, 0, _width, _height);
graphics.endFill();
loader.x = 30;
loader.y = 30;
title.width = _width - 100;
title.y = loader.y + loader.height + 25;
title.x = 30;
description.width = _width - 10;
description.y = title.y + title.height;
description.x = 30;
address.width = _width - 100;
address.y = _height - 40;
address.x = 30;
}
}
This private variable will be typed to your value object that we created earlier.
private var _data:RendererDataObjectVO;
Create these however you want, but I like to right click on my _data var → Source → Create Getters/Setters.
The thing to note here is that we accept an Object in the set data method and type it to our Value Object.
public function get data():Object {
return _data;
}
public function set data(obj:Object):void {
var vo:RendererDataObjectVO = obj as RendererDataObjectVO;
_data = vo;
invalidateProperties();
}
These getters/setters are really just a formality at this point. Any modification would be beyond the scope of this simple tutorial.
What needs to be created:
public function set enabled(b:Boolean):void {
}
public function set selected(b:Boolean):void {
}
public function get selected():Boolean {
return false;
}
public function get isReady():Boolean {
return (loader.contentLoaderInfo.bytesLoaded == loader.contentLoaderInfo.bytesTotal);
}
This is the last step. Now you can create additional item renderer classes and change them at runtime! Try it out, have fun, and be sure to let us know if you have any questions!
slideshow = new Slideshow();
addChild(slideshow);
slideshow.itemRenderer = RestaurantItemRenderer;
slideshow.setSize(800, 600);
var item1:RendererDataObjectVO = new RendererDataObjectVO();
item1.title = "Thaitation";
item1.address = "39 Jersey St. Boston, MA";
item1.description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam at elit quis ligula tristique vulputate. Donec tempor imperdiet urna quis pellentesque. Phasellus eu arcu at tortor ultricies porta vel sed leo. Aenean tincidunt auctor risus, sit amet tempor lectus hendrerit id. Pellentesque dui nulla, vulputate nec egestas nec, porttitor non lectus.";
item1.imageUrl = "assets/thaitation.jpg";
var item2:RendererDataObjectVO = new RendererDataObjectVO();
item2.title = "Sonsie";
item2.address = "255 Newbury St. Boston, MA";
item2.description = "Sed leo enim, gravida vitae consequat quis, venenatis nec urna. Pellentesque erat lacus, posuere sit amet scelerisque eget, imperdiet quis tortor. Phasellus in purus eget urna imperdiet ullamcorper. Etiam mattis, libero ac interdum venenatis, est eros elementum ligula, euismod tincidunt nisl lorem id lacus.";
item2.imageUrl = "assets/sonsie.jpg";
slideshow.dataProvider = [ item1, item2 ];
Completed item renderer: