Building a data-driven image carousel with Sencha Touch 2

This evening I embarked on a little stellar voyage that I’d like to share with you all. Most people with great taste love astronomy and Sencha Touch 2, so why not combine them in a fun evening’s web app building?

NASA has been running a small site called APOD (Astronomy Picture Of the Day) for a long time now, as you can probably tell by the awesome web design of that page. Despite its 1998-era styling, this site incorporates some pretty stunning images of the universe and is begging for a mobile app interpretation.

We’re not going to go crazy, in fact this whole thing only took about an hour to create, but hopefully it’s a useful look at how to put something like this together. In this case, we’re just going to write a quick app that pulls down the last 20 pictures and shows them in a carousel with an optional title.

Here’s what it looks like live. You’ll need a webkit browser (Chrome or Safari) to see this, alternatively load up http://code.edspencer.net/apod on a phone or tablet device:

The full source code for the app is up on github, and we’ll go through it bit by bit below.

The App

Our app consists of 5 files:

index.html, which includes our JavaScript files and a little CSS
app.js, which boots our application up
app/model/Picture.js, which represents a single APOD picture
app/view/Picture.js, which shows a picture on the page
app/store/Pictures.js, which fetches the pictures from the APOD RSS feed

The whole thing is up on github and you can see a live demo at http://code.edspencer.net/apod. To see what it’s doing tap that link on your phone or tablet, and to really feel it add it to your homescreen to get rid of that browser chrome.

The Code

Most of the action happens in app.js, which for your enjoyment is more documentation than code. Here’s the gist of it:

This is pretty simple stuff and you can probably just follow the comments to see what’s going on. Basically though the app.js is responsible for launching our application, creating the Carousel and info Components, and setting up a couple of convenient event listeners.

We also had a few other files:

Picture Model

Found in app/model/Picture.js, our model is mostly just a list of fields sent back in the RSS feed. There is one that’s somewhat more complicated than the rest though – the ‘image’ field. Ideally, the RSS feed would have sent back the url of the image in a separate field and we could just pull it out like any other, but alas it is embedded inside the main content.

To get around this, we just specify a convert function that grabs the content field, finds the first image url inside of it and pulls it out. To make sure it looks good on any device we also pass it through Sencha IO src, which resizes the image to fit the screen size of whatever device we happen to be viewing it on:

Pictures Store

Our Store is even simpler than our Model. All it does is load the APOD RSS feed over JSON-P (via Google’s RSS Feed API) and decode the data with a very simple JSON Reader. This automatically pulls down the images and runs them through our Model’s convert function:

Tying it all together

Our app.js loads our Model and Store, plus a really simple Picture view that is basically just an Ext.Img. All it does then is render the Carousel and Info Component to the screen and tie up a couple of listeners.

In case you weren’t paying attention before, the info component is just an Ext.Component that we rendered up in app.js as a place to render the title of the image you’re currently looking at. When you swipe between items in the carousel the activeitemchange event is fired, which we listen to near the top of app.js. All our activeitemchange listener does is update the HTML of the info component to the title of the image we just swiped to.

But what about the info component itself? Well at the bottom of app.js we added a tap listener on Ext.Viewport that hides or shows the info Component whenever you tap anywhere on the screen (except if you tap on the Carousel indicator icons). With a little CSS transition loveliness we get a nice fade in/out transition when we tap the screen to reveal the image title. Here’s that tap listener again:

The End of the Beginning

This was a really simple app that shows how easy it is to put these things together with Sencha Touch 2. Like with most stories though there’s more to come so keep an eye out for parts 2 and 3 of this intergalactic adventure.

