Write-up Parts 3 and 4

December 19, 2009

Part 3: The features of ‘$tween’

Our language will allow the creation of complex dom animation in an intuitive way. We are assuming that the user knows html and CSS, and basic dom selectors, but not javascript or jquery. It should be relatively easy to create interesting visual effects in an intuitive way. Designing for designers shapes the syntax of our language:

1. If function arguments have a unit, it should be obvious
2. There should be no functions where complex parameter arguments need to be remembered
3. When chaining together an animation, a designer should not have to remember specific order that they need to be chained together with
4. The design should leverage their current knowledge of the DOM, HTML and CSS
5. An animation should be built in the most intuitive way possible

Creating a basic animation:
An animation must consist of three basic things: 1) A attribute and how it should be modified, 2) A duration 3) A specific element to move

Because the designers know CSS, they should know the attribute they want to animate and how they want it modifed for example. There will be an advanced option to pass in a function that modifies a generic div. This creates a tween instance hereafter notifed as [tween]
$tween({“width”: “50px”}); // this will animate the object to eventually be 50px wide
$tween({“width”: “+50px”}); // this will animate the object to eventually be 50px larger than it was initially
$tween({“width”: “x2″}); // this will animate the object to eventually double it’s width
$tween(function(i /*between 0 and 1, essentially percentage done */){return {“width”: “” + i*50 + “px”}); // this will animate the object to eventually be 50px wide

A duration can be specified with
[tween].forSeconds(3) // this animation will take 3 seconds
[tween].forMilliseconds(3000) // this animation will take 3000 milliseconds

A tween can be attached to a specific element with
[tween].attach(“#a”) // attaches this element to the item #a

Finally a tween can be started with
[tween].go() // starts animation
[tween].go(“#a”) // attaches animation to #a and starts animations

Further, tweens can be modified in various ways

A tween can be repeated with
[tween].repeat(3) // animation will repeat 3 times

A tween can be eased with
[tween].ease(‘accelerate’) // start moving slowly and accelerate
[tween].ease(‘decelerate’) // start moving fast and slow down

Two or more tweens can occur simultaneously, in parallel with
$tween.parallel(tween1, tween2, . . . .) // all tweens start at same time

Two or more tween can occur consecutively, serialized with
$tween.serial(tween1, tween2, tween3) // all tweens happen consecutively

A pause can be created with
$tween.pauseForSeconds(2); // does nothing for two seconds
$tween.pauseForMilliseconds(2000); // does nothing for 2 seconds

Complicated animations can be build from simpler animations, all which are abstracted to the animation level. In a rich, interactive environment, most objects will have some sort of roll-over effect and many will share similar roll-over effects, this will make managing and creating these effects easy.

Part 4: Implementation

An animation will essentially be a tree that knows how to invoke it’s children

Every different action listen above will be a different node type. It will set the node that it was called from as the child. For example tween1.attach(div) creates an ‘attachment node’ that has tween1 as a child. $tween.and(tween1, tween2) will create an ‘and node’ that has both tween1 and tween2 as it’s children.

Each object will have a trigger(params) function and an animate(i, params). The params object is used to pass information on to a nodes children. ‘i’ is used to represent how far along an animation is between 0.0 and 1.0.

Calling go() on a tween instance will call that nodes trigger() method

A call on trigger() or animate(i) on a specific node does one of
1) modifies params and calls the node’s child
2) branches the single trigger() or animate() call to multiple trigger() or animate() calls
3) modifies the i parameter

Here we explain how each node is used and created and how they do one of the above 3 actions:

BASIC NODES:

Tween.attr: created using $tween({attr: value});
This is pretty much the basic animator, it only knows a single CSS
attribute and either a modifier or a final value. An identity node
exists too that simply returns true always. Because it is the basic
animator it is less flexible.
trigger() – trigger cannot be called on this node since it doesn’t
have a duration or a dom element.
animate(i, div = null) – i always represents a
value between 0 and 1 that is how far along this single animation
should be. div must be a single dom element. Animate modifies an
elements css attributes based on the inital value that it looks up,
the final modification necessary and the percentage of this that
should be done.

