Wayne Hoover

Full Stack Rails Developer

angularJS and setTimeout 0

I have been working a lot with AngularJS lately, and wanted to share my experience integrating the jQuery isotope plugin with Angular.

This post is spurred my the discussion on the mailing list

In the app I’m currently working on I make isotope and angular work together ultimately by using a technique like this

Basically, I instantiate isotope outside of angular after document.ready in normal jQuery fashion. Inside angular land I use ng-repeat to build my DOM. Since angular builds up the DOM before the document.ready event fires, this works just fine. The only issue is that when I add things to the DOM, I have to tell isotope to update itself. I do this by using $broadcast to trigger an event in the directive that calls the correct isotope function that updates the DOM in isotope fashion.

The key point to notice here is that when I call the isotope function to update the DOM I have to wrap it in $timeout with no delay. Why do we have to do this? Whats so magical about $timeout?

Well, most of the magic that makes two way bindings work in angular happen asynchronously. So what is happening here is that when I want isotope to update the DOM, there is no new DOM elements for it to update yet.

This is the basic flow of events without $timeout

  1. Angular kicks off its code to update the DOM asynchronously.
  2. Isotope DOM update code runs but Angular hasn’t updated the DOM yet.

Here is the basic flow of events with $timeout

  1. Angular kicks off its code to update the DOM async.
  2. Call to isotope DOM update is wrapped in timeout, so its moves to bottom of the async stack
  3. Angular DOM update completes because its next in the async stack.
  4. Isotope DOM update completes with the correct DOM nodes because its last in the async stack (usually, if no other $timeout’s was called)

So basically when you wrap a function in $timeout you push that call to the bottom of the browsers async stack, so in this case the isotope call will be called (hopefully) when angular is done updating the DOM.

This is because in javascript nothing really happens at the same time, there is only one thread, and by calling timeout you can push things to the bottom of that thread. For more on this see here and here.

Ultimately though, I usually don’t like to call $timeout because it feels somewhat hackish, and you can get into trouble if you abuse it and call it in another callback function and forget that code was already moved down the stack.

Sometimes you might figure out a way to not use $timeout, as Max did by just not using ng-repeat like this

In the end I found this solution to be the best for my tastes.

It still uses $timeout but it doesn’t call isotope outside of angular, it keeps everything inside angular which is nice.

Hopefully this was a good explanation of when you might want to use $timeout in places you wouldn’t normally.

Websites I Worked on in 2011

Below is a list of websites I produced in 2011:

Complete Design & Development:

Complete Development:

Maintain:

OpenSource Contributions:

See waynehoover.com/creative for more of my portfolio.

Upload Directly to Amazon S3 With jQuery

I wrote a simple Sinatra app to upload files directly to Amazon S3 using SWFUpload, check it out on GitHub Most of the inspiration (and a lot of the core code) came from Tom Pesman’s post on how to do the same thing, just in rails. I ported Tom’s code to use jQuery and the jQuery swfupload plugin. I also converted most of the views to HAML.

A couple of notes about the code: The ruby code I borrowed from Tom used a couple Rails specific helper functions like ‘hours’ but thankfully these helper functions are all easily accessible in sinatra by including the active_support gem.

Customizing the call back: The javascript now simply POSTs to /upload with the file name uploaded as the data. You will probably want to change this function to pass the whole object, and modify your controller to suite your needs.

Also, you must put the crossdomain.xml file in the root of your S3 Bucket and give it read privileges.

This is my first open source contribution! If you have any questions, ideas on how to make the code better, or even feature requests let me know! Its pretty bare bones right now, maybe I’ll add some styling and some progress indicators later.

The Sinatra App is available on github. It is usses by these libraries:

Ruby: sinatra active_support/core_ext base64

Javascript: jQuery jQuery SWFUpload SWFUpload

Modified Dvorak Keyboard: I U Switch

To make the Dvorak keyboard layout even faster, and to take a que from the Colemak layout, I have created a modified Dvorak keyboard layout.

‘I’ is used far more than ‘U’ so it makes since for me to have I be where U currently is on the Dvorak layout, i.e. right under the left forfinger on the home row.

It took me about a week and a half of using this new layout until I was up to my old speed on the official Dvorak layout. I really like this layout, I move my fingers even less now and type at the same speed!

If you are interested here are the layout files for Mac and PC:

For Mac: Download this file Dvorak-ItoU Mac Place this in /Library/Keyboard Layouts/ and then select it in Settings -> International.

For PC Download this file Dvorak-ItoU PC Open the .exe, it should install fine (Note Vista users might have to run the .exe in XP mode)

Thanks to Code Axe for the inspiration and the tutorial on how to get the custom keyboard working on a PC.

Enjoy!

How to Install APC on a Fresh Ubuntu Install

APC speeds up PHP, and will be built into php6. But before then here is how to install APC on a freshly installed Ubuntu box:

1
2
3
4
5
6
7
8
9
10
apt-get update
apt-get install libpcre3-dev #an APC dependency
apt-get install php5-cli
apt-get install php5-dev
wget http://pear.php.net/go-pear.phar #downloading pear, the php package manager
php go-pear.phar #installing pear
pecl install apc

vim /etc/php5/apache2/php.ini #edit your php.ini and add extension=apc.so
/etc/init.d/apache2 restart #restart apache to reload your php.ini file

test by running <?php phpinfo(); ?>

APC is installed. Enjoy your speedup.