<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4156789181514969150</id><updated>2012-02-15T22:21:08.540-08:00</updated><category term='jquery data'/><category term='jquery'/><category term='comprehensions'/><category term='functions'/><category term='animations stacking'/><category term='refactoring'/><category term='coffeescript'/><category term='callbacks'/><category term='animation'/><category term='classes'/><category term='tutorial'/><title type='text'>CoffeeScript + jQuery tutorials</title><subtitle type='html'>jQuery tutorials implemented in CoffeeScript, CoffeeScript introduction illustrated by jQuery samples - call it what you want. Interactive code snippets running on the lesson pages make you want to dig this stuff!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://coffeequery.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://coffeequery.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Utgarda Loki</name><uri>https://profiles.google.com/107315201864953736669</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-wLpiHDf4dzg/AAAAAAAAAAI/AAAAAAAAAUw/DJbMr48yDrY/s512-c/photo.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4156789181514969150.post-7516016213808604990</id><published>2012-02-01T13:00:00.000-08:00</published><updated>2012-02-04T05:06:03.709-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coffeescript'/><category scheme='http://www.blogger.com/atom/ns#' term='animation'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='callbacks'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery data'/><title type='text'>Lesson 3: Callbacks</title><content type='html'>Last time we spoke of &lt;a href="http://coffeequery.blogspot.com/2012/01/stacking-jquery-animations.html"&gt;stacking animations&lt;/a&gt;, that was fun. But what if you want to start doing something with another element when some animation    is finished? Asynchronous programming comes in handy not only when calling server side. Let's see how callbacks work for jQuery animations.    &lt;p&gt;        Just a few lines of code and we have a MIDI-keyboardish thingie full of colored square keys to click:        &lt;script src="https://gist.github.com/1619170.js?file=midi-keyboard-1.coffee"&gt;&lt;/script&gt;        Yes, they are clickable!    &lt;div id="ani4_palette1" style="height: 80px"&gt;&lt;/div&gt;        Pretty much done already, could employ a couple of swell modern features though. What kind of a midi-keyboard cannot do anything on it's own? Playing sequences after just one touch is a must-have feature, time to code it!        Pressing one key will start off a bunch of pitches, as if we pressed some of them sequentially. When launching an animation on a key, we need         to know which one goes next. We'll link elements using their data field.    &lt;script src="https://gist.github.com/1619170.js?file=midi-keyboard-2.coffee"&gt;&lt;/script&gt;        Have a look at &lt;a href="http://api.jquery.com/jQuery.data/"&gt;jQuery .data&lt;/a&gt;, nice one.        Now that for each element we know who's next, we can enhance the animation function by adding a callback.    &lt;script src="https://gist.github.com/1619170.js?file=midi-keyboard-3.coffee"&gt;&lt;/script&gt;        Callback practice is over, enjoy the result of all this hard work :)    &lt;div id="ani4_palette2" style="height: 80px"&gt;&lt;/div&gt;    &lt;p&gt; Source code links:    &lt;ul&gt;        &lt;li&gt;&lt;a href="http://github.com/utgarda/coffeequery/blob/master/midi-keyboard.html#L1"&gt;MIDI keyboard&lt;/a&gt;        &lt;li&gt;&lt;a href="http://github.com/utgarda/coffeequery"&gt;All lessons&lt;/a&gt;    &lt;/ul&gt;    &lt;p align="right"&gt;&lt;a href = 'http://coffeequery.blogspot.com/2012/01/introducing-classes.html'&gt;Move on to the next lesson!&lt;/a&gt;&lt;/p&gt;&lt;script type="text/coffeescript"&gt;$j = jQuerycolors = [ '#CCDDBB', '#99CC66', '#88AA66'                '#AADDCC', '#66AAAA', '#559999'                '#FFFFDD', '#FF9922', '#DD8822'                '#AACCDD', '#5599CC', '#4477AA' ]nextSquareHtml = (color) -&gt;    """    &lt;div style="background: #{color};             border: 1px solid grey;             height: 30px;             width: 30px;             margin: 5px;             float: left"&gt;&lt;/div&gt;    """grow1 = (square, i) -&gt;    if i&gt;0 and not square.is ':animated'        square.animate(height: 60, 300).animate height: 30, 3000grow2 = (square, i) -&gt;    if i&gt;0 and not square.is ':animated'        square.animate height: 60, 200,                -&gt; grow2 square.data().next, i-1            .animate height: 30fillPalette = (palette, grow) -&gt;    squares = ( $j(nextSquareHtml c) for c in colors )    for s,i in squares        s.appendTo( palette )            .click -&gt;                grow $j(this), 7            .data('next', squares[ (i+1) % squares.length ])fillPalette $('#ani4_palette1'), grow1fillPalette $('#ani4_palette2'), grow2&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4156789181514969150-7516016213808604990?l=coffeequery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://coffeequery.blogspot.com/feeds/7516016213808604990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://coffeequery.blogspot.com/2012/02/lesson-3-callbacks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/7516016213808604990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/7516016213808604990'/><link rel='alternate' type='text/html' href='http://coffeequery.blogspot.com/2012/02/lesson-3-callbacks.html' title='Lesson 3: Callbacks'/><author><name>Utgarda Loki</name><uri>https://profiles.google.com/107315201864953736669</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-wLpiHDf4dzg/AAAAAAAAAAI/AAAAAAAAAUw/DJbMr48yDrY/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4156789181514969150.post-5538610883295757874</id><published>2012-01-15T21:55:00.000-08:00</published><updated>2012-02-13T01:26:36.158-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='comprehensions'/><category scheme='http://www.blogger.com/atom/ns#' term='coffeescript'/><category scheme='http://www.blogger.com/atom/ns#' term='animation'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='classes'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='animations stacking'/><category scheme='http://www.blogger.com/atom/ns#' term='refactoring'/><title type='text'>Lesson 4: Introducing classes</title><content type='html'>&lt;style&gt;    div.tree-frog {border: 1px solid white; height: 38px; width: 38px; position: absolute}&lt;/style&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Suppose we have one state-of-the-art html content representing 5 colorful frogs sitting on a big leaf:&lt;script src="https://gist.github.com/1619170.js?file=leaf-div.html"&gt;&lt;/script&gt;Ok, the markup is bulky, but it still looks great, right?&lt;style&gt;    div.green-leaf div {border: 1px solid white; height: 38px; width: 38px; position: absolute}&lt;/style&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style='margin: 15px; width: 225px; height: 225px'&gt; &lt;div class='green-leaf' style='background:  #458008; position: relative; width: 200px; height: 200px; margin-bottom: 5px' &gt;    &lt;div id='ani3_bar0' style='background: #FF621D; left: 0; top:0'&gt;&lt;/div&gt;    &lt;div id='ani3_bar1' style='background: #B1D02C; left: 0; top:160px'&gt;&lt;/div&gt;    &lt;div id='ani3_bar2' style='background: #D5FA6F; left: 160px; top:160px'&gt;&lt;/div&gt;    &lt;div id='ani3_bar3' style='background: #89C128; left: 160px; top:0'&gt;&lt;/div&gt;    &lt;div id='ani3_bar4' style='background: #B42002; left: 80px; top:80px'&gt;&lt;/div&gt;&lt;/div&gt;&lt;input class='button' id='ani3_select' type='button' value='Select divs'&gt;&lt;input class='button' id='ani3_reset1' type='button' value='Reset'&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;We could select those divs and put them into variables like 'frog1', 'frog2' etc, but we're no kids anymore. Instead, we put them in one place, and use some cool techniques at the same time! &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br/&gt; The first line enumerates the integer range [0..4] and for every n creates an id selector via string interpolation (yep, that #{n} in &lt;span style="color: #d14;"&gt;"#ani3_bar#{n}"&lt;/span&gt; puts in a value ). 5 query results are collected and stored to 'bars' variable. Lookup &lt;a href="http://coffeescript.org/#loops"&gt;Loops and Comprehensions&lt;/a&gt; for more. Short and readable, but it makes 5 id queries instead of one. If we were obsessed with execution speed, that would be bad, so there's a line with a single query too.&lt;br/&gt; Same form of iteration over an array to change every element's attributes. &lt;script src="https://gist.github.com/1619170.js?file=ani3-select-frogs.coffee"&gt;&lt;/script&gt;From now on I'm going to omit some usual stuff, like that line '$j=jQuery' at the beginning of every script, but you know it's there :) &lt;br/&gt;&lt;br/&gt;Now we know how to define functions, let's be nice and provide our frogs with capability to jump around. Check out the four functions' different syntax, meaning totally the same. Pick the flavor that suits you at the moment.&lt;script src="https://gist.github.com/1619170.js?file=ani3-up-down-left-right.coffee"&gt;&lt;/script&gt;Good. Now unleash the frog!&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style='margin: 15px; width: 225px; height: 225px'&gt; &lt;div class='green-leaf' style='background:  #458008; position: relative; width: 200px; height: 200px; margin-bottom: 5px' &gt;    &lt;div id='ani3_bar5' style='background: #FF621D; left: 0; top:0'&gt;&lt;/div&gt;    &lt;div id='ani3_bar6' style='background: #B1D02C; left: 0; top:160px'&gt;&lt;/div&gt;    &lt;div id='ani3_bar7' style='background: #D5FA6F; left: 160px; top:160px'&gt;&lt;/div&gt;    &lt;div id='ani3_bar8' style='background: #89C128; left: 160px; top:0'&gt;&lt;/div&gt;    &lt;div id='ani3_bar9' style='background: #B42002; left: 80px; top:80px'&gt;&lt;/div&gt;&lt;/div&gt;&lt;input class='button' id='ani3_jump_around' type='button' value='Jump around'&gt;&lt;input class='button' id='ani3_reset2' type='button' value='Reset'&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;Wow! It surely is enjoyable to see it frolick. But does it go the right way? &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;Our jumping functions are stackable, cause they accept and return jQuery objects. That's the good part. But the frog goes doesn't start with 'left down right' as somebody less experienced with operations priority concept may expect from our click handler code. The first effective call is on the right, the string should be read like this: &lt;br/&gt;&lt;br/&gt;&lt;code&gt;left(down(right(right(up(up(left(left(down(right(bars2[4]))))))))))&lt;/code&gt; &lt;br/&gt;&lt;br/&gt; We just drop the brackets for the obvious reasons ( like because we can ). &lt;p&gt; Would be nice to have directed jump functions behaving like jQuery animate(), being able to append function calls next to each other and seeing them execute in the same order. For that we need them to return something that also has all four functions inside. ( Instance methods instantly come to my mind, what do you think? )&lt;p&gt; Normally, using just JavaScript, to get many objects behave uniformly we'd need to understand how JS prototypes work. Blessed are those who do. I still find that somewhat tricky. But today we can relax and do it the good old OOP way - define a class. And once again, we'll write less code for that! &lt;br/&gt; &lt;a href="http://coffeescript.org/#classes"&gt;CS classes documentation&lt;/a&gt;, just a friendly reminder :)&lt;p&gt; Ok, lets do it:&lt;script src="https://gist.github.com/1619170.js?file=frog-class-1.coffee"&gt;&lt;/script&gt;&lt;p&gt; Wait, that's not cool. All we did is was wrapping functions code with a class declaration. Yes, we got something by this: now we can queue our jumps more naturally, like &lt;br/&gt;&lt;code&gt;frog.right().down().left()&lt;/code&gt; etc.&lt;br/&gt;But that's just not cool enough. There are reasons to change it:&lt;ul&gt;&lt;li&gt;Code duplication. Four very similar lines of code, with the only defference in animate() arguments.&lt;li&gt;The main asset of every instance is created outside and gets inside as a constructor argument. But, unlike proper decorator implementations, class code relies on the assumption that animated objects are made just the way the class needs to work, without checking it. The class is unseparable from html outside - every time one is updated, the other has to be re-checked.&lt;li&gt;Methods could accept path length. Much gain easily with our new OOP powers.&lt;/ul&gt;&lt;p&gt; To git rid of duplication, let's put all the repeated code in one method, say 'jump', that will accept direction as argument and use predefined arguments for animate(). A key-value map with 'r','l','u','d' for keys should do fine. Then we add another argument to the new jump methods and put animation logic in a loop. Then transform right,left, up and down into convenience methods, each of them now calls jump with proper direction argument. Done. &lt;p&gt; Next - the constructor. Let it accept what varies in those html lines declaring frogs' bodies and inject it into a static html line with string interpolation, then use jQuery to create new element from html, then append it to a container ( another div in our case - the square green leaf ) and store it as the only variable of the newly created class instance. Done. The whole block of html lines flattens to just one, letting us concentrate on frogs' color and position.&lt;p&gt; Looks a bit different:&lt;script src="https://gist.github.com/1619170.js?file=ani3-frog-class-2.coffee"&gt;&lt;/script&gt;&lt;p&gt; Let's see if it works.&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style='margin: 15px; width: 225px; height: 225px'&gt; &lt;div id="leaf" class='green-leaf' style='background:  #458008; position: relative; width: 200px; height: 200px; margin-bottom: 5px' &gt;&lt;/div&gt;&lt;input class='button' id='ani3_long_jumps' type='button' value='4 jumps in a row'&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;Not bad. Readable set of just 4 instructions for each unit, predictable result. In fact, they are so perfectly organized one may even think they are not free-minded lively frogs, but programmed robots!&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt; On the other hand, to heck with direction-named methods, compact path strings are the best for a case like this. Look at this: &lt;script src="https://gist.github.com/1619170.js?file=ani3-frog-class-3-part.coffee"&gt;&lt;/script&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;div style='margin: 15px; width: 225px; height: 225px'&gt; &lt;div id="leaf2" class='green-leaf' style='background:  #458008; position: relative; width: 200px; height: 200px; margin-bottom: 5px'&gt;&lt;/div&gt;&lt;input class='button' id='ani3_round_dance' type='button' value='Round dance!'&gt;&lt;input class='button' id='ani3_reset3' type='button' value='Reset'&gt;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;One character per jump - and still readable. Next would be programming in absolute code! (Just kidding)&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p&gt; Time to stop - it's a bit overdone already. Of course, we love these frisky little creatures, but now it's time to move on to the next adventure!&lt;p&gt; Source code links: &lt;ul&gt;&lt;li&gt;&lt;a href="https://gist.github.com/1619170#file_tree_frogs.html"&gt;Today's research log&lt;/a&gt;&lt;li&gt;&lt;a href="https://gist.github.com/1619170#file_tree_frogs_final.html"&gt;Frog circus - final version&lt;/a&gt;&lt;li&gt;&lt;a href="https://github.com/utgarda/coffeequery"&gt;All lessons&lt;/a&gt; &lt;/ul&gt;&lt;/div&gt;&lt;script type="text/coffeescript"&gt;$j = jQuery#Array comprehension, here it goes!bars = ($j "#ani3_bar#{n}" for n in [0..4])bars2 = ($j "#ani3_bar#{n}" for n in [5..9])#Or could be using CSS id selectors, kinda fast, but has to#be 'jQueryfied' for our needs, i.e. every HTMLDivElement turned to a jQuery object#elements = $j '[id*=ani3_bar]'#bars = ($j(elements.eq i) for i in [0..4])$j('#ani3_select').click -&gt;    b.css('border-color', 'red') for b in bars$j('#ani3_reset1').click -&gt;    b.css('border-color', 'white') for b in barsup = (bar) -&gt; bar.animate(top: '-=40',height: 78).animate height: 38down = (bar) -&gt;    bar.animate        height: 78    .animate        top: '+=40'        height: 38right = (bar) -&gt; bar.animate(width: 78).animate left: '+=40', width: 38left = (bar) -&gt; bar.animate(left: '-=40', width: 78).animate width: 38$j('#ani3_jump_around').click -&gt;    left down right right up up left left down right bars2[4]$j('#ani3_reset2').click -&gt;    bars2[4].stop(true, true).animate( left: 80, top:80, width:38, height:38 )class Frog    constructor: ([color, left, top], leaf) -&gt;        @obj = $j """&lt;div style='background: #{color};        left: #{left}px;        top:#{top}px;        border: 1px solid white;        height: 38px; width: 38px; position: absolute;'&gt;&lt;/div&gt;"""        @obj.appendTo leaf    $aniArgs =        u: [{top: '-=40', height: 78},{height: 38}]        d: [{height: 78},{top: '+=40', height: 38}]        l: [{left: '-=40', width: 78}, {width: 38}]        r: [{width: 78}, {left: '+=40', width: 38}]    jump: (dir, s) -&gt;        @obj            .animate($aniArgs[dir][0])            .animate($aniArgs[dir][1]) for i in [1..s]        this    right: (n) -&gt; this.jump 'r', n    left: (n) -&gt; this.jump 'l', n    up: (n) -&gt; this.jump 'u', n    down: (n) -&gt; this.jump 'd', n    move: (path) -&gt;        @obj            .animate($aniArgs[dir][0])            .animate($aniArgs[dir][1]) for dir in path        thisfrogsData =  [    ['#FF621D', 0, 0]    ['#B1D02C', 0, 160]    ['#D5FA6F', 160, 160]    ['#89C128', 160, 0]    ['#B42002', 80, 80] ]addFrogs = (leaf) -&gt;    ( new Frog( params, leaf ) for params in frogsData )removeFrogs = (frogs) -&gt;    f.obj.remove() for f in frogsfrogs = addFrogs '#leaf'$j('#ani3_long_jumps').click -&gt;    frogs[0].down(4).right(4).up(4).left(4)    frogs[1].right(4).up(4).left(4).down(4)    frogs[2].up(4).left(4).down(4).right(4)    frogs[3].left(4).down(4).right(4).up(4)frogs2 = addFrogs '#leaf2'$j('#ani3_round_dance').click -&gt;    frogs2[i].move(path) for path, i in [        'ddddrrrull'        'rrrulluuur'        'lulluuurrd'        'lldrddlluu'        'dluuurrddd']$j('#ani3_reset3').click -&gt;    removeFrogs frogs2    frogs2 = addFrogs '#leaf2'&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4156789181514969150-5538610883295757874?l=coffeequery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://coffeequery.blogspot.com/feeds/5538610883295757874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://coffeequery.blogspot.com/2012/01/introducing-classes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/5538610883295757874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/5538610883295757874'/><link rel='alternate' type='text/html' href='http://coffeequery.blogspot.com/2012/01/introducing-classes.html' title='Lesson 4: Introducing classes'/><author><name>Utgarda Loki</name><uri>https://profiles.google.com/107315201864953736669</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-wLpiHDf4dzg/AAAAAAAAAAI/AAAAAAAAAUw/DJbMr48yDrY/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4156789181514969150.post-2237012891203083847</id><published>2012-01-13T08:44:00.000-08:00</published><updated>2012-02-01T13:01:42.610-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coffeescript'/><category scheme='http://www.blogger.com/atom/ns#' term='animation'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='animations stacking'/><category scheme='http://www.blogger.com/atom/ns#' term='functions'/><title type='text'>Lesson 2: Stacking jQuery animations</title><content type='html'>&lt;style&gt;    div.tree-frog {border: 1px solid white; height: 38px; width: 38px; position: absolute}&lt;/style&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I feel like making it also a hands-on illustrated introduction to CoffeeScript. But don't forget to check the language overview and coding kickstarter at &lt;a href="http://coffeescript.org/"&gt;coffeescript.org&lt;/a&gt;, cause it's by far the best.jQuery lets you stack animation calls. So, when you want to perform sequential animations on the same page element, one by one, you have a neat interface right for the task!&lt;br /&gt;&lt;br/&gt;Every animation call returns an object that also has 'animate' function. Append animation calls one after another, just the way you want them run. Here's the code:&lt;script src="https://gist.github.com/1607103.js?file=ani.stack.1.coffee"&gt;&lt;/script&gt;&lt;div style='position: relative; width: 510px; height: 80px; background:  #458008'&gt;    &lt;div id='ani2_worm_bar' class = 'tree-frog' style='background: #FF621D; left: 20px; top:20px'&gt;&lt;/div&gt;&lt;/div&gt;&lt;input class='button' id='ani2_go' type='button' value='Go'&gt;&lt;input class='button' id='ani2_reset1' type='button' value='Reset'&gt;&lt;br/&gt;&lt;br/&gt;Let's stack some more. Use more lines if required, don't forget indentation if you do:&lt;script src="https://gist.github.com/1607103.js?file=ani.stack.2.coffee"&gt;&lt;/script&gt;&lt;div style='position: relative; width: 510px; height: 80px; background:  #458008'&gt;    &lt;div id='ani2_worm_bar2' class = 'tree-frog'  style='background: #FF621D; left: 20px; top:20px'&gt;&lt;/div&gt;&lt;/div&gt;&lt;input class='button' id='ani2_gogo' type='button' value='Go Go'&gt;&lt;input class='button' id='ani2_reset2' type='button' value='Reset'&gt;&lt;br/&gt;&lt;br/&gt;CoffeeScript is a modern programming language, outdated programming techniques like code duplication should be avoided. Fortunately, keeping code slim is quite easy, let's define a function:&lt;script src="https://gist.github.com/1607103.js?file=ani.stack.3.coffee"&gt;&lt;/script&gt;&lt;div style='position: relative; width: 510px; height: 80px; background:  #458008'&gt;    &lt;div id='ani2_worm_bar3' class='tree-frog' style='background: #FF621D; left: 20px; top:20px'&gt;&lt;/div&gt;&lt;/div&gt;&lt;input class='button' id='ani2_gogo_cat' type='button' value='Go Go Caterpillar!'&gt;&lt;input class='button' id='ani2_reset3' type='button' value='Reset'&gt;&lt;br/&gt;&lt;br/&gt;Find full sample code behind the link below, save it as html (or clone from github) and play around! (Be careful with auto-formatting in your editor - after inserting code, make sure indentation is preserved)&lt;p&gt; Source code links: &lt;ul&gt;&lt;li&gt;&lt;a href="http://github.com/utgarda/coffeequery/blob/master/caterpillars-all.html#L12"&gt;Caterpillar race&lt;/a&gt;&lt;li&gt;&lt;a href="http://github.com/utgarda/coffeequery"&gt;All lessons&lt;/a&gt; &lt;/ul&gt;&lt;p align="right"&gt;&lt;a href = 'http://coffeequery.blogspot.com/2012/02/lesson-3-callbacks.html'&gt;Move on to the next lesson!&lt;/a&gt;&lt;/p&gt;&lt;script type="text/coffeescript"&gt;    $j = jQuery    $j('#ani2_go').click -&gt;      $j('#ani2_worm_bar').animate(width:78).animate(left:'+=40',width:38)    $j('#ani2_gogo').click -&gt;      $j('#ani2_worm_bar2')        .animate(width:78).animate(left:'+=40',width:38)        .animate(width:78).animate(left:'+=40',width:38)    go = (bar) -&gt;       bar.animate(width:78).animate(left:'+=40',width:38)    $j('#ani2_gogo_cat').click -&gt;      go go go go go go go go go go go $j('#ani2_worm_bar3')    reset = (bar) -&gt;      bar.stop(true, true).animate( left: 20, width:38 )    $j('#ani2_reset1').click -&gt; reset $j('#ani2_worm_bar')    $j('#ani2_reset2').click -&gt; reset $j('#ani2_worm_bar2')    $j('#ani2_reset3').click -&gt; reset $j('#ani2_worm_bar3')&lt;/script&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4156789181514969150-2237012891203083847?l=coffeequery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://coffeequery.blogspot.com/feeds/2237012891203083847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://coffeequery.blogspot.com/2012/01/stacking-jquery-animations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/2237012891203083847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/2237012891203083847'/><link rel='alternate' type='text/html' href='http://coffeequery.blogspot.com/2012/01/stacking-jquery-animations.html' title='Lesson 2: Stacking jQuery animations'/><author><name>Utgarda Loki</name><uri>https://profiles.google.com/107315201864953736669</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-wLpiHDf4dzg/AAAAAAAAAAI/AAAAAAAAAUw/DJbMr48yDrY/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4156789181514969150.post-1113172093455655091</id><published>2012-01-02T13:23:00.001-08:00</published><updated>2012-01-23T12:16:36.611-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='coffeescript'/><category scheme='http://www.blogger.com/atom/ns#' term='animation'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><title type='text'>Lesson 1: jQuery animations are simultaneous</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Hi folks! Inspired by jQuery tutorials on the web, I started porting some of them to &lt;a href="http://coffeescript.org/" target="_blank"&gt;CoffeeScript&lt;/a&gt;, which is, of course, a great source of fun too. I left coffeescript uncompiled so you could easier browse the page code.&lt;br/&gt;Here goes a lesson from &lt;a href="http://wayfarerweb.com/animate-example.php" target="_blank"&gt;Wayfarer's animation tutorial&lt;/a&gt;, mostly unchanged.&lt;p&gt; All animations you start run simultaneously by default, unless you choose to &lt;a href="http://coffeequery.blogspot.com/2012/01/stacking-jquery-animations.html"&gt;stack&lt;/a&gt; them.&lt;br /&gt;&lt;div style="width: 510px; height: 80px"&gt;    &lt;div id="ani1_bar1" style="background: #29AAE1; border: 1px solid white; height: 80px; width: 350px; float: left;"&gt;&lt;/div&gt;    &lt;div id="ani1_bar2" style="background: #333; border: 1px solid white; height: 80px; width: 150px; float: right;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;input class="button" id="ani1_clickme" type="button" value="Click Me!"&gt;&lt;input class="button" id="ani1_restore" type="button" value="Restore"&gt;&lt;script type="text/coffeescript"&gt;    $j = jQuery    clickme = $j '#ani1_clickme'    restore = $j '#ani1_restore'    bar1 = $j '#ani1_bar1'    bar2 = $j '#ani1_bar2'    $j -&gt;        clickme.click -&gt;            bar1.animate {width:150}, 2000            bar2.animate {width:350}, 4000        restore.click -&gt;            bar1.animate {width:350}, 4000            bar2.animate {width:150}, 2000&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Animation in this example is very smooth, because the elements being animated are simple. Be careful, quality is likely to degrade for&amp;nbsp;complex elements.&lt;br /&gt;&lt;br /&gt;jQuery.animate function calls usual form:&lt;br /&gt;&lt;span style="font-family: Verdana, sans-serif;"&gt;&lt;b&gt;jQuery(selector).animate( properties, [ duration ], [ easing ], [ callback ] )&amp;nbsp;&lt;/b&gt;&lt;/span&gt;with properties in [ brackets ] being optional. Using coffeescript you can drop some of the syntax if you like: &lt;script src="https://gist.github.com/1552072.js?file=jquery_animation_1.coffee"&gt;&lt;/script&gt;&lt;p&gt; Source code links: &lt;ul&gt;&lt;li&gt;&lt;a href="http://github.com/utgarda/coffeequery/blob/master/two-bars-resizing.html#L19"&gt;Two bars&lt;/a&gt;&lt;li&gt;&lt;a href="http://github.com/utgarda/coffeequery"&gt;All lessons&lt;/a&gt; &lt;/ul&gt;&lt;p align="right"&gt;Ok, that was too simple, we surely want more fun. &lt;a href = 'http://coffeequery.blogspot.com/2012/01/stacking-jquery-animations.html'&gt;Get to the next lesson!&lt;/a&gt;&lt;/p&gt;&lt;span style="color:rgba(0, 0, 0, 0)"&gt;technorati token D6DWZM9N6BXZ&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4156789181514969150-1113172093455655091?l=coffeequery.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://coffeequery.blogspot.com/feeds/1113172093455655091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://coffeequery.blogspot.com/2012/01/lesson-1-jquery-animations-are.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/1113172093455655091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4156789181514969150/posts/default/1113172093455655091'/><link rel='alternate' type='text/html' href='http://coffeequery.blogspot.com/2012/01/lesson-1-jquery-animations-are.html' title='Lesson 1: jQuery animations are simultaneous'/><author><name>Utgarda Loki</name><uri>https://profiles.google.com/107315201864953736669</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//lh3.googleusercontent.com/-wLpiHDf4dzg/AAAAAAAAAAI/AAAAAAAAAUw/DJbMr48yDrY/s512-c/photo.jpg'/></author><thr:total>0</thr:total></entry></feed>
