Transcript
>> 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 some of the few JavaScript
enhancements we made for core programming features.
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.
So things like HTML, CSS, JavaScript and the DOM APIs.
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.
Just like you would deal with an image,
you can deal with audio and video,
overlay things scripted with the
DOM and JavaScript, et cetera.
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.
So we're actually looking at UIKit
and we ripped completely the design
and its features and re-implement all that in JavaScript.
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.
We're just using HTML5, CSS, and JavaScript.
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.
Now let's talk about some of the
core JavaScript enhancements we made.
And I want to talk about two things, ADClass and ADObject.
I feel bad about this slide because
it starts off JavaScript limitations.
Well, it turns out JavaScript is amazing.
I live everyday in JavaScript.
I write JavaScript all day long and actually love it.
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.
Someone loves JavaScript.
But it has some limitations.
And these are actually not limitations even in JavaScript.
They're more at the syntax level.
Things you'd want to do a bit easier and
these things are for example inheritance.
There is no explicit support for
traditional inheritance in JavaScript.
What I mean by that is there's no clear
relationship between a class or a superclass.
Even the concept of class is sort of loose in JavaScript.
And there's no super keyword like you
would have in Objective-C so you can get
to the superclasses implementation of a method.
Nothing that we don't have in JavaScript,
which is completely pervasive throughout
UIKit is the concept of property synthesis.
That is a JavaScript property which is you're just wrapping
a complex piece of code that'll be running in the background
so that you have a nice expressive API using
properties but you're really running methods.
And there's no built-in support in
the syntax of JavaScript for that.
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.
That's the kind of stuff that JavaScript doesn't
give you for free with a couple lines of code.
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.
So let's look at some of those Core
JavaScript enhancements and how they work.
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.
It's just how you do instance method in JavaScript.
And finally, very important, we need to
make sure we process this class to ADClass.
So we just call ADClass with MyClass.
This is just an example of how you can arrange
things so that you can, you know it's JavaScript,
you can write your code in any way you want to as
long as your class is processed through ADClass.
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.
So these were the 3 core JavaScript enhancements
we've made and there are not a lot of them.
That just speaks to the value of JavaScript.
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.
So these are all the changes we made-- well
extensions if you will we made to JavaScript.
Again, we haven't touched the JavaScript engine.
Within the JavaScript runtime, we've extended
these features using simply JavaScript.
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.
So let's look at building a scroll
view with those JavaScript APIs.
First thing we do is we create a variable scroll
view and we create a new ADScrollView object.
AD is the prefix you'll see for all the
specific two iAd JS JavaScript classes.
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.
But why do I have to write so much JavaScript?
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.
But if you're using an opaque JavaScript
class and it generates a bunch of markup,
you don't even know what that markup looks like.
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.
Then it's just good sense to want to separate
the logic, which belongs in JavaScript
with the content, which belongs in HTML CSS.
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.
So if you're dealing with those JavaScript object, they're
doing all kinds of manipulation that you don't know
about to the DOM tree when you're creating
a layer, when you're putting it somewhere.
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.
Having an element with an ADRootView class
on it means I'm using the declarative layer
and when you process this subtree for
any content that has an AD-prefix class
so that you can create those rich JavaScript projects
that will control those, all those using controls.
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.
No need to write to JavaScript here.
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.
So, it just calls it in a global context of the
JavaScript program environment which is Window.
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.
No need to write any JavaScript
here for your custom control.
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.
It's easy.
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.
It all starts with the JavaScript
file which is your view controller.
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.
JavaScript is dynamic in that way.
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.
Again, we're trying to make like this declarative
type of id comes to life even in JavaScript.
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.
Yeah, first.
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.
Very simple.
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.
So at that point you should be able to
just trigger transition using JavaScript.
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.
Some of the core JavaScript enhancements we've made should
make inheritance easier, property synthesis, and et cetera.
Dealing with views and control, putting things
on screen, both with a rich JavaScript API
and a super simple declarative approach with CSS and HTML.
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.
Thank you.
[ 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.