Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2008-433
$eventId
ID of event: wwdc2008
$eventContentId
ID of session without event part: 433
$eventShortId
Shortened ID of event: wwdc08
$year
Year of session: 2008
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2008] [Session 433] Building Na...

WWDC08 • Session 433

Building Native Look-and-Feel Web Applications Using SproutCore

Essentials • 58:10

SproutCore is an open source, platform-independent, Cocoa-inspired JavaScript framework for creating web applications that look and feel like Desktop applications. Learn how to combine SproutCore with HTML5's standard offline data storage technologies to deliver a first-class user experience and exceptional performance in your web application.

Speaker: Charles Jolley

Unlisted on Apple Developer site

Downloads from Apple

SD Video (626 MB)

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good morning. What's everybody doing? You all have coffee recovering from last night? I'm still recovering from last night. So this is Section 433. We're going to talk about building native look and feel web applications. And really, we're not going to talk very much today about building native looking applications because, right, that's pretty easy.

If you've ever used any kind of CSS, you know much about CSS, you can make your apps on the web look native. The hard thing is to create applications that feel like they're native applications, even though they're running in the web browser. So that's what we're going to really talk about today. My name is Charles Jolly.

I'm a software architect with the new MobileMe. For the last couple years, I've been working on, along with a big group of people at MobileMe, creating the web applications that you saw demoed in the keynote. So we're going to talk a little bit about how we actually did that.

And when we talk about creating native look and feel applications on the web-- what do we really mean? Well, what we're talking about doing is taking an application like this that looks fundamentally like a web page and seeing how we can make this look and feel more like this, right, iPhoto. What would it take if we wanted to create something like iPhoto on the web? Is it even possible? Well, it is.

And we're going to discuss how we do that in four sections today. We're going to talk about the architecture a little bit. And if you don't get anything else out of this talk today, the architecture section is really what-- I hope you'll walk away with the most. Because understanding how to structure these applications is really fundamental to making it possible to create something this great in the web browser.

Once you get your head around that, we'll talk about a framework we've been using for the last couple years to create these applications on the web. And then we'll actually build one of these applications. And then we'll talk a little bit about how you can go about deploying these. Because the actual deployment methods that you use to put this onto the server varies. significantly once you start dealing with this architecture.

So let's get started. So, architecture. What do we really mean when we're talking about building a native look-and-feel application? How does that differ from a desktop or from a typical web application that you might see today? Well, I think it really comes in three pieces, right? First is we expect an immediate response.

When you click on something, it should highlight. When you edit some text, it should be changed. When you drag something to a folder, it should be moved. You shouldn't have to wait on server round trips very often. As much as possible, you want the user to immediately see the change that they've just made. The second thing is we want, and really connected with that first bit, is a rich interaction experience.

You know, when the Mac first came out,

[Transcript missing]

So, how does this compare? Well, obviously everything's happening in the browser. You can almost always give an immediate response. You rarely have to wait on a server round trip. You can implement really rich, dynamic, interactive experiences. You can give the user back the direct manipulation that we lost with the web. And, of course, you can implement client-side storage extremely easily, and you can have this complete offline mode capable, depending on how you built your applications. So that's the web client server architecture.

[Transcript missing]

So, before we get to SproutCore, let's just compare this with the current state of the art. Now, Flickr is an extremely advanced AJAX application, 3270 style. So, I'm on my page here with a couple of sets. Let's say I want to come in here and change this name. Well, how do I do that? Well, I can click on Edit, and I have to go into another page, and then this happened in 2006, so I want to add that.

Well, that didn't actually change it. If I come back here, oh, well, I guess I actually have to tell the server to do it. So, I wait. Okay, I changed. So, not bad, but still, everything interesting is happening in the web browser, right? So, what happens if I want to, say, create a new set and maybe move a few of these photos from a party we went to to another page? Well, first thing I have to do is come back here, and actually, let's see here.

Come here to Sets. I click Create a New Set. Go to My New Set. Now they do have some drag and drop, which is great. That's something that Flickr is known for, their advanced API. Of course, I can't directly manipulate the data in my other set, because these are basically happening in the web server, so what I have to do is, down here they show me all of my photos, and I have about 200 of them on here. So I'm going to have to slide through here until I can find the photos that I want. They do have multiple select, which is nice. And that goes ahead and adds some of them. Just drag that last one up there. OK.