37 Responses to Building a data-driven image carousel with Sencha Touch 2

  1. mz says:

    Could you please show an example on how to create an image grid using Sencha Touch 2? I was able to use dataview with tpl in Sencha touch 1 to do this. But it seems broken with Sencha Touch2 with itemTpl? I can only get one image per line, not multiple images a line.
    Thanks!

  2. Ed Spencer says:

    @mz that’s mostly just down to CSS, but is on my list of things to create

  3. @mz I created a barebones example doing just that a few days ago: http://rdougan.github.com/barebones-tiled-dataview/

  4. mz says:

    Thanks Robert! That’s exactly what I need.

  5. mz says:

    One more question: with old DataView I can use tpl to control how I arrange items with for loop, xindex and xcount. For example, I can control to show only three items on each row. How do I do this in the new DataView?

  6. raghav says:

    All the code is written in the ” launch() “. Is there any other placce where we can place the code. Like some listener that runs before the view is loaded.

  7. raghav11 says:

    All the code is written in the ” launch() “. Is there any other placce where we can place the code. Like some listener that runs before the view is loaded.

  8. Ed Spencer says:

    @raghav11 the view is actually constructed inside that launch function so you can place any code you like before that

  9. raghav11 says:

    Hi Ed , Thanks a lot for your reply . This blog helped a lot . But instead of writing the code inside launch . I want to write it inside the controller . Can I do that , or is launch the only place.

  10. raghav11 says:

    I want the carousel inside a navigation view . Currently we are directly adding it the viewport . I want to add that to a navigation view and the add to the viewport . How to achieve that .

  11. JHay says:

    I like your example, but it doesn’t appear to be working anymore. Did NASA change the feed?

  12. efe says:

    hello ed,

    this seems doesnt working right now. did the rss feed changed or it is totally something different.

    I get the error as
    “TypeError: ‘null’ is not an object (evaluating ‘b[1]’)” in app-all.js:4

  13. Sven says:

    @efe I’ve created a fix for it here: https://github.com/svendahlstrand/APOD/commit/75824eccc5a4d702728f3395589e7cb9d57b7fe0. Feel free to fork my repository or patch it yourself. The bug appears when there’s no image tag to parse: e.g. when a todays “picture” is a Flash file.

  14. Ed Spencer says:

    Thanks guys (Sven especially), it should be working again now. I’ll update it soon with the next exciting chapter 😉

  15. Francis says:

    Nice app!

    In the documentation, ‘store:’ is not a config option for Carousel…it is an error in the doc?!

  16. RO says:

    Hi, I’m wondering if

    1) line 33 in app.js should be store: Ext.getStore(‘Pictures’),
    2) line 67 in app.js should be carousel.getStore().load(function(pictures) { ….

    Thanks in advance.

  17. bclover says:

    Why are you assigning the ‘Pictures’ store to the Carousel and then later on manually setting the items? Do you even need to specify a store if you’re manually looping thru the store and setting the items?

  18. Ed Spencer says:

    @bclover that will become clear in part 2 🙂

  19. Thanks Ed, it took me a few hours to work out what I needed to do to set up my own dynamic carousel! I realized I had to change the sources to app.js and sencha-touch-debug.js to get it working, but I’m getting there.

    Is there a way to autoplay the carousel?

  20. Si says:

    Thanks a lot Ed, I am gradually understanding more and more with this framework thank to these little examples. I’ad had lots of success using snippets of code here and there for a multi item carousel per page in sencha touch 1, but am struggling a little bit to implement it in MVC for v2. The Data View example by robert is great, but doesn’t have paging in the same way.

    I think I have all the correct bits of code to enable it, but MVC confuses me where I should put the push code to push multiple thumbnails onto 1 page of a carousel (like in the .Net magazine tutorial for iPad app, Just One More). Not sure if the push code should go in the View or the controller?

    🙂

  21. Edmund says:

    I don’t understand how to make it work only with this code and without using app-all.js.

  22. Mahesh says:

    Hello Ed,
    Cant we reduce the code written in app.js and move it to view, I want to keep my app.js file as minimal as possible.

  23. Stephen Mattison says:

    Hey Ed, any thoughts on the Infinite carousel? When will that be available? Ive attempted to build such things in the past and always run into problems with scroll performance when swapping out large images. Have you guys found a way to solve that? Thanks!

  24. Rhonnel says:

    Hi Ed. Thanks for posting this blog. but im having trouble displaying the title. Actually it is not showing i download the source code in github and run it in xcode using phonegap 1.8 and build it in ios 5.0 ,. i test it in iphone and in the browser but both did not show the title., but the carrossel is OK. Only the title that is not showing.

  25. Rhonnel says:

    Hi Ed, i got the title work. But my problem now is i want to put the carousel inside the panel or a container or call it in a tab panel.. how to do that in that kind of structure?

  26. ddev says:

    Hello Ed,

    First off, thank you so much for this tutorial. I have been using it with great success as a learning tool for Sencha 2.

    I am coming up short in my google searches for some functionality I am trying to implement with this. I currently have a picker that filters the store. My question is, how do I refresh/update the carousel to reflect the filtered store items?

    thank you for your time!

  27. Rui Baiao says:

    Hello!

    I’m testing out the app and it seems that the pre-defined main app.js file in the index.html configuration is the app-all.js file. I changed it to the app.js and the app is not working anymore. Here is my index.html (without the css configs):

    Touch APOD

    (…styles…)

  28. Rui Baiao says:

    Hello!

    I’m testing out the app and it seems that the pre-defined main app.js file in the index.html configuration is the app-all.js file. I changed it to the app.js and the app is not working anymore. Here is my index.html (without the css configs):

    //
    //
    // Touch APOD

    //
    //
    //
    //
    //

    //the rest..

    any ideas?

    Thank you in advance

    Rui

  29. Rui Baiao says:

    I can’t seem to be able to paste the html code, but anyway i don’t understand why the app is not configured to run the app.js by default. Can someone clarify? I’m pretty new to extjs by the way

    Thank you

  30. ddmore says:

    Thank you for this tutorial. At this point I’m disappointed and frustrated about learning Sensa Touch 2. Although I only started to learn it a week ago, I find it very difficult to grasp beyond the very basic and obvious.

    I covered all part of the tutorial descriptions, help, examples, etc. Watched videos, tried and played with some basic apps. Aside from constructing a carousel, or dataview, list, etc, it’s very difficult to move beyond it due to lack of basic tutorials. I really wish someone would come out with a book on the subject.

    As an example, one of the items frustrates me about this tutorial is in the /view/Picture.js file on line 15. There’s a function called “updatePicture”. What is that? Where is that came from? When is it called? Who calls it? I don’t find ANY documentation on a function called “updatePicture”. The Ext.Img class only has an “updatedata” event listed.

    Is that function was generated from the config member “picture”? Hence “update” + name of member (picture) = “updatePicture”? If so, I don’t see where is it being called. On an update event? Whose update event? The carousel?

    See, there’s a ton of question just about that single function. And small incidents like this take HOURS to figure out. It’s really insane. It’s easy to say “simple” for someone who is a Sencha architect, but maybe you are not looking at things from a Sencha beginner’s point of view. I understand that many people had this and that experience with various other frameworks, such as Ext JS or even Sencha View 1.0 and as such, it’s much easier for them.

    I have some jQuery backgorund and originally wanted to use jQ mobile, but I find it’s still in it’s infancy compared to Sensa Touch. However, the learning curve involved in ST 2…I just don’t know if it’s worth the time. At least not in this point and time. Maybe if a book or two is out on the subject that caters for beginners and explain things from the ground up. Maybe.

  31. p_douhat says:

    I thank the author for the article, however:
    1) How about writing an article that actually uses mvc if that’s the preferred way to construct sencha touch 2 apps?
    2) @ddmore nailed it.. and the author pompously used the word ‘simple’ 5 times in this article (not including his comments in code). I think Sencha just wants you to buy support/training.

  32. Susan says:

    Very good tutorial, thanks :=)

    I’m new to sencha and I wonder if I could have a carousel that displays 2 items at once..

    Any help would be greatly appreaciate

  33. R green says:

    Thanks for this.
    Could an html5 video tag be used in place of an image as you have used ?

  34. Jeffyt says:

    Would love to see how to implement within Sencha Architect. I understand that I can plop most of the code in the app.js (application) but is there a way to smooth this into Architect?

  35. Faozul Azim says:

    I am beginner in sencha touch 2 and I have a query to ask if you please…..how about i try to do this in a controller rather than the app.js? how it would be? I have tried to do this by copying everything between launch event and creates a launch event in my controller and pasted all. but i only get the first image’s name and nothing else, but if i look into the network of the browser, i can see that all images are load successfully.

  36. Shasha says:

    Hello Ed,
    thank you for this tutorial and your code.
    I could run your example and it works fine.

    But when I combined it with my model and store (they already work fine with List and tap…..), I could get the title but have problem with the image.

    I got the 403 (forbidden) error and saw that the path is wrong:

    GET http://localhost/abc/%3Cimg%20typeof=%22foaf:Image%22%20src=%22http://……..”correct pad”

    when I call the jsonp in browser I see [{“node_title”:”article 5″,”nid”:”11″,”field_image”:”<img typeof=\"foaf:Image\" src=\"http://h…..

    Ed, does it mean I had also convert/clean the field_image in the model? -how?
    why when I use the model, store in List, itemTpl …{field_image}…. I get the right image in my List?

    Thank you in advance!
    S.

  37. Shasha says:

    Hello Ed,

    Thank you for your blog and the code. It works fine.

    But when I connect to my store, model (work already with List view, itemtap….) I just get the title and not the images.
    The 403 forbidden error I get, I could see is that images have a wrong path.
    localhost/…/ typeof=”foaf:Image” … (I am working with drupal)

    Do I need to convert the image in my model aslo? how?

    Why I get the correct image/images (and no problem) when I use it in Listview?

    Thank you im advance!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: