Antoine Quint: I'm one of the software engineers working on iAd JS and we're all part of the iOS Apps and Framework team and this is part 2 of our session on creating content with iAd JS and we're going to focus only on the iAd JS Framework today.
Dean did a very good job at covering how you actually build ad content structure and all that.
We're really refocusing on the development and technologies here.
So there are 4 things we're going to talk about.
First, I want to share a little bit, what our motivations and objectives were when we're building iAd JS.
Then we'll discuss the most important parts, which is how you deal with using controls, the things that you actually show on display and interact with.
And we'll wrap up and extend what Dean was talking about in the first part and go in depth about view controllers.
How they work, their lifecycle and what value they provide to your ad.
It is important if you're here that you know and understand the roles and the features of the various web technologies we'll be discussing today.
It also helps if you have familiarity with UIKit.
In fact, if you're a native app developer, I think this talk will be very good for you as well.
You'll be able to pick up on the web programming part of it.
So let's talk about what we did with iAd JS.
We sort of looked at iAd and instantly we knew that what we need to provide is a way to convey great emotion through the ad for the advertisers and also which you engage with the interactivity with the brand contents that the user can really interact with the ad.
And we try to translate that in terms of technology to know what we need to address.
And I think we came up with 4 distinctive areas.
The first one is media playback and that's really important for the emotion.
A great video will convey so much emotion, which is maybe hard to convey in machine code.
Then the advertisers probably are showing off a strong brand and these come with you know rich graphics.
They want to have the full extent of what they can do in Photoshop, stuff like that and translate that into their ad.
And to really bring a little bit more of emotion to that, we want to add motion to those graphics.
That's I think really key and that makes the graphics become just another form of media within your page along with audio and video.
And finally, for interactivity, because we're on iPhone, the key to the iPhone experience, what makes it stand out among all other computer products is the multi-touch interface and how fast a response it is.
So these are the 4 components that we identify that the core features or the core things we're trying to do with iAd JS.
And to me, if I was trying to summarize that with a single well, two words, it will be Rich Media.
This is the 4 components for a rich media experience.
In a rich media experience translates in term of technology to HTML5.
The HTML is kind of a buzzword now.
HTML5 has features and et cetera, but it's really just a set of technologies that we've talked about nowadays.
And all these technologies are key features in WebKit on iPhone.
So for example, HTML5 provides audio and video.
The slides you integrate media in your web page just along with any kind of web content.
First class citizens doing webpage.
Of course we have CSS3 and they've been some great talks this week by some of our colleagues discussing CSS effects using gradients, reflections, masks, et cetera, but I think 3 core CSS3 technologies that are worth highlighting are first, Transforms, lets you transform any part of your web page both in 2D and 3D to re-bring dramatic effects on top of your rich graphics.
And I think Transforms ties in fantastically with Transitions, which lets you go from one state to the other with a nice implicit animation.
You're just saying, here's my start value, here's my end value, just do something pretty.
And when you combine this with 3D effects and I think Dean showed some interesting demos of that in the first session, you really are building tremendous experiences.
There should be a little bit more control over your transitions.
You need special key frames in the middle of the animation.
When you can use CSS animations, we'll give you the full control over the animation that's being performed for you by WebKit.
And as far as interactivity is concerned, I said so, what really matters is multi-touch.
And WebKit on iPhone provides multi-touch events.
They're just special DOM events.
Just like you would deal with mouse on the desktop, you can deal with multi-touch directly on your phone.
But what makes these technologies stand out specifically on iPhone is how well they are integrated into the hardware so that we have tremendous performance and we fully integrate with GPU acceleration.
That means you can use all of these features and get incredible performance from something that just fits in the palm of your hand.
And I think that really amazes me still today.
So that's HTML5, the core of our rich media experience on iPhone.
But I've used the term rich media but it's just, you know one it's kind of a straw man.
It's just one term we can use to characterize what we're trying to do with ads in iAd.
But if you're a native ad developer, you're probably looking at this and thinking, these are more like mini applications, mini apps.
And if you're thinking of apps, you're not really thinking about HTML5 primarily maybe.
You're thinking maybe more about Cocoa Touch.
You're thinking about UIKit.
You're thinking about table views, scrolling components, really rich dynamic user interfaces that come built-in where you have little code to write.
And that's exactly what we're trying to do with iAd JS.
We're trying to combine rich media and mini apps or rather HTML5 and UIKit into one seamless integration.
So that's what we're trying to do with iAd JS.
The first thing we really want is to make it so easy for you to write these really rich ads.
We want to streamline the creation of those rich ads and that's the core value of iAd JS, is make things a lot simpler for you.
The second thing we want is to ensure that we code the best practices so that we leverage as much of the high performance that WebKit on iPhone provides, this hardware acceleration.
You don't really have to know all that much about how it works to get the most performance by using iAd JS.
So some of the core features we baked into the framework we're going to go in depth about this is first, for the user experience, it's key that we have a design that's as close to what we do in native code.
And because we're in the web technologies world, it's HTML5, it's CSS.
That's not really an imperative programming model.
This is declarative.
You're just really writing out things that should happen but you're not really writing code as such.
We want to combine that with the UIKit foundation, which is something that's pretty novel.
And finally, those as we're building a recombination of strains, they're little modules.
So we want to make that modular architecture is at the core of iAd JS so that we can put things together incrementally when we put things on display and we'll get back to that much later in this talk when we deal with view controllers.
And how we did that is by using the same technologies you'll be using when altering content 100 percent web standards.
We haven't used a single line of native code to provide all this functionality to you.
In fact, any of you if you had time and willingness, you can actually write this all yourself.
All open standards, all documented, all for you, so we're dealing at the same level as you are so we know that this is the best integration we can provide inside of web content.
So that is my introduction to iAd JS.
And I want to talk about two things, ADClass and ADObject.
I think their port type or this port type concept of programming is fantastic.
It's so rich and dynamic.
You can insert code.
It's just completely amazing.
It's so flexible.
But it has some limitations.
They're more at the syntax level.
Things you'd want to do a bit easier and these things are for example inheritance.
What I mean by that is there's no clear relationship between a class or a superclass.
And there's no super keyword like you would have in Objective-C so you can get to the superclasses implementation of a method.
So that's another area that we'd like to target.
And finally to combine with the property synthesis, there's another great mechanism in Objective-C, which lets you it's called key value coding, which lets you run callbacks based on when it probably changes on another object.
You have to do a bit more.
So we want to address those 3 areas with iAd JS.
And the way we do that is with a load of syntactic shooter.
The first thing you've got to know about is the ADClass Utility.
You might have seen this being used on some of Dean's slide and what it lets you do is to process your class and just make sure the syntactic shooter that we add is actually interpreted and applied to your class in a background magically.
So first thing, for example, you want to do set up inheritance.
Well, inheritance should just be saying, I'm extending this class.
That's all there is to it.
Do whatever it takes to make it happen.
Well, we can do that with superclass property and we'll see about that in a minute.
Same goes for synthesis.
You can just say, here are a list of properties I want to synthesize, they're in array, just make whatever it needs to be done so that they bind to some methods in the background.
And to complement this ADClass Utility, we have a foundation ADObject Class that most if not all of the iAd JS objects extend that tie into ADClass Utility.
For example, what's the point of having inheritance if we don't have a callSuper method.
So we provide that directly in ADObject.
The same goes with synthesized properties.
It'd be great to have notifications happen automatically when you actually update a synthesized property so you can be notified when that property changes.
That's completely automated with synthesis.
Of course, we have APIs for you to do that manually as well but as you opt into synthesis, the notifications happen magically for you in the background.
You don't have to worry about it.
So let's take a concrete example.
Here, I'm creating MyClass.
It's pretty standard code.
I couldn't come up with anything smarter here.
And I want to make sure it extends ADObject.
So that's single line, just say MyClass is superclass is ADObject.
In fact you don't even have to write that line.
By default, when a class is interpreted by ADClass, we assume if there's no explicit superclass it's just a subclass of ADObject.
So you can even imagine this wasn't here.
Then we have to make sure in our constructor that we call whatever the default constructor of ADObject does, it actually sets up a bunch of things for you in the background and you really want to make sure that that ADObject constructor is called.
So here we call callSuper and callSuper no matter if it's a constructor, an instance method, will do all the magic work to make sure it gets to the superclass' implementation of that method and calls it.
You can pass parameters that will return to value.
It does everything you expect from a callSuper type of call.
And here we got just a standard instance method declaration.
There's nothing fancy here.
And finally, very important, we need to make sure we process this class to ADClass.
So we just call ADClass with MyClass.
Now let's talk about synthesized properties.
Let's say I want to synthesize a property foo on MyClass.
I set the synthesizedProperties to a list of strings or the name of my properties.
In this case, I only have 1.
You can have as many as you wish.
Just to make things simple, we're dealing with 1 here.
When ADClass processes MyClass, it's connected to two things.
The first thing is it looks for a getFoo method on a prototype.
This is a convention.
If you provide getFoo, that means you have a custom getter and so what we do is we automatically bind any getting of foo.
So for example you have an instance of MyClass and you said .foo on it, this actually calls getFoo in the background.
That lets you compute the value of foo dynamically as the user requests it.
This is like a virtual variable as you will.
If you did not provide a special getter, we assume that all you want to do is actually set the _foo instance variable.
This is another convention.
You'd take the name of your property, in that case foo, add the "_" prefix and that will get set automatically if you do not provide a default getter.
For setting, we do pretty much the same thing.
We look for a setFoo method on our prototype.
If we have it, we bind the setting of foo to setFoo, that means if your user as an instance MyClass and sets .foo on it, whatever value you're setting is actually passed to the setFoo method and it's up to you to deal with that and likely record it into an instance variable as well.
And if you don't do anything again here, we just assign as default to an _foo property.
In fact, you don't need to provide either getters or setter.
You can provide nothing to say, it is a synthesized property and the reason you'd want to do that is because you get automatic notifications being triggered.
So that's even worth doing.
So let's look at how we could provide a custom setter, pretty classic thing for a synthesized property.
So first, we set synthesizedProperties, pass it an array of strings, which are the name of the properties we want to synthesize.
In that case, it's only going to be foo.
Since we are actually not we want to set the real value for foo.
Foo is like a nonexistent property.
It's just going to be bound to our setter.
So we want to make sure we implement a special instance variable or an ivar and add an "_" prefix in the name of the variable so we just set _foo, default value to be 0.
Then all we got to do is implement that setFoo method as a convention set and the name of the property.
And there's a single argument being passed here.
That's actually the new value of foo we're trying to set.
And here you'd really be setting a whole bunch of things, running special code, refreshing, drawing or something.
I don't even know.
What you do what you have to remember is to make sure you keep actually the value of _foo because when the user tries to get foo, since you're now providing a special getter here, it will return _foo automatically.
So for custom getter it's very simple.
The same synthesized property declaration, but here we're just implementing getFoo and returning a variable.
You'll notice here we don't even have an instance variable because likely we don't even have a real property for foo.
We just compute it as we go on the fly when required.
So to tie into synthesis, we have automated property observation.
So let's create an instance of MyClass on a control object and call that property MyObject.
Then we want to be notified whenever foo changes on that object and be called back in the context of a controller.
So we get a pointer to my object, call addPropertyObserver on it.
The first parameter is the name of the property we want to synthesize and the second parameter is the object of the called back whenever that property changes since this is this in this context that means our controller.
So now all we got to do is we have to opt into the contract that tells us to implement handlePropertyChange.
That is the expected callback for whatever object is best as a property handler.
So handlePropertyChange got 2 parameters, first one is observedObject.
The second one is propertyName.
This lets you have a single handler for a bunch of property observer and be able to switch based on the originating object and the originating property name.
Now all we got left to do is to handle the change.
But let's say we actually know exactly what method we want to call back, just a little bit more convenience.
Well you can have a third parameter, which is the string referring to the name of the callback for that specific property change.
So that means we only have to implement fooDidChange and notice here we don't have any parameter because we already know exactly why we're getting that callback and then we can do whatever we want here.
We provided first traditional inheritance with the superclass property and callSuper method.
We built in synthesis with the synthesizedProperties completely declaratively, just it's like a here file.
You're just saying, here a bunch of properties I want to be synthesized.
And we automated the property change notifications so that synthesis process.
Let's talk about views and controls.
That's when you get into the meat of things.
And there are 2 main classes I want to discuss here, ADView and ADControl.
So ADView is just a complete rip on UIView and UIKit.
It provides the same methods, the same properties, the same behavior that breed the intent of what we're trying to do here.
And ADView is just a base class for anything that's going to render on your screen.
When you want to put something on display, you got to make sure there's an ADView and it's actually added to the view hierarchy.
But we're dealing with WAP technologies here.
And if you're familiar with WAP technologies, you know that the concept of rendering is somewhat opaque.
We're really just dealing with a tree of objects, elements and just manipulating them and putting them in different places and stunning them with CSS is what actually renders on screen.
So it's no surprise that ADView, since it is rendering content on the screen, is really just a wrapper for a DOM element.
And that element is what we call the layer.
And that is basically the element that will be the root of the hierarchy of that specific view that will be inserted into the DOM.
We'll look at that in a minute and see what it looks like.
Now let's say you want to contain other views instead of your views.
It's pretty classic.
For example, you have a scroll view and you want to have a bunch of buttons within a scroll view so you can scroll through them.
If we were pending elements directly into the layer, we couldn't actually scroll this content because the scroll view has a lot of different elements.
It has scroll indicators and it has an area that actually scrolls when you touch on it.
That is why we call the hostingLayer.
This is the layer that we want to be containing subviews and et cetera, and we'll look in again I have a little example in a minute.
Something that is really important to us is that we want to make it very easy for you to be dealing with something more complex aspects of rich media content.
And one of these aspects is Transitions.
When they're really complex and you want callbacks and et cetera, it's a lot of work to do on your own.
So we actually build all that directly in ADView.
And on top of that, because you don't really know when your transitions are run in which piece of code, in which run loop, we actually provided transaction system so you can say, here's a transaction that starts.
There may be X number of transitions it completes and all that is going to happen in complete synchronization in your engine.
And finally, there's a special kind of view that gets created automatically for you when you load iAd JS in your content and it basically wraps a view around the body elements and we call that the root view and you can get to it using ADRootView.sharedRoot and that's really the root of your view hierarchy.
If you're familiar with UIKit, it's like the window.
First thing we do is we create a variable scroll view and we create a new ADScrollView object.
We set this position in size so that it's displayed 20 pixels margins on either side and it takes most of the width from the height of the window.
And notice here we have helper little data types like ADPoint and ADSize to make it even more convenient for you to deal with those kinds of geometric properties.
Then we set up some of the call properties of the scroll view.
We're going to turn off vertical scrolling.
We're only interested in horizontal scrolling in that example, I'm sorry, and we want to make sure we don't show any of the scroll indicators either, so we just set that on that.
And then to make sure we actually display the scroll view, we get to point it to our share group and we addSubview, well we just add a scroll view as a subview with a single method call.
So what this does behind the scene is actually generates all this markup.
This is actually pretty simple example but some views are incredibly complex and require a lot of code and you don't want to know about this.
You'll notice here a couple of things.
So the div at the top levels are layered.
You'll see a div with a class hosting layer, that's actually a piece of content that's going to scroll, and this is going to hold all the content.
You'll see all the things that are generated you have nothing to do with.
For example, the scroll indicators.
These are all very private to ADScrollView.
You don't need to know about this.
Why did we have to write so much code?
We're trying to make the best of both HTML and UIKit.
So we've already provided the UIKit part.
I think if you're a web author, what you really want to do is to be dealing with markup and style with HTML CSS.
And that really builds a case for what we call the declarative approach, the declarative layer that we build on top of those APIs for you to make it super easy to build using controls within just markup.
And there are 2 key points that makes this very compelling.
First is the ease of authoring.
Say you want to style your scroll view.
You want to change the background color, all that kind of stuff.
That's the value of using CSS, right.
It's so easy to style content.
In fact, we don't want you to know what that markup looks like because if we want to change that implementation in the future, we don't want you to rely on things that we consider to be private.
So we need to know what the markup structure is and if you were laying out the structure yourself, you know exactly how to style it.
And on top of that, it also goes back to performance.
And remember I said one of our primary concerns in iAd JS to make sure things are streaming and we make sure that it's easy for you to get the best performance out of your app.
You don't even know what's going on.
And if you're trying to optimize things, obviously, this is going to it's how you control.
If you have all your markup laid out already, all the CSS created, that's just less time spent rendering, fewer manipulation.
The engine can just deal with that in like one monolithic block and just it's just a lot faster.
So that's the kind of benefits that we get out of a declarative approach.
So let's go back to the code we built.
This looks similar, but it's different.
The first thing you'll notice is we have a body and a class of ADRootView.
That rings a bell.
That reminds me about the sharedRoot, the thing we build automatically with the body.
Well if you're using the declarative layer, this is the entry point.
So in that case, we're putting down the body, pretty typical example.
You can have it on a subtree elsewhere, that's fine.
So now we need to create a scroll view.
So we set up its class to be ADScrollView, that's just an element.
Having ADRootView on the body will make sure we look at all the children and figure out which one has an ADScrollView class so that we can process it.
Then we want to set the properties of our scroll view.
And we can do that declaratively as well.
So if you want to throw them out vertical scrolling, we just AD-vertical-scroll-enabled.
And notice here, we're extending HTML attributes.
I was fairly conflicted about that but I think the value of doing this is so great for you as a developer that as long as I think as long as we add an AD-prefix, I think we're in the clear and it's clear enough for you that this is not a core HTML attribute but just an extension specific to iAd JS.
Now what about position and size.
We don't have an ADPosition or an ADSize here.
That's because CSS already does a great job of positioning and sizing things.
We want to integrate as well as possible with the core web technologies.
So instead of having those custom attributes, we actually just look at the styling of your element.
So here we use left, up, right, bottom to actually position it and make its scale to be you know 20 pixels margin on either hand.
And it's not even just about the style attribute here, which is a core HTML attribute.
You can have all this information in CSS style sheets that are loading in the penalty of the element, all that.
We're looking at the computed style when we're trying to figure out the stylistic information related to view and finally, we put in our hostingLayer and we'll just put whatever content we need in there and we'll see about that in demo later on.
You'll notice we don't talk about scroll indicators here.
This will get added to the tree later on.
In fact there's so much that can be added to the tree you don't even want to know about, but that gives you a good way to know what the structure is and so you create all of this using simply markup.
So that was views.
Now let's talk about controls.
And controls are all instances of the ADControl class which is just a subclass of ADView so all the features you know from ADView that's declarative approach, all these APIs and et cetera, this comes for free in ADControl.
It's just an extension of it.
And what they do is that they provide advance and automatic touch tracking.
We're really trying to make it so you don't have to deal with the interaction private so you have control yourself.
We try to do as much as we can on our own.
And the way we do that is we actually extend the set of built-in multi-touch DOM events and add a little bit more granularity to them.
So let's step back and let's see what developing on the desktop.
I'm sure a lot of you are more familiar with desktop web programming and here we're dealing with the mouse.
That's the input method.
So mouse events on the desktop are always related to target element and that makes really easy to program interactivity based on an element.
It's easy to know when the mouse over is onto it and when the mouse leaves it or click on it, super easy.
So we get all these elements, all these events, I'm sorry, which are all related to a specific target element.
So let's focus on iPhone here.
Let's say we're developing a web app for Safari on iPhone.
It has this great multi-touch DOM events.
But these events really only provide you with the raw touches.
You get all the information you need there though.
It's really important.
This is all we really need.
We can tell how many fingers on the screen, where they are, how they're moving, when touch starts and ends and et cetera.
We get this touchstart event when the touch starts, the touchmove when the touch moves and the touchend when it's over.
But we don't actually get the information, the granularity we'd get on the desktop, at least not so easily.
We don't get like the equivalent of mousemove or a mouseout when we're touching over an element or out.
We need to do a little bit of extra work and that's exactly what ADControl does for you for free.
You don't have to worry about any of these.
And so what we do is that we introduce another set of control events that are specific to iAd JS.
And that's all clean and kosher because DOM events were built so that ostensibly you can create your own events and dispatch them.
It's an open process.
So it completely ties in to the good practices of web development.
So what controls do is they basically listen to all the touches, analyze them and trigger additional touch events, which are a lot more informative about what's going on.
So for example, you can listen to TouchDragEnter.
That means within a touch, we started touching over a given element.
But when we exit that element, we get TouchDragExit.
TouchUpInside as well when we've tapped an element, this kind of events.
And we got a lot more.
And you notice they're all prefixed with control so you know exactly they're related to control to ADControl.
And I'd like to refer you to a great session that happened yesterday.
You'll be able to download on a video later on which were all about detecting touch and gestures in webpages on iPhone OS.
It was great and I really urge you to look into that in greater depth.
So now let's talk about actions.
And again, we're dealing here with DOM events.
Control is here to react to user interaction exactly, right.
So in UIKit, the way to be responding to an action on a control is usually with the action-target mechanism.
That's a great mechanism but it's one to one.
There's nothing bad with that specifically but in the context of web development, you're dealing with an interaction with the one-to-many process.
So many different observers can listen to a mouse even on a given element and they don't have to worry about what each other do.
You can add as many as you want.
So we want to do the exact same thing in our case for actions.
So when a control that you changes, for example, say you have the slider and you're dragging it around the screen, whenever that slider's position changes, it will trigger a control that you change event that lets you know that control scroll value has changed and we do that using DOM events.
So it's a single API for any kind of interaction tracking in your ad.
So let's talk a little bit about DOM event handling.
Let's say we have our slider and want to be told whenever the control that you changes, so we use addEventListener.
Remember it's the exact same API we use with just the DOM and here even though it's an ADControl instance we can use that same API.
We make it that easy.
What we do is we actually forward that event listener to that controls layer.
So first the parameter is going to be the name of the event that we're interested in so it's control that you change and the second object is going to be handler, callback or whatever, and then probably that just says we're not using the capture phase.
That's the detail you don't really need to worry about.
So let's consider your user drags the slider around the screen and the control that you changes even start firing on that slider.
So 2 things that may happen here.
A, the handler parameter, the second parameter to addEventListener is a function, and what happens here is that we get a pointer to that function and we just make a callback.
We don't even actually do that.
WebKit does that for you.
And there's no context here.
It doesn't even know what this it's just a function.
When you're dealing the interactions, pretty likely that you're doing that in the context of a controller.
You have an object that needs to respond to that action so it can do something else with, you know, with respect to certain properties that are specific to that controller object.
So, in that case, what you want to do is make sure that the handler parameter is actually an object.
And what that means is that you enter in a contract that you have to implement a handle event method on that object and that gets called back with the context being your handler.
So, if you have a controller object, you just need to implement controller.handleevent, for example, and it gets called and that this object, the context object is just your controller.
And that's really the best practice.
That's I would argue in 100 percent of cases that's what you want to do.
So, controls are various states, selected, enabled or disabled, and highlighted.
I want to talk a little bit about highlighted because this ties into this touch tracking I was talking about.
Traditionally, you'd say OK, I want to react I want to change the state of my controller and my custom controller based on its being highlighted or not so you'd be subclassing ADControl and overwriting the said highlighted method for example.
Well, that's one way to do it and that is fine.
But we wanted to we want to make it a bit easier for you and what we're going to do is we're going to synchronize the highlighted state with touch tracking so we obviously do that behind the scene but on top of that, we're going to make sure that change of state is reflected directly in CSS.
So let's look at what that means.
We're actually going to build a custom control in a single slide.
Let's start with a markup.
Just like we can instantiate a view, we can instantiate an ADControl and in that case, we also want to make sure it's our custom control so we add another custom name on top of that.
You notice we don't have ADView on here even though it inherits from that.
We actually, when we build in the declarative approach, we automatically add the classes as needed when we're parsing the attribute, the elements.
So, you don't have to worry about the superclasses of your element.
Next one is styling.
So the first thing we do is to create a CSS selector that will match both the ADControl class and MyClass control.
So, they will match our development right here.
We want to make sure we only match controls that are accustomed to our application.
So, here I do very basic styling.
You can do so much with these obviously.
You can use CSS effects to full extent to make awesome looking bonds of controls.
So, in that case, we have a background color to be white and color to be red.
And what we want to do is we want to invert that when the control is highlighted, when the user has a finger on top of that element.
So to do that, I had just, actually just add this CSS class name called highlighted on your element whenever it is highlighted so you don't need a subclass.
All you got to do is write another more specific CSS selector that looks into the highlighted class and just invert the values of background color and color to give it that highlighted state.
You can do it all in markup in pure CSS.
So, let's look at some code to see how we can make all that happen and what we're doing here is we're building a full gallery for my world renowned cat.
And it's like the weather app.
So we have the scroll view that will snap to different pages and at the bottom of the screen, we'll have a page control.
These 4 little dots that are synchronized to the scroll view and that lets us go from one page to the other by a tap of the finger as opposed to dragging.
OK. So, we're going to get started by building some markup.
We've already mostly done that.
We set up our root view to be our body, easy enough, then we'll start processing all the subviews.
So, for example, the scroll view.
You notice here one new property which is paging enabled.
That says that we have to snap in pages' worth of content while we're scrolling through that scroll view.
Again, we do that all magically for you.
You don't have to worry about the touch tracking here to make that work.
We do it all for you.
Then we want to put in some content into our hostingLayer.
So, in that case, we'll just have 4 images, one for each page of our with our cat's picture.
Then we have to build a page control, which is new.
So, class ADPageControl, simple enough.
Set the number of pages to be 4, that's the number of images we're actually dealing with and something that I may not advocate but I think is really worth telling to re-show you the full extent of the declarative layer is to put in an inline event handler.
So, if you're dealing with desktop content with web content, you're likely have seen people putting like on mouseover, on mousemove or whatever, event listeners directly on an element and we can do the exact same thing even though we're dealing with custom events.
So, here we're setting up a special event handler for control that you've changed.
All we need to do is prefix 80-on to the name of our events and we can automatically create an event listener for that declaratively.
So, here that means later on we have to implement controllers method, page control that you changed.
OK. Now, let's lay this out.
Take a scroll view, match it with CSS, set its width, set its height to be just little low gap at the bottom for our page control, which is going to be laid up flush with its subproperty in width and height again.
Now, we need to lay out the scrollable content.
So, first of all, we'll get a hosting layer.
You might want to have a more specific selector here of course, but you know we'll just use the global ones to make the code easy.
I want to make sure it's 4 times the size of a single page.
So, 4 times 320 pixels is 1280 and we want to make sure to lay out each image to have a little bit margin on the right, except for the last one.
No margin there.
We want to snap to the last image really nicely.
So, now we have to write a little bit of code but not too much.
So, we want to get started whenever the DOM content is loaded.
That means the DOM is fully interactive and ready for us to interact and that means iAd JS has done all its work and set up all the views and controls that are already laid out in the content using markup.
So, we call that init method just like main in your native code and we called another init method on a controller object.
That's the object that'll be responsible for dealing with all the interaction within little mini apps.
So, we're going to point at your page control and scroll view because we want to connect those two together and we have to do a little work to bind them together.
So, we're going to point at your sharedRoot and we want to ask our sharedRoot, "Give me all the page controls so that I can get one that's interesting."
So, we provide these special properties that are called collection accessors.
They are automatically generated based on what content is within that subview.
So, if you ask for page control, they'll give you all the page controls under that sharedRoot.
So, we get the first one, we only have one, so it's pretty easy, we'll do the same for scroll view.
And for scroll view, we want to be told whenever we snap to a new page by dragging the scroll view so we implement a delegate property here.
And if you're familiar with UIKit, you know exactly what this is.
If you're not, I'm going to summarize real quick.
A delegate is an object that's supporting your element and extends and pipes into its interaction flow.
So, here we're setting our controller object, this, to be our scroll view's delegate.
That means that controller will receive callback that it can implement that will tell that object what's going on with the scroll view.
So, let's actually just do that.
Let's implement some of that scroll view delegation.
So, there are 2 ways you can snap to a page using a scroll view with paging enabled.
The first one is you may start to drag the scroll view, stop for a little bit and release.
You want to snap to a page with nice little animation.
There was no momentum here.
That's another type of interaction.
So, for that first type, we want to implement the scrollViewDidEndScrollingAnimation delegate, very descriptive.
And when that happens, we want to make sure we sync the page control to the scroll view using that method.
We'll have to implement that later.
Now, let's listen to the other delegate.
That one happens when you do a nice little flick, there's momentum so we do nice little friction-based deceleration so that it snaps nicely to the next page with the speed of your gesture.
So, again we call the same method to sync the control page to scroll view the page control, I'm sorry.
So, what we do here is we do 2 simple things.
We get the content offset of our scroll view, that's the amount of pixels, the content within the scroll view has been scrolled and we divide that by the width of the scroll view.
That's the page's worth of content.
Doing that, we actually get the page number that we are on now.
Just make sure we round it so there's no rounding error and we just design it to page control's current page.
That's all there is to do.
That alone ensures that our scroll view is bound to our I'm sorry that our page control is bound to the scroll view.
Whenever we interact with a scroll view, the page control is updated in sync.
Now, let's do the other way around.
You remember that in a markup, we already bound to the control that you change event on a page control.
That event triggers whenever the current page property changes so we have to look at the current page, multiply that by the width and we get the new X-property that we need to assign to the content offset of the scroll view.
Current page has just changed in there the instance so exactly what we want to be looking at and all we got to do is set the ContentOffsetAnimated, get a point with the X-coordinate and just pass through as the animated flag.
They'll make sure our scroll view nicely animates with the single method call.
And that's what we did.
We did a mini app in a very small amount of code.
So, let me summarize using controls.
I think the key thing, which is one thing that I remember today is that we have these 2 techniques.
We have this rich API based on UIKit that lets you have full programming control and how you create, lay out and et cetera, all these great views and controls.
But on top of that, there's a declarative layer that makes it super easy for you to build all this with HTML CSS.
There's a lot more than that.
There's a lot more than what we've seen.
You've seen from this session there's a bunch of different views and control that come for free by just using iAd JS.
OK. So, we've seen like a scroll view which is obviously a big deal but we do so much more.
We do sliders, we do carousel views, which are accustomed to iAd JS.
We don't even have the in UIKit.
We have the nice little 3D rotating carousels that Steve showed in the Toy Story demo back in April.
We have rating control.
We have start control.
We got all these cool stuff.
We even do color flow, which sounds amazing but we just do that and you get it for free by just laying out of HTML in your page.
It's pretty awesome.
So, that was views and control.
Now I'd like to wrap this up and discuss view controllers and this is all about the ADViewController class.
So, let's go back to the demo that Dean was building.
This is our ad and it just looks like a webpage.
Well, it is.
I mean, an ad is just a web view layered on top of your application with interactive content.
If you're thinking about web content, you're thinking about a webpage.
A webpage is just, you know, a big block of markup and some stuff and if you want to do interactivity, you can just double the visibility of different elements in the tree and that, you know, that's awesome.
Well, if you look at that ad you might actually think that this is not really 1 page but is several pages.
We have the menu, we have the photos, we have the maps and if you just start thinking from an architectural point of view, it's important that the interactivity you're dealing with are specific to each of the screens.
The menu doesn't need to know about what goes on within the map, the annotations or where the usual occasion is.
It's only the map's job to figure out what's going on here and make sure the interactivity is correct.
This is really a modular architecture.
These are all little modules, screens, pages, whatever you want to call them.
I want to make sure we address that in iAd JS and there are some important performance considerations taken into account that really makes the case for the architecture.
The first one is if you're building an ad and you load a lot of content.
Let's say you load all that content upfront, all those images, all those script, all those styles, all of that.
That's a lot of network content to get and that may just take a long time to download your ad and that's not good.
The user taps on the banner and he wants to be able to see the content as soon as possible.
It's not just about that.
It's also if you have a lot of stuff even if it's loaded quick and, you know, fast enough, you have a lot of content in your DOM tree and this may have very bad implications from rendering performance.
I mean the iPhone is amazing but you know there's only so much a device can do.
So, you want to make sure you're not dealing with too much of that stuff as well.
So, they mix the case where 2 core features that we want to add to make things easy for you.
The first one, we want to make sure incremental download of your ad's content is really easy and the second one is we want to make incremental display of your ad just as easy.
So, let's look at the implication of a modular architecture on view controllers.
The first thing we want to do is we want to obstruct the loading of all these resources, all these styles, all these scripts, all these images so you don't have to do this work and make sure this just happens automatically.
I want to make sure that we add and remove views or DOM elements if you will only as needed so that we only have a minimal amount of content in the DOM tree at any time to just render what needs to be rendered on screen.
So, let's look at how a view controller is structured, the anatomy of view controller.
It's really like a bundle of resources for your page of your screen or your module.
That's the programming logic.
That's where everything happens.
Usually, you probably have that link from the original webpage right away.
But you can inject it at anytime.
That is no problem.
What the view controller does is going to point to a bunch of resources.
It can point, for example, for HTML fragment file, which will just be your views content.
It can point to a series of style sheets.
It can use several style sheets.
A good way to build a modular approach in web content is to separate style sheets in different box so you can link them at anyone time to have the minimal amount of style needed.
And you might have a bunch of images that you want to have pre-loaded when the view comes on the screen so that there's no empty gaps on the screen that load on that layer.
So, we have to make that easy for you and we do that using just a single simple configuration.
So the first thing we do, we implement our menu controller here.
We make it super class to be ADViewController.
We want to have all the great features of the ADViewController come for free so we make sure we just extend it.
Then we call the default constructor of ADViewController with the configuration object and we want to describe the various files that we're interested in.
So we're going to talk about the content view.
We want a given style sheet.
It could be many to different style sheets.
We want a bunch of images to be pre-loaded with the rest of the content.
So, let's look at what happens behind the scenes.
So, we have a phone.
Let's pretend it has an ad loaded into it.
There's a view controller on one end and that view controller is a delegate that's going to get message as the view controller's view is being loaded.
So you can easily have another object be monitoring, the loading of a given view controller.
So, let's consider now your user interacts with the phone and wants to put that view controller's view on screen.
Well, that means we need to start creating a view for it.
The view controller manages a view so as soon as you need it, you need to get it back.
You notice here we're not actually getting the content view.
We're just getting a view.
We need to give that back so if the user wants to put the view on the screen right away, you can do that.
It won't have the content, but that will come later, you'll see.
So, it gets a viewDidLoad message onto its view controller class and that says that the process is starting.
So, a loading delegate is getting another delegate method that says that loading is starting as well.
So, that's one we might want to start putting like a little animation spinner say, well, we're loading stuff in background.
That's when a view controller automatically starts sending all those requests to the background using XMLHttpRequest.
You don't have to worry about this.
This just happens for free and the server assembles those files and starts sending them down to our device.
So, we're going to get all those files one by one.
We don't even know which order and you don't need to worry about that but you'll get notifications in your loading delegate as that happens.
It tells you well, here, I've got a new file.
Here it is, here's its URL and that is very useful.
So, if you want to put like a little progress bar you can have it fill in gradually as you get those messages.
So, we're getting towards the end of our content loading here.
What we need now is one last image and we'll be ready to set the whole view up.
Here we go.
So now we start with one last message to our delegate saying we've loaded a required file.
And now we can start doing something interesting.
We tell the loading delegate one last time we finished loading file so you can even listen to just the start and the end.
You don't have to worry about the ones that are coming for each individual file.
And now we get another message just like we have viewDidLoad that says contentViewDidLoad.
What that means is that we've done an immense amount of work for you behind the scenes.
We've actually taken the HTML, we've parsed it, we get in the string, we've created the DOM elements out of that, we've created a view with the DOM elements.
We've done all that automatically for free for you and we've created that content view that we just put into our existing view.
We've also taken the style sheets, put in the tree, loaded it up and made sure all the images were ready to be displayed.
We've done all that for you automatically.
So, that's it.
Our loading mechanism is all done.
So, if we go back to the configuration that we had, we also had this ID property.
This ID property is short but it's very, very, very significant and meaningful.
What it does is it just provides a unique identifier for view controller so you can identify this view controller among all the other view controllers that you have.
You may have a bunch of screens in your ad and you want to get the pointers to that specific one from anywhere else.
Well, because we're given an ID of menu, we can just look into the ADViewController that extends its array and that compiles all the instances of ADViewController out there and just using the name of the the ID of our view controller, we can get a pointer to it.
So, in that case just .menu.
But it has more added values and it really again ties into these declarative features.
It makes it so easy, for example, to match CSS.
Remember when we loaded our view controller we created a view automatically to host all of our content.
Well, you didn't create that view.
You didn't even put a class name on it.
You could do that in code actually if you wanted but, you know, you don't want to do extra work when it's not needed.
Because behind the scenes we make sure we reflect that ID property of your view controller on the content view and the view.
So, your content view, if it doesn't already have an ID attribute, will have an ID attribute as its menu.
And the view that contains the content view that was created automatically for you will use that same ID and add a -container suffix to it.
So, you can start writing styles for content that you didn't even create because we just tell you here's the ID it's going to be.
That's all automated for you.
We talked a lot about coding features but a lot of more declarative features about view controller.
Again, we want to make sure we have really great integration with web technologies.
And the reason for that is we want to add more convenience for you to be dealing with these view controllers and interactivity.
So, let's look at some common programming tasks when dealing with view controllers.
A, you're dealing with a view and a view's content so you'll probably want to reference to different objects that you want to update as you go along.
Then you also really wanted to react to the interaction within your views so the user taps on a button, updates the label of another object that you'll get a reference in step 1.
Well, that's really kind of common.
And the third thing is one of the design pattern that we think is going to be pervasive throughout ads is the transitions between various screens, the various modules.
So, these are a fair amount of code and some are really easy but repetitive and some are really hard like managing a transition is a lot of work.
So we're going to address this with 3 features.
The first one is outlets.
That's the same terminology we use in Objective-C coding and what it does is it automatically creates references to views or elements in your content view.
Notice here I say view and element because we treat both elements that are managed by an ADView and elements that are just regular HTML elements the same.
And you can point to either of those using the same technique.
And that technique is using AD-outlet attribute, just give it a name and that makes it easy for you to get a reference to that object on the outlets property of your view controller.
So you can do this.outlets.title and you get a pointer to that element.
You don't need to do get on with ID.
You don't need to do any of that.
In fact you've noticed here, we don't even use the ID attribute.
That would be a good way to do things except we're dealing again with a modular architecture.
Even though all these things will end up in the same document at some point, to make sure there's not any ID clashing which is supposed to be unique to the whole document.
We want to make sure we have an ID that may be repeated but just specific to that one view controller.
So let's talk about actions.
It would be great if you could bind actions to your view controller just as easily.
Well we provide a way to do that.
We automatically register callback in the context of a view's view controller by just adding one attribute, the AD-action attribute.
And by saying this that means my view controller needs to implement a playAudio method and that gets called back automatically in the context of view controller.
You don't have to worry about getting a reference to it.
This is all done automatically.
All you got to do is focus on implementing that method, that's it.
Let's talk about transitions.
Transitions are like a specific type of actions.
So, we've already simplified things for you.
You can get pointed to your elements and you can know when an element has actually been activated.
Well, that's not what we want you to do.
It's so pervasive in what we think people are going to build at, that we want to make it super easy.
So since our view controllers already have IDs, it should be easy to say well, this should just transition to that view controller.
And we just do that using the AD-transition-to attribute.
You can just give the ID of a controller, for example, maps and will automatically transition to that element.
And this abstracts so many things.
First, it abstracts the loading of the view controller.
We load the view controller's content dynamically when are needed so we don't spend too much time on loading the app.
And when we do transition we got to do so much.
We got to load that content.
We got to add its view when it's ready.
We need to make sure we have the transitions happen in sync for both of them and then when it's done, we need to remove the object controller's view, et cetera.
And it's just a lot of work to trigger all the notifications.
You don't want to deal with that.
So we do that all automatically for you.
So to summarize the core features of view controller is first of all the automatic loading of all the screen resources as if they were a single bundle loaded through a network.
You don't have to worry about any HTTP connection.
It's all done for you.
And then when you're actually building your scene, this is all done incrementally with automated transitions for a great effect.
We've gone further and just standardized even like petty little common coding test to make it even easier for you so, and we've done all that very easily with more declarative features so you can write less code and create less errors in your code.
So that's it.
That was our 4 key points today.
We started discussing the motivation of iAd JS, the mix of rich media and mini apps, HTML5 and UIKit.
And finally, dealing with view controllers, which we have just talked about.
I want to go back to the original slide when we were discussing rich media and mini apps.
Really this framework is all about this, revealing all this with web technologies, HTML5 and UIKit, 100 percent web standards coming together to build iAd JS.
[ Applause ]
So for more information, you can contact our Evangelist Vicki Murley.
You can download the iAdDeveloper Package, you can download our documentation, which is still a work in progress but we're working hard to make sure everything that's rich framework is documented.
And we're building some forums for you to discuss iAd JS on.
There were some great sessions.
Dean was just here before me giving me a more practical approach at how to build ads.
We had a session about integrating ads with iAd and it's being repeated tomorrow.
There are a bunch of great sessions this week.
Some being repeated tomorrow morning about audio and video, CSS effects, HTML5, Touch Events, and et cetera.