call this the big party. Of course this hasn't actually changed anything. If I come back here to sets, again it will make me cancel that. So I'm going to go ahead and save that. Now wait on the server. And there we go again. So not bad, it's a fairly fluid experience.

But we're still looking at this, you know, fundamentally everything is happening in the Web server and most of the time I'm just looking at a representation of my data. So what could we do if we built this with SproutCore? Well, I'm going to show you this is just a little demo we built. This is available on the SproutCore website. And this is Photos. So Photos has, you know, a bunch of albums here. These are just loading from the server.

Here's a few big ones. You can see this one has actually 150 photos. And SproutCore has incremental rendering built in, which is the same thing Cocoa uses so you can draw a large amount of sets. We actually have done tests with this. I've had 5,000 photos loading here and it loads in about five seconds. So that's actually faster than iPhoto was a couple years ago. So let's say we wanted to -- well, we were going to do a couple things. Let's say I wanted to rename this to -- looks like I've got a selection bug there.

Ignore the man behind the curtain. So we'll just see what does it take to actually change this to Canes 2006. Well, I just click on it, type 2006 and hit return. Done. So we're going to go ahead and do a little bit of a test. So we're going to go ahead and do a little bit of a test. So we're going to go ahead and do a little bit of a test. Maybe I want to select a couple, well actually let's go ahead and add a new set. Just come down here, I'll create a new set, call it the big party.

We need to add a couple things to this. So I can select these, I can command select them, I can shift select, I can, whoop, hold the wrong key, I can shift select them if I want to. Of course, I can also use keyboard control. So it's all very natural, and if I want to add it, I just go, that's it. I just added them. Didn't have to wait on anything.

So, of course, that makes using this app is way faster. I mean, you're never waiting on the server. You wouldn't even know that this was happening in the server. In fact, a lot of what's going on in the background here, this can be communicating with the server to update your photos. It's also actually writing these changes to local storage if you're in the right version of Safari, just as you go. So you never have to wait on any of it.

And, of course, we can do a lot more with this, right? We can have a slider. Isn't that nice? It's really interactive. Works pretty well if you have a large number of photos even, even though... And, by the way, I've spent like a day on this guy. So if you really want to be impressed, buy MobileMe in a few weeks.

So, and, you know, the other thing I mentioned was Safari has some really cool effects that they're doing. And so why don't we come over here and let's just see if we go ahead and add it. And, um, If we go ahead and I'm just going to show all these photos and we're going to do select all.

Okay, so what can we do with this? Well, here's a little editor I've done. Just a few things. One thing you'll notice is the titles are automatically selected and joined here because we're using bindings. It just noticed that we have multiple ones. So if I just instead select one here, I can actually edit it and say this guy was in Prague. That's all I have to do. It's done now. But let's do some more interesting things.

So the new Safari--

[Transcript missing]

So, just pretend that didn't happen. So what happens if, let's say we want to, Let's say we wanted to reorder these guys over here. Now, there was actually no really obvious way to do that in Flickr. Here, it's really easy. You just grab it and drag it around. That's all you have to do.

I can actually do the same thing with my photo library. I can just select a couple of these guys, and let's say I want to move them down. You can see the little highlighter. And we've actually implemented scrolling as you hit these edges, which, believe it or not, is extremely complicated in the web. And we just let go, and it drops them. I'll show you, move these up so it's a little easier to tell.

Okay, so it's even awesomer in WebKit, so let me show you WebKit really quick. Notice how fast this is loading. Just keep that in mind. Stuff that in your back pocket for a little later. Okay, so let's go ahead. I'm gonna create the big party. Since we're running in a different browser now. And I'm just going to grab a couple of these photos so you can kind of see this.

Okay, so as I was saying before, I'm going to get these a little bigger so you can see this. So one of the cool things we have in WebKit is this thing called CSS rotation, which lets you rotate photos. So what happens if we can actually rotate photos in the web, right? It's pretty amazing.

But that's not the cool part. The cool part is that this is data living in the client, okay? So what I did here was I have a slider that is bound to the rotation property on a controller that's managing all three, all of these photos. And these photos actually live in some other albums. Remember, I just pulled them over from the other albums. So you see they're already rotated there too.

So, everything's pretty much handled for you. So, that's the demo. Now, something I want to point out about this, you saw how fast this was loading and everything. So, you know, we got a little bit of press with SproutCore on Monday. It was mentioned on some websites after the MobileMe thing. And so, this is running on the public SproutCore site.

And this site currently is hitting about, it's getting 5,000 to 6,000 hits a day, which is pretty high compared to what it's normally been getting, considering that it's running on a 995 shared plan from DreamHost. And so that performance is happening on a shared plan on DreamHost, which is huge, right?

Imagine what you can get. I'll give you an example. I launched a web company a couple years ago. We got on TechCrunch. That's how we got mentioned here. We got on TechCrunch with my previous company, and we had a server, you know, very best server we could get.

It was hot off the presses. It was running custom software up and down, and that mention on TechCrunch nearly brought us to our knees, right? This guy is running on a shared plan, and it's running smoothly because everything's happening in the web browser, and it's so efficient at being able to spread out the load across all of your clients.

So you get not only some really great features, but even a little more difficult to appreciate incredible amounts of distribution of your application load, which just, you know, it does wonders for easing those sleepless nights when you just put your product out on the market. So there you go. So that's our demo for now.

[Transcript missing]

So let's look inside the actual application. Now, there's a couple things you want to see. If you're, you know, model view controller world, you'll see three very familiar folders. You put your controllers and models and views in those folders. You can actually put them anywhere you want, and the system will take care of it. This just makes it easier. You have a file called core.js where you define your namespace. SproutCore helps you namespace everything so you can have multiple modules loaded at one time, and it will all work. You also have a main function where your main function goes.

And there are a few other things. This is the English lproj. If you've done Cocoa development, you recognize that lproj. SproutCore has built-in support for localization. So you can put your HTML, any images you want, any CSS. If you have localized JavaScript, in this example, we have a strings.js. You drop them into this English lproj.

If you want to do a French localization, you create a directory called French lproj, and you just add whatever resources you want. You can also create a string.js for example. You can localize your strings. You can localize in any language. SproutCore has built-in support for these four, but if you wanted to do anything else, you just use the two-letter language code lproj. SproutCore will automatically build and deploy it for you. So MobileMe is localized because we're Apple and we have to do that.

So we're using this system automatically. So it's a really, really nice way to handle localization, which is generally pretty difficult. We also have a couple extra little features. One of them is fixture data. SproutCore actually supports fixtures. You can load fake model data in here, like photos, for example.

When I first wrote this app and I didn't want to pull it from the server just yet, I just write up my fake photo JSON feed and I drop it into fixtures. And when I'm in development mode, it's automatically loaded and installed. So you can work in fixtures without having any server mode.

You also have unit testing built right in, which is huge because JavaScript is extremely difficult to unit test unless you're writing in SproutCore and then it's easy. . . And now my colleague Peter is going to come up, Peter Bergstrom, and show you how to build one of these.

All right, so we're going to build the temperature converter application that Charles just went over a little bit. So the first thing we're going to do is bring up Terminal and use the SproutCore build tools to create our converter application. So this just builds the skeleton of the application actually.

And this looks familiar from the slides. And this is what we're going to modify. So let's go into the converter application and start SEServer. So here we can take a look at what it builds. This is just the generic page that we start with, but let's actually make this do something. So we go into the body.rhtml here, and we're going to change this to font size. Let's see how we do that. Command plus.

Is that better? All right. OK. So let's do this. I'm just going to drop this in here. So now we have some HTML. And we use the Ruby helpers here to create a text field. It's going to be a text field view. And we're going to name this one Celsius.

We can give it a hint. So that'll just be ghost text that will show up in the text field. So, I'm going to go ahead and add a new name here for Fahrenheit. I'm going to drop in some CSS as well. There it is. Adding 20 pixels. Add a border.

So we'll refresh this. And now you can see here that we have ghost text. When we actually focus into the field, it'll change. And I noticed that I didn't change this. There we go. The next thing we want to do is actually create a controller so we can put our application logic in there. So I'm going to go back in here. We do SCGen to build the controller. It's going to be a controller.

We're going to call So this actually will create a controllers directory and a test directory. We'll get back to a unit test later. But the first thing we want to do is add some values here in the controller, one for F value, which is going to be the Fahrenheit value, and one for So, we can go back to our text field here and create a binding. So, the binding will allow us to bind the value of the text field to the one in the controller. So, if we do a change to the controller, it will update automatically and the other way around as well.

Fahrenheit value. There. So now you see that it says 2 and 32. Those are the values we put in the controller. I'm going to bring up the error console, and you can see here that we can actually To set the value of, for example, the C value to 300,

[Transcript missing]

We want to actually get a notification so it actually won't change.

So we need to use set to actually let everyone who is listening to the value that it's changed. So let's go back to the-- So, we're going to create two functions here, one to convert from Celsius to Fahrenheit and one to convert the other way. So, the first one is going to be convert C to F. And this is actually going to be a function that observes the value. So when we change the value in the text field, this function will be automatically executed. So we're going to do observes cvalue. So we're going to get the value.

Let's do our conversion. Here, so it's going to be 9/5 plus 32. And we're going to get the original Fahrenheit value. And since it's a floating point number, we want to make-- we can't just do a direct comparison and see if it's actually changed. So we're going to do math absolute rig minus converted. So just see if it's changed. And if it has changed enough, we're going to set the F value here to the converted value. And I'm just going to drop in the other function here.

So we should be able to now change the value here. So as I'm typing, the Fahrenheit value So now we actually have a working converter, but we don't really know if it works right. So let's build some unit tests. So when I created the controller, we actually also had a kind of a basic unit test created for us. So let's do some modifications here. So it should convert Celsius to Fahrenheit.

So I'm going to set the value of the Celsius value. To something we know, 100. And then we can do converter, convert, controller. Get the Fahrenheit value, because it's already supposedly changed, and we can do should equal And now we can bring this up in the unit test suite. And you see that our test passed.

So we can actually -- Another thing that's really great is that we can turn on continuous integration. So, this will run now in the background, and I can just leave this minimized and create another test here. So, I'm going to grab this one. Save it. And whoops, I actually did something wrong here. So I actually caused a unit test to fail because I tried to set it to 100 degrees Fahrenheit. That's not 212 degrees Celsius. So it actually is 37.7. So that failed. So let's fix this. And now it shows that both of them have passed.

[Transcript missing]

So that's how you build a SproutCore application. There's another little feature that you can find actually documentation on the website. We have built-in documentation generation. So if you saw in some of the code there, there were some comments that said, you know, place your documentation here. You can put that in there and then just visit, just like there is a built-in test runner, there's also a built-in documentation viewer that comes with every application.

You don't have to do anything. You just add documents.

[Transcript missing]

So building this before was really difficult, but since Charles has done a lot of work on the build tools, it's been a lot simpler, more simple. It's a lot more simple now. So now we just do scbuild.

converter, and we want to put some options here. So R will make it only build the required things like SproutCore and Prototype as well as the Converter app. And we'll make this verbose so we can see what's going on. So it'll build Prototype, SproutCore, collect all the images, and also our little very small app, compared to everything else. So it creates it in the temp directory. So let's go inside there. And just open that up.

So these are the things that are created. The converter application and the prototype and SproutCore. So inside of here, you can actually see that our index.html here, the text fields or text field views that we did in Ruby have now turned into input fields. And here are the bindings and the hints that we specified for it. So basically, all the things that we do inside of the RHTML with the Ruby help will actually be automatically converted into JavaScript for us. So we don't actually have to do anything with it.

And here's our minified code. It's not very large. And you can actually just go in here. And this is what SproutCore looks like, minified as well. Now what we want to do is take this and drop this into our web server. So, we have a little bit of a break here, and we can just go to this. To local host, converter, or static convert, oh, autocompleted.

So this is our wonderful deployed app. And it just works the same way as the one that we ran in the build environment, but this is a lot faster to load because we don't have to generate any of the JavaScript or the files in real time like we do in the build environment or in the development environment. So thank you.

[Transcript missing]