Tween.duration: created using [tween].forSeconds(value)
This is what converts a trigger() call into an animate() call and
therefore creates a percentage based context for it’s child.
trigger(params) – first calls it’s child with animate(0, div?) – if
there is a div parameter in params it is passed on to the animate
call. If params has a callback parameter then this is called after
the animation is done (to deal with ‘then’s). If params has an ease
parameter than this is used to modify i before it’s passed down (a
linear ease could be modified to parabolic)
animate(i) – an error should be thrown in this case. this means that
two intervals have been set which doesn’t have an inuitive meaning.

Tween.attach: created using [tween].attach(value . . . )
This is what is responsible for attaching an animation to a DOM
selector. The value passed in on instantiation may represent many
elements, this breaks that up into multiple animations
trigger(params) – Calls trigger(params) on it’s child setting the div
parameter to every DOM item that is selected using ‘value’. If there
is already a div parameter in params it throws an error
animate(i) – Calls animate(i, div) where div is every unique DOM item
that was selected using ‘value’. If called with two arguments, throws
and error

——

ACCESSORY NODES:

Tween.and: created using $tween.and(value, value . . .)
This is doing two animations at the same time
trigger(params) – Calls trigger(params)on both it’s children.
animate(i, params) – Calls animate(i, params) on both it’s children

Tween.then: created using $tween.then(value, value . . .)
This is doing one animation and then another
trigger(params) – Calls trigger(params) on first child, setting a
callback param that is a function that calls trigger(params) onto
second animation etc. If params already has a callback parameter then
this callback should be called first, and then the second parameter.
animate(i, params) – If this is called it means that the children do
not have durations and just assumes that they all get equal parts of
the animation. If n = the amount of values passed in, then just calls
first child’s animate(i, params) on the first child for values of i <
1/n, calls animate(i, params) on the second child if 1/n < i < 2/n etc

Tween.repeat: created using [tween].repeat(value)
This simply does the same as [tween].then except the callback

Tween.pause(value): created using $tween.pauseForSeconds(value)
essentially creates an tween that does nothing for 'value' seconds
return $tween().forSeconds(value);

Tween.ease(value): created using [tween].ease(value)
This adds an easing capability to tweens. It will have preset values
that can be passed in such as 'gravity' or 'slide'. It should know
how to convert a 'linear' value between 0 and 1 to an eased value
trigger(params) – adds a function that knows how to modify i to the
ease paramater of params. If 'ease' already exists throws error.
animate(i, params) – simply modifies i to the new value and calls child.

Project Write-Up: Parts 1 and 2

December 19, 2009

Part 1: Our project initially aimed to be a small javascript toolkit (along the lines of jQuery, but likely with less features), but we've since changed our goal to provide a simple toolkit for animating DOM elements on a web page. This will be helpful for web developers who need a middle ground between a dynamic website with javascript and full-on flash for animation, and it will provide a simple interface, as its target audience is web developers. Doing animation in javascript is possible, but quite tedious. A web developer will not want to deal with setting timeouts and calculating durations and intermediate values in an animation. One way we aim to simplify this task is by defining "tweens", which is I believe a flash terminology for an animation where the developer specifies a value to update (such as a div's width) and the amount to change it by, and the time-span, and the "tween" code will handle all of the nitty-gritty details. Why solve this problem? There is indeed an existing solution for jQuery (our solution also will leverage jQuery's extant, and quite effective, means of manipulating the DOM), but it is quite simple. The jQuery animation tool is a quick and easy way to alter the CSS attributes of individual elements in isolation, but it doesn't provide a way to coordinate the animation of multiple elements. This is exactly what we aim to do—provide an intuitive means of composing animations of multiple elements. Part 2: Since we've already compared our project to the jQuery toolkit's animation tool, I'll describe how they built their library; the internals of our code are set up in a similar manner. At the core of jQuery is the "$" function, which returns a jQuery object. It takes a selector, which can be a variety of things: something to identify a DOM element by CSS properties (e.g. an equivalent to getElementById) or tag name, a DOM element object itself, or some other rarer cases. An example of jQuery code: $(document).ready(function() { $("div").css({'backgroundColor':'blue'}).append("<img src=\"blah\"/>").show(); }); This example demonstrates two types of jQuery selectors. The first passes the javascript object "document" to the "$" function, and registers an anonymous function to run when the document's ready event fires. The second call, within the anonymous function, selects all div elements in the HTML document, changes the background color to blue via CSS, creates an image and appends it within every div, and then shows the divs (which were perhaps previously hidden with "hide()"). The implementation of jQuery is, from a high level, fairly simple. It creates an object, called jQuery, as a function, and all functionality is programmed into this object. It contains all of the convenience methods of jQuery, which themselves encapsulate handling browser quirks and whatnot. jQuery also includes its own CSS selection engine for filtering and running regexes on the page's style sheets. One interesting aspect of the implementation is that the jQuery object has an "extend" function that can be used to add new fields and methods to the object, and this method is used to modularize the library—for example, AJAX support and animations are included via this type of extension. The library is then made accessible by defining a new field in the existing javascript "window" object—the jQuery object is assigned to and called by "window.$". To get an idea of what this looks like, here's some boiled down pseudocode. var jQuery = window.$ = function(selector) { return new jQuery.prototype.init(selector) } jQuery.prototype = { init: function(selector) { ... }, attr: function ( ... ) { //either get or set HTML attribute values. }, } jQuery.extend = jQuery.prototype.extend = function() { // do some copying. } jQuery.extend({ ajax: function( ... ) { //do ajax stuff! }, ... }); An example for the Animate tool (http://docs.jquery.com/Effects/animate) that shows composition of animations (but only on a single element!) is shown below: $("#go2").click(function(){ $("#block2").animate( { width:"90%"}, 1000 ) .animate( { fontSize:"24px" } , 1000 ) .animate( { borderLeftWidth:"15px" }, 1000); });

Additions and Clarifications to $tween

December 13, 2009

Some questions we had:

1)      It was not clear to me whether you plan to embed this language in javascript, or in jquery or in the 164 language.

We plan on embedding this language into javascript.  The purpose of $tween is not to define new semantics for selecting components, therefore jQuery will still be an integral part of the language.

2)      Please examine the jquery function animate (http://docs.jquery.com/Effects/animate) and argue why your solution is nicer.

We believe that our $tween language is much simpler than jQuery’s “animate” function because of a few reasons:

1 – $tween allows re-use of animations.  Once you define bounce() you can arbitrarily apply it to any part of the dom or compose it with other animations

2- $tween allows composition of animations.

Implementation Details:

There are two steps to animating a dom element.

1 – Define the animation

2 – Attach the animation

For example here are three applications that we’d like to be able to run in the final language:

A simple program showing concatenation.  On clicking the button the div box will simultaneously grow from 100px by 100px to 200px by 140px.

<html>
<head>
<script src=”http://code.jquery.com/jquery-latest.js”></script>

<script>

$(document).ready(function(){

var growWidth = $tween.scaleWidth(“200px”);
var growHeight = $tween.scaleHeight(“1.4x”);
var growBoth = growWidth.and().growHeight;

(“#go”).click(function(){
growBoth(“#block”);
});

</script>
<style>
div {
background-color:#bca;
height:100px;
width:100px;
}
</style>

</head>
<body>
<button id=”go”>» Run</button>
<div id=”block”>Hello!</div>
</body>
</html>

A simple program showing general css property manipulation, animation reuse and composition.  Assuming that many of the engineers that will be animating a site will be the same engineers creating the initial CSS, we allow arbitrary animation of CSS properties.  Also, one div #a bounces left , dev #b bounces up, div #c bounces left and then bounces up, and finally dev #d bounces up and left concurrently

<html>
<head>
<script src=”http://code.jquery.com/jquery-latest.js”></script>

<script>
$(document).ready(function(){

var bounceLeft = $tween({“left”: “-=50px”)).bounce();
var bounceUp = $tween({“top”: “-=50px”)).bounce();

bounceLeft(“#a”);
bounceUp(“#b”);
bounceLeft.and.bounceUp(“#c”);
bounceLeft.then.bounceUp(“#d”);

});
</script>

<style>
div {
position:absolute;
background-color:#abc;
left:50px;
top:50px;
height:90px;
width: 90px;
}
</style>

</head>
<body>
<span id=”result”> </span>
<div id=”a” style=”background-color:blue;”></div>
<div id=”b” style=”background-color:green;”></div>
<div id=”c” style=”background-color:black;”></div>
<div id=”d” style=”background-color:grey;”></div>
</body>
</html>

Our final example program shows the complicated way that tweens can be composed.  One animation bounces the div, while the other one moves it down 200 px.  Both of these animations modify the “top” attribute, but $tween will be able to to both concurrently.

<html>
<head>
<script src=”http://code.jquery.com/jquery-latest.js”></script>

<script>
$(document).ready(function(){

var bounceUp = $tween({“top”: “-=20px”)).bounce(.5);
var moveDown = $tween({“top”: “+=200px”}).linear(5);

$(“#moveAndBounce”).click(
bounceUp.and.moveDown(“.block”);
);

});
</script>
<style>
div {
position:absolute;
background-color:green;
top:50px;
width:90px;
height:90px;
}
</style>
</head>
<body>
<button id=”moveAndBounce”>move</button>
<div></div>

</body>
</html>

Homework 3: JavaScript Toolkit

November 21, 2009

Tweener

Part 1: Problem being solved

The aim of this project is very similar to that of the jQuery javascript toolkit. Toolkits like jQuery exist to ease programming for the web, which is tedious and unwieldy due to conflicting browser standards, ways of manipulating the DOM, and registering and handling events. Our goal is to create a library for javascript that presents the programmer with a simple, consistent, and intuitive way to interact with an HTML/CSS document.

One example of ugly code that a javascript toolkit solves is doing browser checking to determine how to register events. These sorts of problems are common knowledge to web developers that must deal with them on a daily basis. To illustrate this, here’s a link to an article about the difficulty of writing a script that detects the cursor position upon an event:

http://evolt.org/article/Mission_Impossible_mouse_position/17/23335/index.html

Hopefully, our language will provide a wraper for these obnoxious details, so the programmer can simply write something like “event.page_x”.

This problem is absolutely hard. As someone who has written javascript for web pages before, I can say that programming without toolkits is infinitely worse. One is constantly looking up W3C standards and browser support conflicts and wrangling with inconsistent syntax and obscure methods for manipulating the page elements. I think the profusion of javascript toolkits today is enough of a testament to the difficulty of this problem.

There’s no feasible way to circumvent this problem for a web developer. A web developer’s work must be as accessible as possible, meaning a potential user should not be required to have any special program to use a specific page—the web developer must ensure that his work supports all platforms and browsers. This means he must rely on existing languages and techniques for interacting with HTML and CSS, and the only one that is implemented in all web browsers is javascript.

Part 2: A language that currently solves this problem

Since we’ve already compared the goal of our project to the jQuery toolkit, I’ll describe that library.

At the core of jQuery is the “$” function, which returns a jQuery object. It takes a selector, which can be a variety of things: something to identify a DOM element by CSS properties (e.g. an equivalent to getElementById) or tag name, a DOM element object itself, or some other rarer cases.

An example of jQuery code:

$(document).ready(function() {

$(“div”).css({‘backgroundColor’:'blue’}).append(“<img src=\”blah\”/>”).show();

});

This example demonstrates two types of jQuery selectors. The first passes the javascript object “document” to the “$” function, and registers an anonymous function to run when the document’s ready event fires. The second call, within the anonymous function, selects all div elements in the HTML document, changes the background color to blue via CSS, creates an image and appends it within every div, and then shows the divs (which were perhaps previously hidden with “hide()”).

The implementation of jQuery is, from a high level, fairly simple. It creates an object, called jQuery, as a function, and all functionality is programmed into this object. It contains all of the convenience methods of jQuery, which themselves encapsulate handling browser quirks and whatnot. jQuery also includes its own CSS selection engine for filtering and running regexes on the page’s style sheets. One interesting aspect of the implementation is that the jQuery object has an “extend” function that can be used to add new fields and methods to the object, and this method is used to modularize the library—for example, AJAX support and animations are included via this type of extension. The library is then made accessible by defining a new field in the existing javascript “window” object—the jQuery object is assigned to and called by “window.$”.

To get an idea of what this looks like, here’s some boiled down pseudocode.

var jQuery = window.$ = function(selector) {

return new jQuery.prototype.init(selector)

}

jQuery.prototype = {

init: function(selector) { … },

attr: function ( … ) { //either get or set HTML attribute values. },

}

jQuery.extend = jQuery.prototype.extend = function() {

// do some copying.

}

jQuery.extend({

ajax: function( … ) { //do ajax stuff! },

});

Part 3: The features of ‘$tween’

Our language will facilitate easy and clean animation within the dom.  This should mainly be for designers who want to add some extra visual effects to their web application layout.  It should be relatively easy to create interesting visual effects in an intuitive way.  Also, taking into consideration that this is primarily for designers, most defaults are for the ‘common use’ scenario.  Also, with all the languages that front-end developers must remember, $tween should be as easy as possible.  In order to do this, order of adding attributes to a tween is not important and unless some sort of argument is required (such as scale), then default values will be provided if an attribute is added without ()

The easiest way seems to be to abstract the idea of a ‘tween’ or animation, that could just be used as a callback function would be used.  For example a ‘pulse’ tween could be defined

var pulse = $tween.scale(1.2).bounce; //this creates a tween that will scale a dom element 1.2 times its size and back with a bounce-like effect

and then if a certain link should pulse when clicked on simply add

<input type=”button” onclick=”pulse()” value=”Show alert box” />

another example:

var bounce = $tween.yLoc(20).bounce; //this creates a tween that moves a dom element up 20 pixels with a bounce-like effect

and these two effects can be added together in many ways

var bouncePausePulse = $tween.bounce.pause(1).pulse;

var bounceAndPulse = $tween.bounce.and.pulse;

Complicated animations can be build from simpler animations, all which are abstracted to the animation level.  In a rich, interactive environment, most objects will have some sort of roll-over effect and many will share similar roll-over effects, this will make managing and creating these effects easy.

Part 4: Implementation

Creation takes the form of an identifier followed by a series of calls.  A tween object is created using the identifiers:

$tween.

The syntax will allow the designer to specify:

Which attribute to be animated:

yLoc(y) – the desired ‘y’ location

xLoc(x) – the desired ‘x’ location

scale(n) – the desired size of the item

(eventually we could incorporate background/foreground color, border animation, text size, opacity, etc)

Styles or ‘ease’ of animation, with optional arguments for length of time:

‘regular(n)’ [default] – direct move from one position/size to another at a constant rate

‘elastic(n)’ – creates an elastic-like action (quick at first then slowing down)

‘bounce(n)’ – creates a bounce-like action (equivilant to an elastic movement followed by an elastic return)

‘linear(n)’ – tween at a constant rate

‘instantly’ – instantly move or scale

Concatenation operators for connecting tweens:

‘pause(n)’ – pause for a certain amount of time then continue

‘repeat(n)’ – repeat n times (leave out for infinite)

‘then’ – immediately follow previous tween (effectively a pause(0))

‘and’ – do the two tweens concurrently

And always allowing the item to return to the beginning locations with:

‘$return’ – a special tween that will with the original yLoc, xLoc and scale attributes

We envision there being two main types of objects

a tween – what the 2 ‘$’ attributes return ($tween, and $return)

- this is actually a function, but will be seen as an animation, or tween, that can be added to any event

and

- a tween attribute – which is what all the other functions return

there may also be a wrapper class for concatenation operators so that operations such as ‘and.animation1′ does not return a legal function

The internal representation will be a class that builds itself based on attributes added via function calls.  When the tween class receives this object, it will build the necessary callback function.

There will be no interpreter/compiler required, the processing will be building the tween object attribute object and then creating the necessary callback.

debugging can be done via the many JavaScript debuggers available.


Follow

Get every new post delivered to your Inbox.